설정 파일 전체 구조와 읽는 순서
Clash의 config.yaml은 YAML 형식의 텍스트 파일로, 클라이언트는 시작 시 최상위 필드를 순서대로 읽습니다. 이 파일을 이해하는 가장 좋은 방법은 위에서 아래로 네 구간으로 나누는 것입니다: 공통 설정, DNS 설정, 노드 정의, 전략 그룹 및 규칙.
YAML 문법 규칙은 간단합니다: 들여쓰기는 공백을 사용하고(탭 금지), 같은 레벨의 필드는 들여쓰기를 일관되게 맞춰야 하며, 키와 값 사이에는 영문 콜론과 공백을 넣습니다. 필드 순서 자체는 파싱에 영향을 주지 않지만 proxies, proxy-groups, rules 사이에는 참조 관계가 있습니다: 전략 그룹이 참조하는 노드 이름은 먼저 proxies에 정의되어야 하고, 규칙이 참조하는 전략 그룹 이름은 먼저 proxy-groups에 정의되어야 합니다. 「공통 → DNS → proxies → proxy-groups → rules」 순서로 작성하면 읽기 흐름에도 맞고, 정의되지 않은 이름을 참조해 발생하는 오류도 피할 수 있습니다.
최소한으로 동작하는 설정의 뼈대:
port: 7890
socks-port: 7891
allow-lan: false
mode: rule
log-level: info
dns:
enable: true
nameserver:
- 223.5.5.5
proxies:
- name: "예시 노드"
type: ss
server: 203.0.113.10
port: 443
cipher: aes-256-gcm
password: "example-password"
proxy-groups:
- name: PROXY
type: select
proxies:
- "예시 노드"
- DIRECT
rules:
- DOMAIN-SUFFIX,github.com,PROXY
- GEOIP,CN,DIRECT
- MATCH,PROXY
이 뼈대는 ipv6, external-controller 같은 선택적 필드를 생략했지만, 이미 「시작 → 프록시 경유 → 규칙 분기」의 전체 흐름을 완성할 수 있습니다.
공통 필드: 포트, 모드, 로그
최상위 공통 필드는 클라이언트의 기본 동작을 제어합니다. 아래 표는 가장 자주 쓰이는 항목입니다:
| 필드 | 예시 값 | 기능 |
|---|---|---|
| port | 7890 | HTTP 프록시 수신 포트 |
| socks-port | 7891 | SOCKS5 프록시 수신 포트 |
| allow-lan | false | LAN 장치 연결 허용 여부 |
| mode | rule | 실행 모드: rule / global / direct |
| log-level | info | 로그 레벨: silent / error / warning / info / debug |
| ipv6 | false | IPv6 트래픽 사용 여부 |
| external-controller | 127.0.0.1:9090 | 외부 제어 API 수신 주소 |
mode는 세 가지 값이 가장 헷갈리는 필드입니다. rule 모드는 rules 영역의 규칙을 순서대로 매칭해 첫 번째로 일치하면 전달하며, 일상에서 가장 많이 쓰는 모드입니다. global 모드는 모든 트래픽을 proxy-groups의 첫 번째 전략 그룹으로 보내 rules 매칭을 건너뜁니다. direct 모드는 모든 트래픽을 직접 연결하므로 사실상 프록시를 전역으로 우회하는 것과 같아 노드 장애를 확인할 때 유용합니다.
port와 socks-port는 동시에 수신할 수도 있고 하나만 열 수도 있습니다. 로컬 7890 포트를 다른 프로그램이 사용 중이면 시작 로그에 bind: address already in use가 표시됩니다. 이때 포트를 7897처럼 비어 있는 값으로 바꾸면 됩니다.
external-controller는 RESTful API를 제공하며, Clash Verge의 패널, Yacd, Metacubexd 모두 이 주소로 설정을 읽고 수정합니다. 기본값인 127.0.0.1 바인딩은 로컬에서만 접근을 허용합니다. secret 필드를 설정했다면 API 호출 시 해당 요청 헤더를 함께 보내야 합니다.
log-level은 평소에는 info를 권장하고, 문제를 추적할 때 임시로 debug로 바꾸는 것이 좋습니다. debug는 각 연결의 규칙 매칭 정보를 출력합니다:
[TCP] dial Match(DomainSuffix): github.com → PROXY
[UDP] dial Match(GEOIP): 8.8.8.8 → DIRECT
이런 로그는 트래픽이 어떤 규칙으로 처리되었는지 바로 알려 주므로, 트래픽 분기(라우팅) 디버깅에 가장 효과적인 도구입니다.
DNS 설정 구간: nameserver와 fallback의 역할 분담
dns 구간은 도메인 해석 경로를 결정하며 설정에서 두 번째로 중요한 부분입니다. 핵심 필드는 다음과 같습니다:
| 필드 | 예시 값 | 기능 |
|---|---|---|
| enable | true | 시스템 DNS 대체 여부 |
| listen | 0.0.0.0:53 | DNS 서비스 수신 주소 |
| nameserver | 223.5.5.5, 119.29.29.29 | 기본 해석 서버 |
| fallback | 8.8.8.8, 1.1.1.1 | 예비 해석 서버 |
| fallback-filter | geoip: true | fallback 실행 조건 |
| default-nameserver | 223.5.5.5 | 노드 도메인 해석에 사용할 서버 |
nameserver는 대부분의 도메인을 해석하며, 보통 중국 국내 공공 DNS를 입력합니다. 예를 들어 223.5.5.5(알리바바)와 119.29.29.29(텐센트)는 응답이 빠르고 오염 문제가 없습니다.
fallback은 오염된 도메인을 처리할 때 사용합니다: nameserver가 반환한 IP가 geoip에서 예약 주소로 판정되면 클라이언트는 fallback의 서버로 다시 해석합니다. 간단한 구성이라면 fallback에 8.8.8.8과 1.1.1.1을 넣으면 충분합니다.
여기서 흔히 빠지는 함정이 하나 있습니다: proxies의 노드가 IP 대신 도메인을 사용하면 클라이언트가 노드 도메인을 해석할 때도 dns 구간을 거칩니다. 노드 도메인이 오염되면 모든 노드에 연결할 수 없게 됩니다. 따라서 default-nameserver에는 신뢰할 수 있는 중국 국내 DNS를 반드시 입력하고, 노드 도메인 해석을 fallback 흐름에 맡기지 마세요. TUN 모드에서는 dns 구간의 enable이 true여야 합니다. 그렇지 않으면 TUN을 켠 뒤 시스템 트래픽의 도메인 해석이 제대로 되지 않습니다.
proxies 노드: 프로토콜별 정의 방법
proxies는 배열이며 각 요소가 하나의 프록시 노드를 정의합니다. 서로 다른 프로토콜은 name, type, server, port 네 가지 기본 필드를 공유하고, 프로토콜 전용 필드는 각각 다릅니다.
SS 노드는 필드가 가장 적습니다:
- name: "SS-도쿄"
type: ss
server: 203.0.113.10
port: 443
cipher: aes-256-gcm
password: "your-password"
cipher의 일반적인 값으로 aes-256-gcm, chacha20-ietf-poly1305, 2022-blake3-aes-256-gcm 등이 있습니다. 비밀번호는 구독 서비스 제공자와 일치해야 하며, 다르면 핸드셰이크 단계에서 바로 실패합니다.
VMess 노드는 uuid, alterId와 전송 계층 필드가 추가됩니다:
- name: "VMess-싱가포르"
type: vmess
server: 203.0.113.20
port: 443
uuid: "550e8400-e29b-41d4-a716-446655440000"
alterId: 0
cipher: auto
network: ws
ws-opts:
path: "/path"
headers:
Host: "example.com"
alterId는 최신 서버 구현에서는 보통 0입니다. network가 ws일 때는 ws-opts의 path와 Host를 함께 사용해야 하며, 두 값은 구독 서비스 제공자의 설정과 정확히 일치해야 합니다. 잘못 입력하면 TLS 핸드셰이크 후 터널을 만들 수 없습니다.
Trojan 노드 구조는 VMess와 비슷하지만 uuid가 없습니다:
- name: "Trojan-로스앤젤레스"
type: trojan
server: 203.0.113.30
port: 443
password: "your-password"
sni: "example.com"
skip-cert-verify: false
sni는 TLS의 SNI 확장에 사용되며 인증서 도메인과 일치해야 합니다. skip-cert-verify는 기본값 false이며, 노드 인증서 자체가 유효하지 않고 위험을 감수할 수 있는 경우가 아니라면 true로 바꾸지 않는 것이 좋습니다.
Hysteria2 노드에는 up과 down 대역폭 파라미터가 추가로 필요합니다:
- name: "Hysteria2-홍콩"
type: hysteria2
server: 203.0.113.40
port: 443
password: "your-password"
up: "50 Mbps"
down: "200 Mbps"
sni: "example.com"
up/down은 클라이언트의 가용 대역폭을 선언합니다. 값이 너무 작으면 전송 속도가 제한되고, 너무 크면 혼잡이 발생할 수 있습니다.
proxy-groups 전략 그룹: 선택 로직을 중첩하는 방법
proxy-groups는 전략 그룹을 정의하며, 그룹 내 proxies 목록은 노드를 참조할 수도 있고 다른 전략 그룹을 참조할 수도 있습니다. 자주 쓰는 네 가지 유형:
| 유형 | 동작 | 적합한 상황 |
|---|---|---|
| select | 노드를 수동으로 하나 선택 | 일상용 메인, 수동 전환 |
| url-test | 주기적으로 속도 측정 후 지연이 가장 낮은 노드 자동 선택 | 자동 최적화를 원할 때 |
| fallback | 목록 순서대로 사용, 장애 시 다음 노드로 전환 | 고정 우선순위가 필요할 때 |
| load-balance | 여러 노드에 트래픽을 균등 분배 | 다중 노드 대역폭 통합 |
select 유형이 가장 직관적입니다:
- name: PROXY
type: select
proxies:
- "SS-도쿄"
- "VMess-싱가포르"
- "Trojan-로스앤젤레스"
- DIRECT
- REJECT
url-test는 속도 측정 주소와 간격을 추가로 설정해야 합니다:
- name: Auto
type: url-test
url: "https://www.gstatic.com/generate_204"
interval: 300
tolerance: 50
proxies:
- "SS-도쿄"
- "VMess-싱가포르"
interval 단위는 초이며 300이면 5분마다 한 번 속도를 측정합니다. tolerance는 지연 차이가 50ms 미만일 때 전환하지 않도록 하여 잦은 변동을 방지합니다.
전략 그룹은 중첩할 수 있습니다. 고급 작성법입니다:
proxy-groups:
- name: PROXY
type: select
proxies:
- Auto
- "SS-도쿄"
- DIRECT
- name: Auto
type: url-test
proxies:
- "SS-도쿄"
- "VMess-싱가포르"
여기서 PROXY 그룹의 첫 번째 옵션은 Auto 그룹입니다. Auto를 선택하면 실제 트래픽은 url-test가 자동으로 결정합니다. 중첩 깊이에 대한 엄격한 제한은 없지만, 두 단계를 넘지 않는 것이 좋습니다. 그 이상이면 「지금 어느 노드를 타고 있는지」 추적하기 어려워집니다.
rules 규칙 영역: 매칭 순서가 트래픽 방향을 결정합니다
rules는 설정의 마지막 구간이자 트래픽 분기의 핵심입니다. Clash는 순서대로 규칙을 매칭하며 첫 번째로 일치하면 멈추고 더 아래를 보지 않습니다. 따라서 규칙 순서가 매우 중요합니다.
자주 쓰는 규칙 유형:
| 규칙 접두사 | 매칭 대상 | 예시 |
|---|---|---|
| DOMAIN | 전체 도메인 | DOMAIN,www.google.com,PROXY |
| DOMAIN-SUFFIX | 도메인 접미사 | DOMAIN-SUFFIX,google.com,PROXY |
| DOMAIN-KEYWORD | 도메인 키워드 | DOMAIN-KEYWORD,github,PROXY |
| IP-CIDR | IPv4 대역 | IP-CIDR,192.168.0.0/16,DIRECT |
| GEOIP | 국가 또는 지역 | GEOIP,CN,DIRECT |
| PROCESS-NAME | 프로세스 이름 | PROCESS-NAME,wechat.exe,DIRECT |
| MATCH | 기본(폴백) | MATCH,PROXY |
실제 운영에 사용할 수 있는 rules 예시:
rules:
- DOMAIN-SUFFIX,local,DIRECT
- IP-CIDR,127.0.0.0/8,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT
- IP-CIDR,10.0.0.0/8,DIRECT
- DOMAIN-SUFFIX,cn,DIRECT
- GEOIP,CN,DIRECT
- DOMAIN-SUFFIX,google.com,PROXY
- DOMAIN-SUFFIX,youtube.com,PROXY
- DOMAIN-KEYWORD,github,PROXY
- MATCH,PROXY
위 순서에 주의하세요: 먼저 LAN 및 중국 국내 트래픽을 DIRECT로 보내고, 그다음 해외 도메인을 PROXY로 매칭하며, 마지막에 MATCH로 처리합니다. 만약 DOMAIN-SUFFIX,google.com,PROXY를 GEOIP,CN,DIRECT보다 앞에 두면, google.com의 해석 결과가 중국 국내 IP(예: CDN이 국내 노드로 스케줄링한 경우)라면 잘못 직접 연결될 수 있습니다.
규칙 이름(마지막 필드)은 반드시 proxy-groups에 정의된 그룹 이름이거나 DIRECT, REJECT 두 내장 목표여야 합니다. 존재하지 않는 그룹 이름을 참조하면 설정 검증에서 바로 오류가 납니다.
규칙 순서가 곧 우선순위입니다.Clash는 rules의 첫 줄부터 순서대로 매칭하고, 일치하면 멈춥니다. GEOIP,CN,DIRECT 같은 광범위한 규칙을 DOMAIN-SUFFIX,google.com,PROXY 같은 구체적인 규칙보다 앞에 두면 후자는 영원히 매칭될 기회를 얻지 못합니다.
설정 검증과 흔한 오류
config.yaml을 작성한 뒤 먼저 명령줄로 문법을 검증하고 클라이언트를 시작하면 디버깅 시간을 크게 줄일 수 있습니다. mihomo 코어의 검증 명령:
./mihomo -t -f config.yaml
configuration file ... test is successful 출력이 나오면 통과입니다. Clash Verge의 「설정」→「매개변수 설정」에도 설정 검사 진입점이 있으며, 본질적으로 동일한 검증 로직을 호출합니다.
흔한 오류를 빈도순으로 정리하면:
- 들여쓰기에 Tab을 사용했습니다. YAML은 공백만 인식하므로 편집기에서 「탭을 공백으로 변환」을 켜면 방지할 수 있습니다.
- 콜론 뒤에 공백을 빠뜨렸습니다. port:7890은 포트 필드가 아니라 문자열 키로 해석됩니다.
- 비밀번호 등 특수 문자가 따옴표로 감싸지지 않았습니다. 비밀번호에 #, :, * 같은 문자가 포함되면 반드시 큰따옴표로 감싸야 합니다. 그렇지 않으면 YAML이 주석이나 구조 기호로 해석합니다.
- 정의되지 않은 노드 이름이나 전략 그룹 이름을 참조했습니다. proxies의 name과 proxy-groups의 proxies 목록이 정확히 일치하는지 확인하세요.
- 같은 이름의 노드를 중복 정의했습니다. 나중 정의가 이전 정의를 덮어써서 「설정을 바꿨는데 동작은 그대로」인 듯한 착시를 만들기 쉽습니다.
검증 명령의 출력을 위 목록과 대조하면 대부분의 설정 문제를 5분 안에 찾을 수 있습니다.