1. 증상: DNS만 병목인지 가르기
웹사이트가 열리긴 하는데 주소를 친 직후 한참 멈춘 뒤에야 화면이 채워질 때, 브라우저 개발자 도구 네트워크 탭에서 DNS 조회(lookup) 구간이 유난히 길게 찍히는 경우가 있습니다. 또는 한두 도메인만 알 수 없는 IP 대역을 받아 로그인 페이지가 엇나가거나, 실제로는 국내 사용자를 타깃으로 하는 서비스인데 해외 에지로 튕겨 지연이 커지기도 합니다. 이런 패턴은 TCP 레벨의 SYN 재시도보다 먼저 이름 해석 경로를 봐야 이익인 경우가 많습니다.
Clash를 끄거나 시스템 DNS만 바꿨을 때 증상 같이 따라가면, 병목이 Clash dns: 블록과 그 위·아래(시스템, 라우터, 다른 VPN) 중 어디인지 가늠하기 쉽습니다. 반대로 Clash를 통하지 않는 앱은 정상인데 Clash를 켠 앱만 이상하면, 우선 로컬 리스너와 업스트림 목록부터 의심하는 편이 낫습니다. WSL2나 Docker처럼 겹친 스택에서는 호스트와 게스트가 서로 다른 nameserver 줄을 보고 있어도 증상이 비슷하게 보일 수 있으니, 측정 위치를 항상 같게 맞추는 습관이 필요합니다.
2. nameserver와 fallback이 하는 일
대부분의 Clash·Mihomo 계열 문맥에서 nameserver는 기본 DNS 질의를 맡깁니다. 여기서 받은 응답이 빠르고 정직하면 그대로 쓰고, 느리거나 의심스러운 응답이 감지되면 fallback에 등록한 서버로 같은 질의를 다시 보내는 식의 이중 구조를 많이 씁니다. fallback-filter는 언제 두 번째 줄로 넘길지, 어떤 IP 대역·GeoIP 규칙으로 오답을 걸러낼지를 정의합니다. 한 줄로 요약하면 nameserver는 일상용 대열, fallback은 재검증 대열에 가깝습니다.
nameserver-policy(또는 구성에 따라 이에 상응하는 필드)는 특정 접미사·지오사이트 묶음을 지정 서버로만 보내고 싶을 때 씁니다. «국내 도메인은 국내 친화 리졸버, 나머지는 해외 DoH»처럼 질의 출발지를 먼저 갈라 놓으면 fallback이 과하게 돌거나, 반대로 한 업스트림에만 의존해 오염되기 쉬운 상태를 줄일 수 있습니다. 키 이름과 중첩 규칙은 코어 버전마다 조금씩 다르므로, 적용 전에 공식 문서의 DNS 절을 열어 두고 대조하는 것이 안전합니다.
| 구간 | 역할 |
|---|---|
| nameserver | 기본 질의. 지연·가용성이 좋은 서버를 앞에 두는 편이 일반적입니다. |
| fallback | 필터 조건을 만족하면 같은 이름에 대해 재질의해 비교·대체하는 용도입니다. |
| fallback-filter | GeoIP, ipcidr, 도메인 패턴 등으로 «이 응답은 신뢰하기 어렵다»를 정의합니다. |
| nameserver-policy | 일부 접미사만 특정 리졸버로 보내 국내외·사내·스트리밍 등 회선을 분리합니다. |
3. 단계 1: dns.enable·리스너·enhanced-mode
YAML 맨 아래에 붙어 있는 작은 dns: 블록을 가정해 보겠습니다. 먼저 enable: true인지 확인합니다. 꺼져 있으면 앱이 시스템이 주는 경로를 그대로 쓰거나, 반대로 혼합 모드에서 기대와 다른 스택이 열리는 경우가 있습니다. 클라이언트 UI에 «시스템 DNS 사용» 같은 토글이 따로 있다면 YAML과 둘 다 같은 의도인지 맞춥니다.
listen 주소는 LAN 공유나 TUN 연동 시 충돌이 잦은 부분입니다. 이미 다른 서비스가 같은 포트를 쓰고 있으면 Clash 쪽 리스너가 올라오지 않거나, 조용히 다른 경로로 빠져 버립니다. 방화벽에서 UDP 53·TCP 53·혹은 지정한 DoH 프록시 포트가 막혀 있지 않은지도 함께 봅니다.
enhanced-mode가 fake-ip인지 redir-host인지에 따라 같은 nameserver라도 애플리케이션이 보는 답이 달라집니다. fake-ip는 연결 직전까지 가짜 주소를 보여 주는 경향이 강하고, 필터 목록과 세트가 맞지 않으면 일부 도메인만 이상하게 보이기도 합니다. DNS만 손보기 전에 모드를 고정해 두고, 그 전제에서 아래 단계를 진행하는 것이 혼선이 적습니다.
4. 단계 2: nameserver 구성
nameserver 목록에는 보통 UDP, TLS(DoT), HTTPS(DoH) 형식이 섞입니다. 회사망·캠퍼스·일부 통신사에서는 특정 DoH 호스트가 필터링되어 간헐 타임아웃만 남기고, 겉으로는 «Clash가 불안정하다»로 오인됩니다. 이럴 때는 같은 리졼에 있는 다른 엔드포인트나 DoT로 바꿔 A/B 해 보는 것이 빠릅니다.
목록을 늘일수록 이론상 견고해지지만, 동시 다발 질의가 늘면 지연도 함께 늘 수 있습니다. 실무에서는 2~3개의 신뢰할 만한 업스트림을 두고, nameserver-policy로 분기하는 편이 관리에 유리합니다. 아래는 구조만 보여 주는 예시이며, 호스트·경로는 사용 중인 코어 문서와 정책에 맞게 바꿔야 합니다.
dns:
enable: true
listen: 0.0.0.0:53
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- https://dns.example-a.net/dns-query
- tls://dns.example-b.net
# Add GeoIP / routing-aware resolvers per policy below
dns: 블록이 중복 병합되면 나중에 온 항목이 이전 항목을 덮어쓸 수 있습니다. 편집 후에는 반드시 실제로 로드된 설치 본문(프리뷰·내보내기)을 확인하세요.
5. 단계 3: fallback과 fallback-filter
fallback은 «첫 응답이 필터에 걸리면」 혹은 «일정 조건의 질의에 한해» 발동합니다. 지나치게 공격적인 fallback-filter는 정상 응답까지 재질의하게 만들어 체감 지연만 키울 수 있고, 반대로 느슨하면 오염된 답을 그대로 받아 쓰게 됩니다. GeoIP 코드·ipcidr 블록이 템플릿 그대로 복사되어 있지 않은지, 본인의 거주·회선과 맞는지를 한 번씩 점검하는 것이 좋습니다.
일부 사용자는 fallback에만 해외 신뢰 리졸버를 두고 nameserver에는 상대적으로 가까운 서버를 두는 패턴을 씁니다. 이때도 두 목록이 같은 질의에 대해 일관된 A/AAAA 세트를 주는지 로그나 외부 dig로 샘플링해 보세요. IPv6 AAAA가 한쪽에서만 비어 있으면 듀얼 스택 환경에서만 깨지는 이슈로 이어질 수 있습니다.
dns:
fallback:
- https://dns.trusted-fallback.example/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
# domain:
# - '+.some-sinkhole.tld'
6. 단계 4: nameserver-policy로 회선 분리
국내 포털·은행·OTT가 섞인 환경에서는 «모든 질의를 하나의 DoH로만 보낸다»가 비용 대비 최선이 아닐 때가 많습니다. nameserver-policy로 +.kr나 지오사이트 묶음을 지정 리졸버에 붙이면, 지역 최적화가 필요한 도메인은 가까운 응답을 받고 나머지는 해외 업스트림을 타게 만들 수 있습니다. 정책 키 문법은 구독에 포함된 geosite·geodata 버전에 의존하므로, 규칙이 비어 있거나 오래되면 아무 일도 안 하는 policy 줄만 늘어난 채로 남을 수 있습니다.
정책을 추가할 때는 매칭 순서와 중첩을 같이 봅니다. 더 구체적인 패턴이 뒤에 가려지면, 분기 의도와 실제 트래픽이 어긋납니다. 또한 policy로 보낸 리졸버 자체가 막혀 있으면 해당 접미사 전체가 느려지므로, 정책별로도 2차 후보를 두는 사용자도 있습니다.
dns:
nameserver-policy:
"geosite:cn":
- tls://dns.in-region.example
"+.corp.internal.example":
- 10.0.0.53
7. fake-ip·직연결과 프록시 DNS
fake-ip를 켠 상태에서 nameserver가 돌려주는 답은 애플리케이션 관점과 커널 관점에서 다르게 해석될 수 있습니다. fake-ip-filter(또는 동등한 목록)에 들어간 호스트는 실제 A/AAAA를 보게 되고, 이때 어떤 업스트림이 쓰였는지가 곧 직연결 vs 프록시 구간의 일치 여부로 이어집니다. 필터에 없는 호스트는 가벼워 보이지만 SNI·인증서·지연 측정 타이밍에 따라 혼동이 생기기도 하므로, DNS 처리와 규칙 엔진을 따로 머릿속에서 겹쳐 두지 말고 로그로 한 번씩 확인하는 습관이 좋습니다.
일부 Mihomo 계열 구성에서는 DNS 질의 자체를 특정 프록시 그룹으로 보내는 옵션(예: proxy-server-nameserver 등)을 지원합니다. 현지망에서 해외 DoH까지 가는 경로가 불안정할 때, 질의만 노드 쪽으로 빼는 방식이 해석 안정성을 올려 주는 경우가 있습니다. 반대로 노드가 DNS 포트를 막거나 NAT가 꼬이면 이중 장애가 되므로, 해당 옵션을 켤 때는 타임아웃과 대체 업스트림을 같이 준비하는 편이 안전합니다. DIRECT로 나가야 하는 도메인에 실수로 프록시 경유 리졸버를 묶으면, Geo 분류·은행·지역 잠금 이슈로 겉보기 «DNS 오염»과 비슷한 증상이 날 수 있습니다.
8. 검증 순서
설정을 저장한 뒤에는 아래 순서로 좁히면 재현성이 좋습니다. 한 번에 네 가지를 바꾸지 말고, 한 단계 통과 확인 후 다음으로 넘어가세요.
- 클라이언트 로그에서 DNS 관련 오류·재시도가 줄었는지, 특정 업스트림만 반복 실패하는지 확인합니다.
- 문제 호스트명에 대해 Clash 리스너를 통해 조회했을 때와, 시스템
dig/nslookup로 조회했을 때의 응답 세트를 비교합니다. nameserver-policy가 기대한 패턴에 매칭되는지, 지오데이터 버전이 너무 오래되지 않았는지 봅니다.- IPv4·IPv6 각각에 대해 A·AAAA가 한쪽에서만 비어 있는지 확인합니다. 듀얼 스택 글(IPv6 인터페이스)과 결이 맞습니다.
- 브라우저나 전용 DNS 누설 검사 페이지로 질의가 예상 서버로만 가는지 샘플링합니다. WebRTC·DNS 유출 편에서 다룬 것과 같이 앱마다 스택이 다를 수 있습니다.
9. 요약
Clash DNS가 느리거나 일부 결과만 이상할 때, 노드 그룹을 헛돌리기 전에 nameserver와 fallback·fallback-filter, 필요 시 nameserver-policy를 순서대로 정리하는 것이 체감과 정확도 모두에 이득인 경우가 많습니다. fake-ip와 직연결이 DNS 응답을 어떻게 소비하는지, 프록시를 타는 리졸버를 쓸 때의 장단까지 맞춰 보면 «해석은 됐는데 페이지만 이상하다» 같은 모호한 상태가 줄어듭니다.
문서와 템플릿은 잘 정리되어 있어도, 최종 구성은 항상 사용자의 망과 구독 합본에 달려 있습니다. 핵심 키워드와 동작 원리를 손에 익혀 두면 이후 구독 갱신·클라이언트 교체 때도 같은 삽질을 반복하지 않기 쉽습니다. 루트 저장소와 이슈 트래커를 참고하고 싶다면 GitHub를 열어 오픈 소스·버그 리포트를 확인할 수 있지만, 일상적인 클라이언트 설치 파일은 사이트에서 받는 편이 분기와 서명 안내가 한곳에 모여 있습니다.
규칙·YAML·모드 설명을 한 번에 훑고 싶다면 Clash 문서 허브를 먼저 연 다음, 이 글의 단계를 따라 dns: 블록만 다시 맞춰 보세요. 같은 도구라도 DNS 레이어가 정리되면 전체 체감 속도가 한 단계 올라가는 경우가 많습니다.