ADVANCED CONFIG · 고급 설정
Clash 고급 설정 가이드
정책 그룹, 규칙셋, DNS, TUN, 스니핑, 오버라이드, 외부 컨트롤까지—구독만으로는 채울 수 없는 설정 영역을 7개 장으로 정리하고, 각 장마다 바로 복사해 쓸 수 있는 YAML 예제를 담았습니다.
7개 장 · 필요한 부분만 바로가기 · 예제는 mihomo 코어 필드 기준
이 페이지는 참고용 매뉴얼로, 사용 가이드와는 역할이 다릅니다. 가이드는 0부터 시작해 실제로 쓸 수 있게 만드는 과정—구독 가져오기, 모드 선택, 프록시 검증—을 다루고, 이 페이지는 쓸 수 있게 된 뒤 어떻게 잘 쓸지를 다룹니다. 정책 그룹을 어떻게 구성할지, 규칙셋을 어떻게 구독화할지, DNS가 발목을 잡지 않게 하는 법, TUN을 언제 켤지, 스니핑으로 무엇을 보완할지, 다중 구독을 어떻게 합칠지, 외부 패널을 안전하게 여는 법까지. 7개 장은 서로 독립적이므로 위 목차에서 필요한 부분만 골라 읽어도 됩니다.
예제는 mihomo(Clash Meta) 코어의 YAML 필드를 기준으로 작성했으며, Clash Plus, Clash Verge Rev, FlClash 등 주요 클라이언트는 모두 이 코어를 사용해 해석합니다. 일부 필드는 이미 아카이브된 구버전 Clash 코어에는 없으며, 해당 부분은 본문에서 별도로 표시했습니다. 아직 클라이언트를 설치하지 않았다면 다운로드 센터에서 플랫폼에 맞는 버전을 받으세요. 클라이언트 간 차이와 선택 기준은 클라이언트 비교에서 확인할 수 있습니다.
정책 그룹 유형과 실전 활용
정책 그룹은 Clash 설정의 핵심입니다. 모든 트래픽은 결국 '어느 출구로 나갈 것인가'라는 질문에 답해야 하며, rules가 트래픽을 정책 그룹으로 분류하고 정책 그룹이 출구를 선택하는 구조입니다. 구독에 기본 포함된 정책 그룹은 대개 '노드 선택'과 '자동 선택' 두 가지뿐이라 쓸 수는 있지만 손에 익지 않습니다. 다섯 가지 유형을 제대로 파악해야 '영상은 홍콩, 다운로드는 일본, 장애 시 자동으로 백업 라인으로 전환'처럼 용도별로 분리된 구조를 만들 수 있습니다.
다섯 가지 유형 한눈에 보기
| 유형 | 선택 방식 | 주요 용도 |
|---|---|---|
| select | 사용자가 직접 선택 | 메인 출구, 용도별 출구 |
| url-test | 주기적으로 속도 측정 후 지연 최소값 선택 | 무인 운영용 자동 출구 |
| fallback | 목록 순서대로 사용 가능한 첫 항목 선택 | 메인+백업 페일오버 구성 |
| load-balance | 정책에 따라 연결을 여러 노드에 분산 | 다중 라인 병렬 처리, 단일 라인 부담 완화 |
| relay | 트래픽이 그룹 내 모든 노드를 순서대로 경유 | 전치 중계+착지형 체인 프록시 |
다섯 가지 유형은 서로 중첩할 수 있습니다. 한 정책 그룹의 proxies 항목에 다른 정책 그룹의 이름을 넣어도 됩니다. 실전에서 가장 안정적인 구조는 3단계 구성입니다—용도별 정책 그룹(예: '스트리밍', '다운로드')이 출구 정책 그룹을 가리키고, 출구 정책 그룹이 다시 노드나 url-test 그룹을 가리키며, rules는 용도별 그룹만 참조합니다. 이렇게 하면 출구를 바꿔도 규칙은 그대로, 노드를 바꿔도 출구는 그대로 유지되어 유지보수 부담이 최소화됩니다.
select와 url-test: 수동 결정과 자동 최적화
select는 아무런 검사를 하지 않고 프론트엔드에서 선택한 것을 그대로 사용하므로 최종 결정 단계에 적합합니다. url-test는 interval 주기마다 그룹 내 노드의 지연을 측정해 현재 가장 빠른 곳으로 출구를 전환합니다. 실사용성을 좌우하는 두 파라미터가 있는데, tolerance는 전환 임계값(밀리초 단위)으로, 후보 노드가 현재 노드보다 몇십 밀리초밖에 빠르지 않을 때는 전환하지 않아 비슷한 두 라인 사이에서 출구가 계속 흔들리는 것을 막습니다. lazy를 true로 두면 그룹에 트래픽이 없을 때 측정을 멈춰 불필요한 탐지 요청을 줄입니다.
proxy-groups:
- name: "최종 출구"
type: select
proxies: ["자동 최적화", "수동 지정", "DIRECT"]
- name: "자동 최적화"
type: url-test
use: ["airport-a"]
url: "https://www.gstatic.com/generate_204"
interval: 300
tolerance: 80
lazy: true
- name: "수동 지정"
type: select
include-all: true
filter: "홍콩|HK"
use는 proxy-providers에 등록된 구독을 참조하며, include-all: true를 두면 설정 안의 모든 노드를 그대로 포함하고, filter로 정규식을 걸어 한 번 더 걸러낼 수 있습니다. 세 필드는 함께 사용할 수 있습니다—전체를 포함한 뒤 정규식으로 걸러내고, 구독을 병합하는 순서입니다. 속도 측정 주소는 generate_204처럼 응답 본문이 매우 작은 헬스체크용 주소를 쓰면 됩니다. interval은 120초 이상을 권장하는데, 측정을 너무 자주 하면 그 자체로 상당한 트래픽을 소모하며 일부 서버 업체는 이를 이유로 속도를 제한하기도 합니다.
fallback과 load-balance: 페일오버와 병렬 처리
fallback은 목록 순서를 우선순위로 취급합니다. 헬스체크는 첫 번째 항목부터 시작해 사용 가능한 것을 먼저 사용하며, 메인 라인이 끊기면 자동으로 백업으로 전환되고 메인이 복구되면 다시 되돌아갑니다. '메인 전용선+예비 라인' 구성에 적합하며, url-test보다 사람이 정한 순서를 더 존중합니다. 반대로 load-balance는 단일 라인 최적화를 추구하지 않고 그룹 내 정상 노드 전체에 연결을 분산합니다. strategy가 consistent-hashing이면 같은 대상 도메인은 항상 같은 노드로 해시되어 로그인 상태와 세션이 유지되고, round-robin이면 연결마다 순환하여 처리량은 최대지만 같은 사이트에서도 IP가 바뀔 수 있습니다. mihomo는 이 둘의 절충안으로 sticky-sessions도 제공하는데, 같은 발신 기기를 가능한 한 같은 노드에 붙여둡니다.
- name: "메인/백업 라인"
type: fallback
proxies: ["전용선 입구", "자동 최적화"]
url: "https://www.gstatic.com/generate_204"
interval: 180
- name: "다중 라인 병렬"
type: load-balance
use: ["airport-a"]
strategy: sticky-sessions
url: "https://www.gstatic.com/generate_204"
interval: 300
relay: 체인 프록시
relay는 트래픽이 그룹 내 노드를 순서대로 하나씩 거쳐 나가게 합니다. 대표적인 용도는 '전치 중계+착지'로, 로컬에서 전치 노드까지는 최적화된 라인을 쓰고 전치 노드에서 착지 노드까지는 일반 국제 출구를 써서 안정성과 목적지 지역 출구 특성을 동시에 얻을 수 있습니다. 체인의 각 구간은 각자 대역폭을 소모하고 전체 지연은 각 구간의 합이 되므로 노드는 두 개를 넘지 않는 것이 좋습니다. mihomo에서는 더 가벼운 대안으로 개별 노드에 dialer-proxy를 지정해 어느 전치 노드를 거쳐 나갈지 설정할 수 있어, 별도로 그룹을 만들 필요가 없습니다.
- name: "중계 착지"
type: relay
proxies: ["전치 중계", "미국 착지"]
참고
정책 그룹 이름을 바꾼 뒤에는 rules 안의 참조도 함께 수정해야 합니다. 이름이 일치하지 않으면 해당 규칙은 오류 없이 조용히 무효화됩니다. 헬스체크 주소는 전체 그룹에서 통일해 쓰면 되고, 그룹마다 따로 찾을 필요는 없습니다.
규칙셋 구독 관리
rules에서 rule-providers로
초기 설정에서는 수백, 수천 개의 규칙을 rules 필드에 직접 쌓아 넣었습니다. 읽기도 수정도 어렵고, 구독이 갱신될 때마다 파일 전체가 덮어써져 직접 추가한 규칙까지 사라지곤 했습니다. rule-providers는 규칙을 설정에서 분리해 독립적인, URL로 구독 가능한 규칙셋 파일로 만듭니다. 코어가 시작할 때 다운로드해 로컬에 캐시하고 주기적으로 갱신하며, rules에는 참조 한 줄만 남깁니다. 이제 설정은 두 층으로 나뉩니다—정책 구조는 직접 작성한 YAML에 남고, 규칙 데이터는 자동 갱신되는 규칙셋에 맡겨집니다.
광고 차단, 스트리밍 분리, 내부망 허용 같은 검증된 요구사항은 커뮤니티에서 수년간 관리해온 규칙셋이 이미 있으므로, 직접 하나씩 작성하는 것보다 구독하는 편이 훨씬 안정적입니다. 회사 내부망이나 자체 구축한 서비스처럼 로컬에만 필요한 규칙은 file 타입의 provider로 로컬 파일을 두고, 동일하게 RULE-SET으로 참조해 관리 방식을 통일할 수 있습니다.
선언 형식과 필드
rule-providers:
adblock:
type: http
behavior: domain
format: yaml
url: "https://example.com/rules/adblock.yaml"
path: ./ruleset/adblock.yaml
interval: 86400
lan-local:
type: file
behavior: classical
path: ./ruleset/lan.yaml
type을 http로 두면 url로 구독하고, file로 두면 로컬 파일을 읽습니다. path는 로컬 캐시 위치로, 다운로드가 성공하면 규칙셋이 저장되어 다음 시작 시 먼저 캐시를 읽습니다. interval은 갱신 주기(초 단위)로, 86400이면 하루에 한 번입니다. format은 파일 형식을 지정하는데, yaml은 흔한 리스트 형식, text는 한 줄에 하나씩 적는 순수 텍스트, mrs는 mihomo 전용 바이너리 형식으로 용량이 가장 작고 로딩이 가장 빨라 대형 규칙셋에는 우선적으로 선택하는 게 좋습니다.
세 가지 behavior의 차이
| behavior | 내용 형태 | 매칭 비용 | 적합한 경우 |
|---|---|---|---|
| domain | 도메인 목록만 | 매우 낮음, 해시 매칭 | 광고·추적 도메인 등 순수 도메인 목록 |
| ipcidr | IP 대역만 | 낮음, 프리픽스 매칭 | 지역 IP 대역, 통신사 대역 |
| classical | 규칙 문법이 혼합된 완전한 형태 | 항목별 순차 평가 | 도메인, IP 대역, 포트가 섞인 경우 |
behavior는 코어가 이 파일을 어떻게 해석할지 결정하며, 잘못 지정하면 전체 규칙셋 로딩이 실패합니다. domain 파일에 IP 대역이 섞여 있거나 ipcidr 파일에 도메인이 섞여 있으면 오류가 발생합니다. 서드파티 규칙셋을 구독할 때는 배포 페이지에 표기된 타입을 먼저 확인하고 behavior와 format을 그대로 따라 적어야 하며, 파일명만 보고 추측하면 안 됩니다.
rules에서 참조하기와 갱신 방식
rules:
- RULE-SET,lan-local,DIRECT
- RULE-SET,adblock,REJECT
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,최종 출구
RULE-SET의 두 파라미터는 순서대로 provider 이름과 목적지(정책 그룹 또는 DIRECT, REJECT)입니다. rules는 위에서부터 순서대로 매칭되고 처음 일치한 항목이 적용되므로 순서가 곧 우선순위입니다—로컬 및 차단 규칙을 앞에, 분리 규칙을 중간에, GEOSITE·GEOIP·MATCH를 마지막 방어선으로 둡니다. 위치를 잘못 두는 것이 규칙이 작동하지 않는 가장 흔한 원인으로, MATCH 뒤에 있는 규칙은 절대 실행되지 않습니다.
갱신은 백그라운드에서 이루어집니다. 시작할 때 각 http provider 캐시의 경과 시간을 확인해 interval을 넘으면 비동기로 새로 받아옵니다. 받아오기에 실패하면 기존 캐시를 그대로 사용하므로 규칙이 비워지거나 연결이 끊기지 않습니다. 즉시 갱신하려면 패널에서 해당 provider의 갱신 버튼을 누르거나 path가 가리키는 캐시 파일을 삭제한 뒤 설정을 다시 불러오면 됩니다. GEOSITE와 GEOIP는 별도의 데이터베이스 파일을 사용하며, 갱신 방법은 블로그 《Clash GeoIP·GeoSite 데이터베이스 갱신 방법과 분리 규칙 조합》에서 확인할 수 있습니다. RULE-SET과 혼동하지 않도록 주의하세요.
참고
같은 provider를 여러 rules 항목에서 참조해 각각 다른 정책 그룹으로 보낼 수 있습니다—예를 들어 하나의 스트리밍 도메인 목록을 지역별로 나눠 다른 출구에 분배할 때 구독을 중복할 필요가 없습니다.
DNS 설정 최적화
프록시 클라이언트가 DNS를 직접 처리해야 하는 이유
시스템 기본 DNS는 통신사의 UDP 53 포트를 사용하며 평문이라 조작에 취약합니다. 이는 프록시 효과에 직접 영향을 주는 두 가지 문제로 이어집니다. 첫째는 오염으로, 조회 도중 잘못된 결과가 주입되어 받은 IP로 접속 자체가 안 되는 경우입니다. 둘째는 유출로, 어떤 도메인에 접속했는지가 통신사에 그대로 노출되어 분리 자체가 무의미해집니다. 더 눈에 잘 안 띄는 세 번째 문제는 DNS 결과가 규칙 매칭을 좌우한다는 점입니다—도메인 기준으로 작성된 규칙은 정확한 해석 경로가 먼저 확보돼야 코어가 도메인을 얻을 수 있습니다.
Clash 내장 DNS 서버는 해석 과정을 분리 체계에 편입시키기 위한 것입니다. 국내(중국 본토) 도메인은 국내 DoH로 직접 해석하고, 프록시 도메인은 원격 노드가 대신 해석하며, 노드 서버 자체의 도메인은 전용 리졸버로 처리해 '프록시에 연결해야 프록시 주소를 해석할 수 있는' 순환 문제를 피합니다. dns 필드를 켜는 순간 해석 경로 전체가 코어의 통제 아래 들어옵니다.
필드별 역할
| 필드 | 역할 |
|---|---|
| default-nameserver | 시작 시 DoH·DoT 서버 자체의 도메인을 해석, IP로 지정해야 함 |
| nameserver | 메인 리졸버 그룹, UDP·DoH·DoT·DoQ 지원 |
| proxy-server-nameserver | 노드 서버 도메인 해석 전용 |
| direct-nameserver | 직접 연결 규칙에 일치한 도메인은 여기로 |
| fallback | 예전 필드, 프록시 도메인 해석 그룹(mihomo는 nameserver-policy 사용 권장) |
| nameserver-policy | 도메인 또는 geosite 기준으로 리졸버를 지정, 분리의 핵심 |
바로 사용 가능한 dns 설정 예제
dns:
enable: true
listen: 0.0.0.0:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "time.*.com"
- "ntp.*.com"
- "+.stun.*.*"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
proxy-server-nameserver:
- https://doh.pub/dns-query
nameserver:
- https://doh.pub/dns-query
- https://dns.alidns.com/dns-query
nameserver-policy:
"geosite:cn":
- https://doh.pub/dns-query
"geosite:geolocation-!cn":
- https://1.1.1.1/dns-query
이 설정의 원리는 다음과 같습니다. default-nameserver는 순수 IP로 최후 방어선을 두어 doh.pub, dns.alidns.com 같은 리졸버 자체의 도메인을 먼저 해석합니다. nameserver-policy는 geosite 기준으로 도메인을 두 경로로 나누어 국내 도메인은 국내 DoH로, 그 외는 프록시 쪽 DoH로 보내 원격 노드에서 해석을 마칩니다. proxy-server-nameserver는 노드 도메인만 별도로 처리해 일반 해석과 서로 간섭하지 않습니다. listen은 코어가 1053 포트에서 DNS 서비스를 제공하도록 하며, TUN의 dns-hijack이 시스템 조회를 이곳으로 유도합니다.
enhanced-mode: redir-host와 fake-ip
redir-host는 실제 해석을 수행해 조회를 상위 서버로 전달하고 실제 IP를 반환받는 방식으로 호환성이 가장 좋지만, DNS 왕복이 한 번 더 필요하고 코어가 보는 것은 IP뿐이라 도메인 규칙은 캐시를 역조회해야 합니다. fake-ip는 198.18.0.1/16 대역 내의 가상 주소를 즉시 반환해 앱이 결과를 받는 즉시 연결을 시작할 수 있게 하며, 코어는 앞서 기록한 '가상 주소-도메인' 매핑으로 도메인을 복원해 규칙을 매칭합니다—실제 왕복을 건너뛰어 첫 연결이 더 빠르고 규칙도 도메인 단위로 정확히 매칭됩니다. 대부분의 데스크톱·모바일 환경에서는 fake-ip가 더 나은 선택이며, 실제 IP가 반드시 필요한 서비스는 fake-ip-filter에 등록해 제외해야 합니다. ipv6는 광랜에 IPv6가 할당되지 않은 환경에서는 끄는 것을 권장하는데, AAAA 조회가 전체 해석 속도를 늦출 수 있습니다.
dns 필드를 수정했는데도 적용되지 않는 것은 흔한 의문입니다. 설정을 다시 불러오는 것은 첫 단계일 뿐이며, 운영체제와 브라우저가 각자 이전 해석 결과를 캐시해두었으므로 시스템 DNS 캐시를 지우거나 브라우저를 재시작해야 새 경로가 실제로 적용됩니다.
문제 해결
프록시를 켠 뒤 특정 사이트만 열리지 않고 끄면 정상이라면 대부분 DNS 분리 문제입니다. 먼저 nameserver-policy에서 해당 도메인이 어느 경로로 분류됐는지 확인하고, 그다음 fake-ip-filter에 항목 추가가 필요한지 확인하세요.
TUN과 Fake-IP
TUN이 해결하는 문제
시스템 프록시의 본질은 '앱에 프록시 주소를 알려주는 것'이며 앱이 이를 따르겠다고 해야만 실제로 적용됩니다. 브라우저와 대부분의 오피스 소프트웨어는 문제없지만, 게임, 커맨드라인 도구, 상당수 데스크톱 앱은 시스템 프록시 설정을 그냥 무시해 트래픽이 직접 연결로 그대로 나갑니다. TUN은 다른 경로를 택합니다—코어 안에 가상 네트워크 카드를 만들고 라우팅 테이블을 통해 기기 전체의 TCP·UDP 트래픽을 모두 끌어들이므로 앱은 전혀 신경 쓸 필요가 없습니다. 프록시를 지원할 필요도, 하나씩 설정할 필요도 없습니다.
대가는 권한입니다. 가상 네트워크 카드와 라우팅 테이블은 모두 시스템 수준의 리소스입니다. Windows는 커널 서비스 설치가 필요하고, macOS는 한 번의 권한 승인이 필요하며, Linux는 capabilities나 root 권한이 필요합니다. Clash Plus, Clash Verge Rev 등의 클라이언트는 이 과정을 설정 화면의 스위치 하나로 만들어두어 안내에 따라 한 번만 승인하면 됩니다. Android 클라이언트는 그 자체로 VPNService 형태라 TUN 계층에서 자연스럽게 동작하고, iOS는 시스템 네트워크 확장이 대신 처리해 사용자가 별도로 할 일이 없습니다. 각 플랫폼용 클라이언트는 다운로드 센터에서 운영체제별로 받을 수 있습니다.
tun 필드
tun:
enable: true
stack: mixed
device: Meta
mtu: 1500
dns-hijack:
- any:53
- tcp://any:53
auto-route: true
auto-detect-interface: true
| 필드 | 값 | 설명 |
|---|---|---|
| stack | system / gvisor / mixed | TCP/IP 스택 구현, 아래 설명 참고 |
| device | 네트워크 카드 이름 | 기본값 Meta, 일반적으로 변경 불필요 |
| dns-hijack | 리스닝 주소 목록 | 53 포트 조회를 내장 DNS로 가로채기 |
| auto-route | true / false | 라우팅을 자동 배포해 기기 전체 트래픽을 인계받기 |
| auto-detect-interface | true / false | 물리 출구 네트워크 카드를 자동 인식해 트래픽 루프 방지 |
| mtu | 숫자값 | 기본값 1500, 일부 모바일 네트워크는 1428 부근으로 낮춰야 함 |
stack은 세 가지 중 하나를 선택합니다—system은 운영체제 프로토콜 스택을 직접 사용해 전달하므로 성능이 가장 좋고, gvisor는 사용자 영역 프로토콜 스택으로 연결을 재구성해 호환성이 가장 넓으며 일부 엄격한 네트워크 환경에서 더 안정적입니다. mixed는 TCP는 system, UDP는 gvisor로 처리해 양쪽 장점을 절충하며 대부분 클라이언트의 기본값입니다. auto-route와 auto-detect-interface는 반드시 함께 켜야 합니다—전자는 트래픽을 끌어들이고 후자는 코어 자체의 아웃바운드가 물리 네트워크 카드로 나가도록 보장합니다. 후자가 없으면 루프가 생겨 TUN을 켠 뒤 전체 인터넷이 끊기는 증상이 나타납니다.
Fake-IP의 동작 원리
Fake-IP는 TUN과 짝을 이루는 기능입니다. 앱이 도메인을 조회하면 내장 DNS는 실제 해석을 하지 않고 fake-ip-range(198.18.0.1/16)에서 가상 주소를 하나 할당해 반환하고 가상 주소와 도메인의 매핑을 기록합니다. 앱은 곧바로 그 가상 주소로 연결을 시도하고, TUN이 이를 가로채 매핑을 통해 도메인을 복원한 뒤 도메인 기준으로 규칙을 매칭해 직접 연결할지 노드로 보낼지 결정합니다. 노드로 보낼 때는 도메인을 그대로 전달해 원격에서 해석하므로 로컬에서는 실제 DNS 결과가 전혀 필요하지 않습니다.
이 방식은 두 가지 직접적인 이점을 줍니다—첫 연결이 빠르다는 점(실제 DNS 왕복 한 번을 건너뜀)과 분리가 정확하다는 점(규칙 매칭이 IP가 아닌 도메인 기준으로 이루어짐)입니다. 대가는 '가상 주소만 보이는' 부작용입니다. 로컬 네트워크 서비스, NTP 시각 동기화, STUN NAT 통과, 일부 게임 안티치트, 은행 보안 프로그램은 반드시 실제 IP를 받아야 하므로 해당 도메인은 fake-ip-filter에 등록해야 합니다. filter는 와일드카드를 지원합니다—*.lan은 .lan으로 끝나는 모든 도메인, +.example.com은 메인 도메인과 모든 하위 도메인에 매칭됩니다.
플랫폼별 적용 포인트
Windows에서는 클라이언트의 서비스 모드가 코어를 시스템 서비스로 등록하며 TUN 스위치는 설정 페이지에 있습니다. macOS는 강화 모드를 처음 켤 때 한 번 비밀번호 인증이 필요합니다. Linux 데스크톱 클라이언트도 동일하게 스위치를 제공하며, 명령줄로 mihomo를 직접 실행할 때는 setcap으로 권한을 부여해야 합니다.
sudo setcap 'cap_net_admin,cap_net_bind_service=+ep' /usr/local/bin/mihomo
권한을 부여한 뒤에는 일반 사용자로도 TUN을 실행할 수 있어 항상 root로 실행할 필요가 없습니다. 서버 측 전체 배포 과정은 블로그 《Linux에서 Clash 배포하기: 데스크톱 클라이언트 설치와 mihomo 명령줄 설정》에서 확인할 수 있습니다.
참고
TUN과 시스템 프록시 중 하나만 사용하면 됩니다. 평소 TUN을 쓴다면 시스템 프록시는 따로 켤 필요가 없습니다. TUN을 켠 뒤에는 dns-hijack과 enhanced-mode가 짝을 이루고 있는지 확인하세요—fake-ip 모드에서는 53 포트를 가로채야 해석 흐름 전체가 완성됩니다.
도메인 스니핑
규칙은 도메인을 필요로 하지만 연결에는 도메인이 없을 수 있다
Clash의 규칙 체계는 도메인을 중심으로 돌아가지만, 코어에 도달하는 연결에 도메인이 항상 붙어 있는 것은 아닙니다. 앱이 자체적으로 DNS를 처리하거나 DoH를 내장하거나 이전 해석 결과를 캐시해두거나, 심지어 IP를 하드코딩해두는 경우도 있어 이런 연결은 코어에 들어올 때 목적지 IP만 가지고 있습니다. 도메인이 없으면 DOMAIN, DOMAIN-SUFFIX, GEOSITE는 모두 무효화되고 트래픽은 GEOIP나 MATCH까지 밀려 내려가 분리 정확도가 크게 떨어집니다.
도메인 스니핑은 연결 자체의 핸드셰이크 데이터에서 도메인을 다시 읽어냅니다. TLS 연결의 ClientHello에는 SNI 필드가 있고, 평문 HTTP 요청에는 Host 헤더가 있으며 둘 다 암호화되지 않은 형태로 존재합니다. 코어는 전달하기 전에 핸드셰이크 패킷을 살짝 확인해 도메인을 추출한 뒤 이를 해당 연결에 다시 붙이고, 이후 규칙 매칭은 도메인 기준으로 진행됩니다. TUN이 기기 전체 트래픽을 인계받은 뒤로는 시스템 DNS를 건너뛰는 연결도 모두 코어에 노출되므로 스니핑은 TUN의 필수 짝이 되었습니다.
설정 방법
sniffer:
enable: true
parse-pure-ip: true
override-destination: true
sniff:
HTTP:
ports: [80, "8080-8880"]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
skip-domain:
- "Mijia Cloud"
- "+.push.apple.com"
parse-pure-ip는 순수 IP 연결에도 스니핑을 시도하며, 이것이 스니핑의 주 무대입니다. override-destination은 스니핑으로 얻은 도메인으로 연결의 목적지 주소를 바꿔 redir-host 모드의 연결도 도메인 기준으로 분리할 수 있게 합니다. sniff 아래에서는 프로토콜별로 포트 범위를 지정하며, QUIC은 TCP상의 TLS와 SNI 추출 방식이 달라 별도로 다룹니다. skip-domain은 예외 목록으로, 스니핑하면 이상 동작이 나타난다고 알려진 서비스(일부 푸시 채널, 스마트홈 클라우드 서비스 등)를 등록하면 코어가 해당 도메인에 대해 스니핑을 건너뜁니다.
예외 상황과 문제 해결
스니핑이 모든 것을 해결해주지는 않습니다. ECH(Encrypted Client Hello)를 사용하는 연결은 SNI가 암호화되어 있어 스니핑으로 도메인을 얻을 수 없고 IP 규칙으로 되돌아갈 수밖에 없습니다. 일부 환경에서는 QUIC 스니핑이 영상 사이트 로딩 이상을 일으킬 수 있으므로 QUIC 항목만 따로 지워 확인해볼 수 있습니다. 스니핑은 핸드셰이크 단계에서 몇 개 필드만 읽을 뿐 트래픽을 복호화하지 않으므로 성능 부담은 무시할 수 있는 수준입니다.
Fake-IP와의 관계도 짚어둘 필요가 있습니다. fake-ip 모드에서는 도메인이 DNS 단계에서 이미 코어에 넘어와 있으므로 스니핑이 쓰일 곳은 '앱이 시스템 DNS를 건너뛰는' 일부 상황뿐입니다. redir-host 모드나 순수 IP 직접 연결 상황에서는 스니핑이 분리 정확도의 주된 보장책입니다. 스니핑을 켠 뒤 특정 서비스가 연결되지 않는다면 먼저 그 도메인을 skip-domain에 추가해 확인해보고, 그다음 다른 방향을 점검하세요.
참고
스니핑과 규칙은 대체 관계가 아니라 상호 보완 관계입니다. 도메인 규칙이 완벽할수록 스니핑이 방어해야 할 부담은 줄어듭니다. 반대로 모든 분리를 스니핑에만 의존하면 ECH를 만났을 때 한꺼번에 무력화됩니다.
로컬 오버라이드와 다중 구독 병합
피할 수 없는 모순
기기 구독은 하나의 완전한 YAML로 제공되며, 클라이언트는 주기적으로 갱신하는데 갱신은 곧 전체 교체입니다. 직접 추가한 노드, 손댄 정책 그룹, 조정한 DNS 설정은 다음 갱신 때 모두 사라집니다. 로컬 변경 사항과 구독 내용을 분리해두는 것이 Clash를 장기간 잘 쓰기 위한 전제입니다. 방법은 두 층으로 나뉩니다—다중 구독은 proxy-providers로 모아 노드와 구독 파일을 분리하고, 로컬 수정은 클라이언트의 오버라이드 기능으로 패치와 구독 파일을 분리합니다. 온라인 구독 변환 서비스로 여러 구독을 하나로 합치는 사람도 있지만 이는 구독 주소를 제3자에게 넘기는 대가를 치릅니다. proxy-providers는 같은 일을 로컬에서 처리해 주소가 기기 밖으로 나가지 않습니다.
proxy-providers: 여러 구독을 하나의 노드 풀로 모으기
proxy-providers:
airport-a:
type: http
url: "https://example.com/sub-a.yaml"
path: ./providers/airport-a.yaml
interval: 86400
health-check:
enable: true
url: "https://www.gstatic.com/generate_204"
interval: 300
override:
additional-prefix: "[A] "
airport-b:
type: http
url: "https://example.com/sub-b.yaml"
path: ./providers/airport-b.yaml
interval: 86400
override:
additional-prefix: "[B] "
self-hosted:
type: file
path: ./providers/self.yaml
각 provider는 독립적으로 다운로드, 캐시, 헬스체크를 수행합니다. override.additional-prefix는 해당 구독의 모든 노드 이름 앞에 접두사를 붙여, 두 기기 업체의 이름이 겹치는 경우(어디나 있는 '홍콩 01')에도 서로 덮어쓰지 않고 패널에서도 한눈에 소속을 구분할 수 있게 합니다. filter 필드는 정규식으로 필요한 노드만 골라 받을 수 있는데, 예를 들어 가정용 인터넷 라인만 가져올 수 있습니다. file 타입의 self-hosted에는 직접 구축한 노드를 로컬 파일로 두어 구독 노드와 같은 층위로 풀에 넣을 수 있습니다.
병합한 뒤에는 정책 그룹에서 use로 provider를 참조해 proxies와 함께 섞어 쓸 수 있습니다.
- name: "자동 최적화"
type: url-test
use: ["airport-a", "airport-b", "self-hosted"]
url: "https://www.gstatic.com/generate_204"
interval: 300
클라이언트 오버라이드: 구독에 패치 적용하기
주요 클라이언트는 모두 오버라이드 계층을 제공하며 원리는 동일합니다—구독 YAML을 다운로드한 뒤 사용자가 정의한 패치를 먼저 적용하고 그 결과를 코어에 전달해 적용시킵니다. Clash Plus는 구독 설정 안에 오버라이드 입구를 제공하고, Clash Verge Rev는 Merge(YAML 경로 기준으로 필드 병합)와 Script(스크립트로 자유롭게 다시 작성) 두 방식을 제공하며, FlClash는 오버라이드 설정에서 규칙과 정책 그룹 추가를 지원합니다. 패치로 할 수 있는 일은 다양합니다—전치 규칙 삽입, 정책 그룹 추가, dns 수정, ipv6 끄기 등, 구독이 백 번 갱신돼도 패치는 그대로 유지됩니다.
오버라이드에서 가장 흔히 쓰는 것은 전치 규칙입니다. 클라이언트는 대개 'rules 맨 위에 추가'하는 슬롯을 제공하며, 맨 앞에 있는 규칙이 우선순위가 가장 높아 '회사 도메인은 직접 연결', '특정 사이트는 반드시 특정 출구로' 같은 개인화된 항목을 넣기에 적합합니다. 구독에 원래 포함된 규칙은 손대지 않고 그대로 유지되며, 문제가 생기면 오버라이드를 끄기만 하면 구독 원래 상태로 바로 돌아갈 수 있어 문제 해결 경로가 매우 짧습니다. 구독 가져오기와 모드 선택 같은 기본 과정은 여전히 전제 조건이며, 핵심 단계는 사용 가이드에서 확인할 수 있습니다.
병합 충돌과 유지보수 원칙
다중 구독 병합에서 문제가 자주 생기는 곳은 세 군데입니다. 이름 충돌은 서로 다른 구독의 동명 노드가 중복 제거되거나 나중 것이 앞의 것을 덮어써 발생하며, additional-prefix가 가장 안정적인 해결책입니다. 정책 그룹 동명은 오버라이드에서 추가한 그룹이 구독 기본 그룹과 이름이 같으면 오버라이드가 우선 적용되어 구독 그룹이 대체됩니다—의도한 경우라면 기능이지만 의도치 않은 경우라면 사고입니다. 규칙 순서는 전치 규칙이 구독 규칙보다 우선하므로 지나치게 광범위한 전치 규칙(예: 대량의 IP 직접 연결)을 넣으면 구독의 분리 설정이 무력화될 수 있어 전치 항목은 반드시 정밀하게 작성해야 합니다.
유지보수 측면에서는 로컬 변경 사항을 하나의 오버라이드로 모아 규칙, 정책 그룹, DNS를 집중 관리하고 변경 사항에 주석을 남기는 것을 권장합니다. 구독 갱신이 실패해도 기존 캐시가 남아 있어 노드가 갑자기 사라지지 않습니다. 갱신 실패 시 점검 순서와 자동 갱신 설정 방법은 블로그 《Clash 구독 갱신 실패의 흔한 원인과 자동 갱신 설정 방법》에서 확인할 수 있습니다.
외부 컨트롤 패널
external-controller란
코어가 시작되면 external-controller에 지정된 주소로 RESTful API와 WebSocket 인터페이스 한 세트가 노출됩니다—프록시 조회, 노드 전환, 규칙 확인, 활성 연결 보기, 실시간 로그 수신까지 가능하며, 클라이언트의 그래픽 인터페이스도 본질적으로 이 API를 호출하는 것입니다. 이를 켜고 웹 패널을 연결하면 특정 클라이언트에 얽매이지 않고 어떤 브라우저에서든 실행 중인 코어를 관리할 수 있습니다—라우터에서 돌아가는 mihomo, 서버에서 무인으로 실행되는 인스턴스도 모두 이 경로로 관리합니다.
켜는 방법
external-controller: 127.0.0.1:9090
external-ui: ui
secret: "your-password"
external-controller는 API 리스닝 주소이고, external-ui는 패널 정적 파일 디렉터리를 가리키며 설정을 마치면 http://127.0.0.1:9090/ui 로 패널에 접속할 수 있습니다. secret은 접근 토큰으로 패널 로그인과 API 요청 모두에 필요합니다. 패널 파일은 커뮤니티에서 배포하는 완성된 패키지를 쓰면 됩니다—metacubexd, zashboard, yacd가 모두 안정적인 선택이며 배포 패키지를 받아 ui 디렉터리에 풀어두면 됩니다. 로컬 파일을 두지 않고 패널의 온라인 페이지를 바로 열어 API 주소와 키를 입력해도 되며, 이 경우 브라우저가 로컬 API에 직접 연결합니다.
자주 쓰는 API 한눈에 보기
| 엔드포인트 | 메서드 | 기능 |
|---|---|---|
| /proxies | GET | 전체 프록시와 정책 그룹 상태 |
| /proxies/{name} | PUT | select 그룹의 선택 항목 전환 |
| /proxies/{name}/delay | GET | 지정한 노드의 지연 측정 |
| /rules | GET | 현재 적용 중인 규칙 목록 |
| /connections | GET / DELETE | 활성 연결 조회 및 초기화 |
| /configs | GET / PATCH | 실행 중인 설정 읽기·즉시 수정 |
| /traffic · /logs · /memory | GET(WebSocket) | 실시간 속도, 로그, 메모리 스트림 |
| /version | GET | 코어 버전 정보 |
패널의 모든 기능은 이 엔드포인트들을 기반으로 하며, 직접 스크립트를 작성할 때도 동일하게 호출합니다—주기적으로 속도를 측정해 라인을 전환하거나, 연결 수에 따라 경고를 보내거나, 트래픽을 모니터링 시스템에 연결하는 것 모두 흔히 쓰는 활용법입니다. 명령줄로 확인하려면 요청 헤더 하나만 있으면 됩니다.
curl -H "Authorization: Bearer your-password" http://127.0.0.1:9090/proxies
보안 경계
바인딩 주소는 우선 127.0.0.1로 두어 로컬 접근만 허용하는 것이 기본이자 가장 안전한 형태입니다. 스마트폰으로 라우터의 코어를 관리하는 것처럼 로컬 네트워크 접근이 정말 필요한 경우에는 바인딩 주소를 내부망 주소로 바꾸되 반드시 secret을 설정해야 합니다. 토큰 보호가 없는 API는 같은 네트워크의 누구에게나 프록시 제어권을 넘겨주는 것과 같습니다. 어떤 경우에도 9090 포트를 공용 네트워크에 매핑하거나, 0.0.0.0으로 바인딩한 뒤 방화벽만 믿고 방치해서는 안 됩니다.
secret은 충분히 긴 무작위 문자열을 사용하고, 설정에 적은 뒤 코어를 재시작하면 적용됩니다. 요청 헤더로 전달되며 패널이 기억해두므로 일상적인 사용에서는 신경 쓸 필요가 없습니다. 패널 온라인 버전은 브라우저가 입력한 API 주소에 직접 연결하는 방식이라 키가 제3자 서버를 거치지 않지만, 그래도 신뢰할 수 있는 네트워크에서만 사용하고 사용 후에는 탭을 닫는 것을 권장합니다.
관련 링크
클라이언트는 다운로드 센터에서 플랫폼별로 받을 수 있으며 Clash Plus를 우선 추천합니다. 시작 가이드는 사용 가이드에서, 선택 기준은 클라이언트 비교에서 확인할 수 있습니다. YAML 필드별 상세 설명은 블로그 《Clash 설정 파일 완벽 해설》, 처음 연결했을 때 노드 선택과 프록시 검증 방법은 《Clash 첫 연결 가이드》를 참고하세요.