Clash API가 담당하는 일과 자동 전환의 범위
Clash API를 활용하면 클라이언트 화면을 직접 열지 않고도 현재 프록시 상태를 조회하고, 정책 그룹의 선택 노드를 변경하고, 연결 목록과 커널 로그를 확인할 수 있습니다. 여기서 API는 노드 자체를 새로 만드는 기능이 아니라 실행 중인 Clash 또는 mihomo 커널의 상태와 정책을 제어하는 인터페이스입니다. 따라서 자동 전환을 구성할 때는 먼저 사용할 클라이언트가 외부 컨트롤러를 지원하는지, 실제로 어떤 커널이 실행 중인지 확인해야 합니다. FlClash, Clash Verge Rev, Clash for Android와 mihomo 기반 클라이언트는 메뉴 이름과 지원 범위가 조금씩 다를 수 있습니다.
가장 간단한 자동 전환은 url-test 그룹을 사용하는 방법입니다. 커널이 지정된 URL을 주기적으로 요청해 각 노드의 지연 시간을 측정하고, 조건에 맞는 노드를 그룹의 현재 선택 항목으로 바꿉니다. 반면 외부 스크립트는 여러 그룹을 함께 조작하거나, 특정 HTTP 상태 코드와 패킷 손실을 기준으로 판단하거나, 장애 알림을 보내야 할 때 적합합니다. 두 방식을 섞을 수도 있지만, 커널의 자동 선택과 스크립트의 강제 전환이 서로 다른 기준으로 실행되면 선택 노드가 계속 바뀌는 문제가 생길 수 있습니다.
| 방식 | 판단 기준 | 적합한 상황 | 주의점 |
|---|---|---|---|
url-test |
측정 URL의 응답 시간 | 일상적인 노드 자동 선택 | 한 번의 지연 시간이 실제 전체 품질을 보장하지 않음 |
| 외부 API 스크립트 | HTTP 상태, 연속 실패, 사용자 정의 조건 | 장애 대응과 알림 자동화 | 인증 정보와 중복 실행을 관리해야 함 |
| 수동 전환 | 사용자 판단 | 일시적인 장애나 예외 상황 | 장애가 반복되면 대응이 늦어질 수 있음 |
External Controller를 안전하게 설정하기
외부 컨트롤러는 Clash 커널이 HTTP API 요청을 수신하는 주소입니다. 기본적으로 로컬 컴퓨터에서만 사용할 목적이라면 127.0.0.1:9090에 바인딩하는 것이 가장 안전합니다. 프록시 트래픽을 받는 mixed-port: 7890과 API를 받는 external-controller: 127.0.0.1:9090은 역할이 다릅니다. 브라우저나 스크립트가 API에 접속할 때는 반드시 컨트롤러 포트를 사용해야 하며, 혼합 포트로 API 요청을 보내면 정상적으로 처리되지 않습니다.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
secret: change-this-to-a-long-random-value
secret은 API 요청의 Authorization 헤더에 Bearer 토큰으로 전달합니다. 짧은 문자열이나 다른 서비스에서 재사용하는 비밀번호를 사용하지 말고, 최소 32자 이상의 무작위 값을 생성하는 편이 좋습니다. 설정 파일을 다른 장치와 공유하거나 문제 해결을 위해 로그를 전달할 때는 이 값과 구독 URL의 토큰을 함께 삭제해야 합니다.
LAN 접근이 필요한 경우의 방화벽 확인
휴대전화나 별도의 모니터링 장치에서 API를 호출해야 한다면 컨트롤러를 LAN 주소에 바인딩할 수 있습니다. 예를 들어 0.0.0.0:9090은 모든 네트워크 인터페이스에서 수신하므로 편리하지만, 방화벽과 공유기 환경에 따라 외부에 노출될 위험이 큽니다. 공인 IP에 직접 포트를 열거나, 인증 없는 컨트롤러를 인터넷에 공개해서는 안 됩니다.
external-controller: 192.168.1.20:9090
secret: use-a-unique-random-secret
- 로컬 스크립트만 사용:
127.0.0.1바인딩을 유지합니다. - 같은 LAN의 장치에서 사용: 컴퓨터의 사설 IP에 바인딩하고 운영체제 방화벽에서 필요한 장치만 허용합니다.
- 원격 인터넷에서 사용: API 포트를 직접 개방하지 말고 VPN 또는 인증된 역방향 프록시를 사용합니다.
- 작업이 끝난 뒤: 컨트롤러의 LAN 수신을 끄고 커널을 재시작해 적용 상태를 확인합니다.
url-test 그룹으로 기본 자동 전환 구성하기
정상적인 노드 중 지연 시간이 낮은 항목을 자동 선택하려면 proxy-groups에 url-test 유형을 추가합니다. interval은 측정 주기이며 초 단위입니다. url은 노드가 실제로 접근할 수 있는 안정적인 HTTP 또는 HTTPS 주소를 사용해야 합니다. tolerance는 현재 선택된 노드와 새 측정 결과의 차이가 이 값보다 작을 때 불필요한 전환을 줄이는 완충 범위입니다.
proxy-groups:
- name: 자동 선택
type: url-test
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 80
proxies:
- 서울-01
- 서울-02
- 도쿄-01
- 싱가포르-01
rules:
- MATCH,자동 선택
위 예시에서는 300초마다 각 노드를 검사합니다. tolerance: 80은 측정값이 조금 좋아졌다는 이유만으로 즉시 교체하지 않도록 하는 값입니다. 노드 간 지연 시간 차이가 작고 연결이 안정적이라면 50~100ms 정도의 완충 범위를 고려할 수 있습니다. 반대로 장애 복구를 빠르게 감지해야 한다면 검사 주기를 줄일 수 있지만, 측정 요청이 많아지고 짧은 네트워크 변동에 민감해집니다.
측정 URL과 그룹 구성 점검
- 측정 URL이 특정 지역이나 로그인 세션에 의존하지 않는지 확인합니다.
- 응답 본문보다 빠른 성공 여부가 중요하므로 작은 응답을 반환하는 주소가 유리합니다.
- 프록시 그룹에 실제로 존재하는 노드 이름을 넣어야 하며, 구독 갱신 후 이름이 바뀌면 그룹에서도 제외될 수 있습니다.
- 측정 URL에 접근할 수 없다고 해서 모든 인터넷 서비스가 장애인 것은 아닙니다. 다른 HTTPS 주소로 교차 확인하세요.
- 지연 시간만 낮고 패킷 손실이 많은 노드가 선택되지 않도록 실제 사용 서비스의 접속도 함께 확인합니다.
자동 선택 그룹의 현재 상태는 API로 조회할 수 있습니다. 컨트롤러가 로컬 주소에서 실행 중이고 시크릿을 설정했다면 다음처럼 요청합니다.
curl -s \
-H "Authorization: Bearer change-this-to-a-long-random-value" \
http://127.0.0.1:9090/proxies/자동%20선택
응답에는 그룹 유형, 현재 선택된 now 값, 포함된 노드 목록과 지연 시간 정보가 반환됩니다. 그룹 이름에 공백이나 한글이 있다면 URL 인코딩해야 합니다. 먼저 전체 그룹 목록을 확인하려면 GET /proxies를 사용하고, 특정 그룹의 상세 내용을 확인하려면 GET /proxies/{name}을 사용합니다.
API로 장애 노드 교체하기
수동 또는 스크립트에서 정책 그룹을 변경하는 API는 PUT /proxies/{group}입니다. 요청 본문에 name을 넣으면 해당 그룹의 선택 항목이 바뀝니다. 그룹이 select 유형이거나 외부에서 선택 가능한 정책 그룹이어야 하며, url-test 그룹은 커널의 자동 측정 결과에 의해 다시 선택될 수 있습니다.
curl -X PUT \
-H "Authorization: Bearer change-this-to-a-long-random-value" \
-H "Content-Type: application/json" \
--data '{"name":"도쿄-01"}' \
http://127.0.0.1:9090/proxies/자동%20선택
성공 응답만 보고 작업을 끝내지 말고 바로 다시 조회해 now 값이 바뀌었는지 확인하세요. 노드 이름이 존재하지 않거나 그룹이 선택 가능한 유형이 아니면 오류가 반환될 수 있습니다. 또한 설정을 다시 불러오거나 구독을 갱신하는 과정에서 그룹이 재생성되면 API로 변경한 선택 상태가 초기화될 수 있으므로, 영구적인 기본값은 YAML 설정이나 클라이언트의 오버라이드에 보관해야 합니다.
간단한 장애 대응 스크립트 작성
스크립트는 먼저 API에서 그룹 상태를 읽고, 현재 노드가 연속해서 실패했을 때만 후보 노드로 전환해야 합니다. 한 번의 timeout만으로 즉시 전환하면 무선 네트워크의 순간적인 손실에도 정책이 바뀔 수 있습니다. 다음 예시는 구조를 설명하기 위한 간단한 Python 코드이며, 실제 환경에서는 그룹명과 후보 노드명을 자신의 설정에 맞게 바꿔야 합니다.
import time
import requests
BASE = "http://127.0.0.1:9090"
TOKEN = "change-this-to-a-long-random-value"
GROUP = "자동 선택"
CANDIDATE = "도쿄-01"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
try:
state = requests.get(
f"{BASE}/proxies/{requests.utils.quote(GROUP, safe='')}",
headers=headers,
timeout=5,
)
state.raise_for_status()
data = state.json()
print("현재 선택:", data.get("now"))
# 실제 운영에서는 별도의 연속 실패 카운터를 사용하세요.
response = requests.put(
f"{BASE}/proxies/{requests.utils.quote(GROUP, safe='')}",
headers=headers,
json={"name": CANDIDATE},
timeout=5,
)
response.raise_for_status()
print("전환 완료:", CANDIDATE)
except requests.RequestException as error:
print("API 요청 실패:", error)
운영용 코드에서는 전환 대상이 현재 그룹에 포함되어 있는지 확인하고, 마지막 전환 시각을 파일이나 경량 데이터베이스에 기록하는 것이 좋습니다. 예를 들어 최소 10분의 재전환 간격을 두고, 3회 연속 실패할 때만 다음 노드로 넘어가도록 하면 플래핑을 줄일 수 있습니다. 전환 후에는 동일한 테스트를 한 번 더 실행해 후보 노드도 실패한 경우 세 번째 후보나 수동 선택 상태로 되돌리는 예외 처리가 필요합니다.
로그와 API 응답으로 장애 원인 확인하기
자동 전환이 실행되지 않을 때는 먼저 API 서버 자체가 응답하는지 확인합니다. 401 Unauthorized는 시크릿이 없거나 잘못된 경우가 많고, 404 Not Found는 그룹 이름의 URL 인코딩이나 API 경로가 잘못되었을 가능성이 큽니다. 500 계열 응답은 커널 로그와 현재 설정의 파싱 상태를 함께 확인해야 합니다.
| 증상 | 우선 확인할 항목 | 대응 |
|---|---|---|
| 연결 거부 | 커널 실행 여부, 컨트롤러 포트, 다른 프로세스 사용 여부 | 실제 external-controller 주소와 포트를 확인 |
| 401 응답 | Authorization 헤더와 시크릿 값 |
Bearer 형식과 공백을 점검 |
| 그룹을 찾을 수 없음 | 그룹 이름, 한글·공백 인코딩, 설정 재생성 여부 | GET /proxies로 실제 이름을 다시 조회 |
| 전환 후 곧바로 원복 | url-test 자동 측정, 다른 스크립트, 클라이언트 자동화 |
제어 주체를 하나로 정하고 실행 주기를 조정 |
| 노드는 바뀌지만 접속 불가 | 노드 자체의 TLS, DNS, 인증과 측정 URL 차이 | 실제 목적지 접속과 커널 로그를 별도로 확인 |
FlClash나 다른 클라이언트의 로그 화면에서는 API 요청 결과보다 커널이 노드에 연결할 때 발생한 오류가 더 중요할 수 있습니다. dial tcp timeout, connection reset, TLS 인증서 오류, DNS 조회 실패는 각각 다른 조치를 요구합니다. 로그 레벨을 장시간 debug로 유지하면 민감한 호스트명과 연결 정보가 많이 남을 수 있으므로, 재현에 필요한 짧은 시간만 높이고 평소에는 info 수준을 사용하는 편이 안전합니다.
최종적으로는 다음 순서로 점검하세요. 첫째, 컨트롤러 주소와 인증 헤더로 API에 접근할 수 있는지 확인합니다. 둘째, /proxies에서 그룹과 후보 노드가 실제로 존재하는지 확인합니다. 셋째, 그룹 상세 응답의 now와 지연 시간 정보를 확인합니다. 넷째, 수동 PUT 전환을 실행하고 다시 조회합니다. 마지막으로 스크립트의 연속 실패 조건과 실행 주기를 적용합니다. 이 순서를 지키면 API 문제, 그룹 설정 문제, 노드 네트워크 문제를 한꺼번에 추측하지 않아도 됩니다.