왜 “Sniffer”가 필요할까요?
Clash Meta 계열(mihomo 코어)에서 분류 규칙은 기본적으로 “이 연결이 어느 호스트인가?”를 알아야 DOMAIN·DOMAIN-SUFFIX 같은 조건에 걸립니다. 그런데 실제 트래픽은 처음부터 도메인 문자열을 들고 오지 않는 경우가 많습니다. 특히 TLS 1.3 암호화 연결은 초기 핸드셰이크에 SNI(Server Name Indication)로 목적 호스트를 밝히지만, 코어가 그 전 단계에서 목적지를 “IP 주소 하나”로만 본다면 규칙 엔진은 IP-CIDR·GEOIP 쪽으로만 미끄러지기 쉽습니다.
HTTP/3가 쓰는 QUIC(보통 UDP 443)도 비슷한 딜레마가 있습니다. 브라우저·앱이 QUIC을 켜 두면, 웹 페이지는 빨라지지만 코어 입장에서는 “UDP로 나가는 한 덩어리”에 가깝게 보입니다. 이때 Sniffer가 초기 패킷에서 호스트 정보를 읽어 내면, 사용자가 이미 작성해 둔 분류 규칙이 다시 의미를 갖습니다. 반대로 Sniffer를 끈 채 DOMAIN 규칙만 늘려도, 해당 트래픽이 IP 기준으로 먼저 결정되면 체감상 “규칙이 안 먹는다”고 느끼게 됩니다.
이럴 때 Sniffer·QUIC·SNI 조합을 의심하세요
대표적인 패턴은 다음과 같습니다. 브라우저에서는 특정 사이트만 엉뚱한 노드로 나가고, 나머지는 정상이다. 앱은 웹보다 더 자주 QUIC을 켜 두어 증상이 “앱에서만” 드러난다. 로그나 연결 패널에서 목적지가 도메인이 아니라 IP로만 찍힌다. 혹은 GEOIP나 광범위한 MATCH에 먼저 걸려, 세밀한 DOMAIN-SUFFIX 규칙까지 손이 닿지 않는다.
물론 모든 문제의 원인이 Sniffer는 아닙니다. DNS가 fake-ip·redir-host와 맞지 않거나, TUN과 시스템 프록시가 섞여 경로가 갈라지면 비슷한 증상이 납니다. 그래서 본문에서는 Sniffer를 켠 뒤에도 남는 경우를 대비해, TUN 모드 가이드와 분류 규칙 심화 글과 짝을 이루는 점검 순서를 함께 제시합니다.
전제: 코어·모드·로그
Sniffer는 Clash Premium이 아니라 Meta / mihomo 계열에서 다루는 기능입니다. GUI 클라이언트 이름은 FlClash, Verge, ClashX Meta 등 제각각이지만, 실제로는 같은 코어가 config.yaml(또는 프로필)의 sniffer: 블록을 읽습니다. 먼저 사용 중인 빌드가 Meta 계열인지 확인하세요.
모드 측면에서는 TUN이나 redir처럼 “패킷을 코어가 받아 처리하는 경로”에서 Sniffer가 더 잘 드러나는 편입니다. 순수 시스템 HTTP 프록시만 쓰는 환경에서도 TLS 연결은 중간에 끼어 들 수 있지만, 증상이 앱 전체 트래픽에 퍼져 있다면 TUN 쪽 설정을 먼저 정돈하는 편이 낫습니다. TUN의 DNS 가로채기·라우팅 개념은 해당 튜토리얼을 참고하세요.
설정을 바꿀 때는 로그 레벨을 잠시 올려 두고, 연결 이름에 도메인이 붙는지·여전히 IP로만 남는지를 확인하면 학습 곡선이 짧아집니다. 다만 로그에는 민감한 호스트가 찍힐 수 있으니, 공유·캡처 시에는 마스킹하는 습관을 들이세요.
설정 파일에서 Sniffer 켜기 (예시)
아래는 이해를 돕기 위한 예시입니다. 포트 목록·스니핑 대상 프로토콜은 환경과 코어 버전에 맞게 조정해야 하며, 구독이 덮어쓰는 경우 로컬 merge나 GUI의 “프로필 편집” 우선순위를 확인하세요.
# Illustrative snippet — adjust ports and keys per your mihomo build
sniffer:
enable: true
sniff:
TLS:
ports:
- 443
- 8443
QUIC:
ports:
- 443
HTTP:
ports:
- 80
- 8080-8880
force-dns-mapping: true
parse-pure-ip: true
override-destination: false
핵심은 TLS와 QUIC에 대해 “어느 포트에서 패킷을 들여다볼지”를 지정하는 것입니다. HTTP는 평문이 남는 환경에서만 의미가 있으며, 실제 서비스 대부분은 443에서 끝나므로 TLS·QUIC이 본론입니다. force-dns-mapping·parse-pure-ip는 DNS 모듈과의 연계를 강화하는 옵션으로, fake-ip를 쓰는 구성에서 규칙 일관성을 높이는 데 도움이 될 수 있습니다. 다만 이 조합은 DNS 섹션과 함께 설계해야 하므로, 한쪽만 복사해 붙이면 역효과가 날 수 있습니다.
override-destination: 언제 true, 언제 false?
override-destination는 “스니핑으로 얻은 호스트명을, 이후 규칙 매칭을 위해 목적지 표현에 반영할지”에 가깝게 이해하면 됩니다. false로 두면 실제 패킷의 목적지 IP는 유지하고, 규칙 엔진 쪽에서만 도메인 힌트를 쓰는 흐름에 가깝습니다. true는 동작이 공격적으로 바뀌어, 특정 아웃바운드·호환 시나리오에서 예상 밖의 경로가 나올 수 있어, 처음에는 false에서 시작해 증상을 보며 조정하는 편이 안전합니다.
어떤 구독 템플릿은 이미 Sniffer 블록을 포함하고, override-destination: true로 박혀 있기도 합니다. “남이 준 설정”을 그대로 쓰다 보면 이 값만 바꿔도 증상이 달라지는 경우가 있으니, 로컬에서 의도한 값을 명시적으로 고정해 두는 것을 권합니다.
SNI를 살려 DOMAIN 규칙에 걸리게 하기
Sniffer가 제 역할을 하면, 연결 메타데이터에 example.com 같은 문자열이 붙고 DOMAIN-SUFFIX,example.com,MY_GROUP 규칙이 상단에 있다면 그 그룹으로 떨어져야 합니다. 여기서 자주 터지는 실수는 규칙 순서입니다. MATCH나 지나치게 넓은 GEOIP가 위에 있으면, 아래쪽 DOMAIN 규칙은 평생 실행되지 않습니다.
또 하나는 서브도메인입니다. CDN 앞단이 cdn.vendor.net이고 본문 규칙은 vendor.net만 묶어 두었다면, 의도와 다르게 매칭될 수 있습니다. 이럴 때는 실제 캡처한 호스트를 기준으로 DOMAIN을 세분화하거나, 공식 문서·개발자 도구의 네트워크 탭으로 “어떤 호스트가 443을 쓰는지”를 먼저 모읍니다. 규칙 타입별 우선순위와 전략 그룹 패턴은 규칙 심화 글과 함께 보세요.
# Example: put specific DOMAIN rules above broad GEOIP / MATCH
rules:
- DOMAIN-SUFFIX,cdn.example.com,PROXY_A
- DOMAIN-SUFFIX,api.example.com,PROXY_B
- GEOIP,KR,DIRECT
- MATCH,PROXY_FALLBACK
QUIC(HTTP/3)와 UDP 443
QUIC은 TCP가 아니라 UDP 위에서 동작합니다. 그래서 “TCP 프록시만 잘 되면 된다”는 가정이 깨지면, 브라우저가 자동으로 HTTP/3로 올라간 사이트에서만 이상이 생기기도 합니다. Sniffer에서 QUIC 항목을 켜 두면, 초기 패킷에 실린 연결 정보를 바탕으로 호스트 추론이 가능해져 DOMAIN 규칙이 QUIC에도 적용될 여지가 생깁니다.
그러나 모든 QUIC 스택이 동일하게 스니핑 친화적이지는 않습니다. 클라이언트·서버 구현, ECH(암호화된 ClientHello) 도입 여부, 중간 장비의 UDP 차단 등은 변수입니다. 즉 Sniffer는 만능 열쇠가 아니라 “공식적으로 제공하는 힌트를 최대한 살리는 장치”에 가깝습니다. QUIC을 끄면(브라우저 실험 플래그나 일부 앱 설정) 증상이 사라진다면, 원인 후보를 Sniffer·UDP 경로 쪽으로 좁힐 수 있습니다.
게임·실시간 음성처럼 지연에 민감한 UDP와 Web QUIC이 같은 포트 대역을 쓰면 혼란이 생깁니다. 이때는 해당 트래픽을 DIRECT로 빼는 규칙을 앞에 두는 전략이 여전히 유효합니다. 게임 UDP 점검 흐름은 게임·음성 튜토리얼과 교차해서 읽으면 좋습니다.
DNS·fake-ip와 한 세트로 맞추기
Sniffer만 켜고 DNS가 뒤죽박죽이면, “도메인은 맞는데 IP 규칙이 엇갈린다”는 형태로 다시 깨질 수 있습니다. 특히 fake-ip 모드에서는 도메인→가짜 IP 매핑이 규칙 평가 순서와 맞물리므로, fake-ip-filter에 넣을 호스트와 nameserver 폴백 순서를 함께 봐야 합니다.
운영 팁으로, 변경은 한 번에 한 가지씩입니다. Sniffer on → DNS nameserver 순서 조정 → TUN DNS hijack 확인처럼 단계를 나누면, 어느 레이어에서 증상이 바뀌는지 기록하기 쉽습니다. 기능 개요를 넓게 보고 싶다면 문서 개요도 함께 참고하세요.
skip-domain / force-domain (있을 때)
일부 버전·템플릿에는 skip-domain·force-domain(또는 유사 이름)으로 스니핑 예외를 지정하는 필드가 있습니다. 은행·사내 포털처럼 ClientHello 검사 자체가 민감한 서비스는 스니핑을 건너뛰도록 목록에 넣는 사례가 있고, 반대로 특정 도메인만 강제로 스니핑하도록 좁히는 경우도 있습니다.
키 이름은 릴리스 노트를 따라가며 확인하는 것이 안전합니다. 구독이 오래된 스니펫을 들고 있으면 새 코어에서 키가 바뀌었는데도 조용히 무시되는 일이 생기므로, 업그레이드 후에는 mihomo 마이그레이션 가이드와 릴리스 노트를 한 번씩 대조하세요.
켰는데도 안 맞을 때 체크리스트
- 코어 확인: Meta/mihomo인지, Sniffer 지원 빌드인지.
- 프로필 병합: GUI가 생성한 최종 YAML에
sniffer가 실제로 들어갔는지. - 규칙 순서: 세부 DOMAIN이 넓은 MATCH·GEOIP보다 위인지.
- DNS: fake-ip·redir-host·TUN DNS hijack이 서로 모순 없는지.
- QUIC: 브라우저·앱에서 HTTP/3만 문제인지(비교 실험).
- ECH·프라이버시 기능: SNI가 가려지면 스니핑 힌트가 줄어든다는 전제를 기억할 것.
- 다른 VPN·필터: TUN 스택이 둘 이상 겹치면 스니핑 이전에 패킷이 변형될 수 있음.
이 목록을 끝까지 확인했는데도 특정 앱만 남는다면, 앱이 커스텀 인증서 고정·비표준 TLS·자체 QUIC 스택을 쓰는지 조사하는 단계로 넘어갑니다. 이때는 Clash만으로 해결이 어려울 수 있어, 앱별 우회(분할 터널, 기업 정책 준수 범위 내 DIRECT)를 고려해야 합니다.
프라이버시·정책·합법 사용에 관해
Sniffer는 로컬에서 패킷 헤더를 읽어 라우팅 결정을 돕는 기능입니다. 그러나 조직망·학교망·타인의 장비에서는 네트워크 정책을 위반할 수 있으니, 허용된 환경에서만 사용해야 합니다. 본문은 기술 설명을 목적으로 하며, 특정 서비스를 우회하도록 독려하는 내용이 아님을 분명히 합니다.
정리: Sniffer는 “도메인 규칙을 다시 읽게 하는 스위치”
Clash Meta Sniffer는 SNI와 QUIC이 주는 힌트를 살려, IP만 보이던 연결을 다시 도메인 기반 분류 규칙 아래로 가져오는 공식적인 수단입니다. TUN·DNS·규칙 순서와 세트로 맞추면, “대부분은 맞는데 몇몇 사이트만 노드가 이상하다”는 증상을 줄이는 데 실질적으로 도움이 됩니다. 반대로 Sniffer 하나만 켠다고 모든 QUIC 문제가 사라지는 것은 아니므로, 위 체크리스트를 습관화해 두면 같은 증상이 다시 와도 진단 시간이 짧아집니다.
GUI가 다른 여러 클라이언트 가운데에서도, 코어가 mihomo라면 설정 표현은 크게 다르지 않습니다. 최신 빌드와 문서를 한 화면에서 맞춰 보고 싶다면, 아래 링크에서 받은 뒤 프로필에 sniffer 블록을 직접 확인해 보세요. 다른 도구에 비해 규칙·DNS·TUN을 한 코어에서 다루는 흐름이 정돈되어 있어, 이런 미세 튜닝에 시간을 덜 쓰게 되는 편입니다.
→ Clash 공식 클라이언트 무료 다운로드 — 최신 클라이언트에서 프로필을 열고 Sniffer·DNS·TUN을 함께 점검해 보세요.