먼저 Clash DNS 처리 흐름부터 이해하기
Clash의 DNS 모듈은 시스템 쿼리를 공용 DNS 하나로 단순 전달하지 않습니다. 활성화하면 로컬 포트를 수신하고 설정된 업스트림 서버를 읽은 뒤, 도메인과 규칙, 반환된 주소를 바탕으로 사용할 결과를 결정합니다. TUN과 DNS 하이재킹을 켜면 원래 라우터나 공용 DNS의 53번 포트로 향하던 요청도 이 흐름으로 가져올 수 있습니다.
일반적인 쿼리는 네 단계로 나눌 수 있습니다. 애플리케이션이 도메인 주소를 요청하고, 시스템이 요청을 Clash에 전달합니다. Clash는 nameserver, 매칭된 정책 서버 또는 fallback에 쿼리를 보내고, 마지막으로 fallback-filter와 향상 모드에 따라 실제 주소나 Fake IP를 반환합니다. 웹페이지 접속 여부, 도메인 규칙 매칭 여부, 프록시 노드 도메인 해석 여부가 모두 이 과정의 영향을 받을 수 있습니다.
읽기 쉬운 기본 설정
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 1.1.1.1
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
- https://dns.google/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
여기서 listen은 127.0.0.1:1053을 사용하므로 로컬 루프백 주소의 UDP/TCP 1053번 포트에서만 수신합니다. 1053은 흔히 사용하는 비특권 DNS 수신 포트로, 시스템의 기존 53번 포트 서비스와의 충돌을 피할 수 있습니다. 클라이언트가 이미 수신 주소를 자동으로 관리한다면 구독 파일에 충돌하는 설정을 다시 추가하지 않는 것이 좋습니다.
nameserver, default-nameserver, fallback은 각각 어떤 역할을 할까
nameserver: 기본 업무용 도메인 해석 경로
nameserver는 대부분의 도메인 쿼리를 처리하는 주요 업스트림입니다. 일반 UDP DNS를 지정할 수도 있고, 호환되는 mihomo 커널에서는 DoH와 DoT 같은 형식도 사용할 수 있습니다. 가정용 네트워크에서 지연 시간을 줄이려면 가까우면서 응답이 안정적인 서버를 선택하고, 암호화된 전송이 필요하다면 HTTPS DNS 주소를 사용하면 됩니다.
nameserver:
- 223.5.5.5
- 119.29.29.29
- https://dns.alidns.com/dns-query
한 목록에 여러 서버를 넣었다고 해서 매번 첫 번째 항목부터 순서대로 기다리는 것은 아닙니다. 구체적인 동시 처리와 결과 선택 방식은 커널 구현에 따라 달라지므로 응답 특성이 크게 다른 서버 네댓 개를 한꺼번에 넣는 것은 바람직하지 않습니다. 실제 설정에서는 안정적인 업스트림 2~3개만 유지하는 편이 문제를 추적하기 쉽습니다.
default-nameserver: DNS 서버 자체의 도메인부터 해석하기
nameserver에 https://dns.alidns.com/dns-query처럼 호스트 이름이 포함된 DoH 주소를 사용하면, 커널이 HTTPS 연결을 만들기 전에 dns.alidns.com의 IP를 알아야 합니다. default-nameserver는 주로 이러한 부트스트랩 해석을 담당하며 bootstrap DNS라고도 합니다.
default-nameserver:
- 223.5.5.5
- 1.1.1.1
“DNS 서버를 해석하려면 먼저 DNS 서버에 접속해야 하는” 순환 의존성을 피하려면 여기에는 직접 접속할 수 있는 IP 주소를 우선 입력하는 것이 좋습니다. 로그에 lookup dns server failed나 context deadline exceeded가 계속 나타난다면 DoH 주소를 더 추가하기보다 먼저 현재 네트워크에서 이 주소들에 접속할 수 있는지 확인해야 합니다.
fallback: 병렬로 사용할 또 다른 후보 결과
fallback은 주 업스트림과 다른 해석 관점을 제공하는 데 사용됩니다. 활성화하면 Clash가 필터 조건을 바탕으로 nameserver 결과와 fallback 결과 중 하나를 선택합니다. nameserver가 시간 초과된 뒤에만 작동하는 것은 아니므로, 멀리 있는 DoH 서버를 지나치게 많이 추가하면 연결과 리소스 사용량이 늘어날 수 있습니다.
로컬 네트워크의 주요 DNS가 이미 안정적이고 Fake IP 모드를 전체 규칙 세트와 함께 사용한다면 fallback이 반드시 필요한 것은 아닙니다. 먼저 간단한 설정을 정상적으로 작동시킨 뒤 DNS 오염, 지역에 맞지 않는 결과 또는 특정 도메인 이상이 발생할 때 후보 경로를 추가하는 편이 오래된 템플릿을 통째로 복사하는 것보다 안정적입니다.
fallback-filter로 최종 결과 선택하기
fallback-filter는 주 결과를 교체할 필요가 있는지 판단합니다. 일반적인 조건으로 GeoIP 국가 코드, 특정 네트워크 대역, 도메인 목록을 사용할 수 있습니다. 확장 필드 지원 여부는 커널 버전에 따라 다를 수 있으므로 mihomo를 사용할 때는 현재 커널 문서와 시작 로그를 기준으로 확인해야 합니다.
geoip와 geoip-code
fallback-filter:
geoip: true
geoip-code: CN
이 설정은 GeoIP 데이터를 바탕으로 반환된 주소의 지리적 위치를 판단합니다. 일반적으로 주 업스트림이 현재 지역에 맞는 주소를 반환하면 해당 결과를 사용하고, 반환 주소가 필터 조건에 맞지 않으면 fallback 결과를 검토합니다. 판단 품질은 클라이언트가 사용하는 GeoIP 데이터의 최신성에 좌우되며, 국가 코드를 절대적으로 정확한 회선 측정값으로 보아서는 안 됩니다.
ipcidr: 명백히 비정상적인 주소 대역 차단하기
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 0.0.0.0/32
- 127.0.0.0/8
- 240.0.0.0/4
ipcidr은 일반 공용 도메인이 반환하지 않기를 원하는 주소 범위를 표시할 수 있습니다. 예를 들어 공용 웹사이트가 127.0.0.1로 해석되는 것은 대체로 비정상입니다. 하지만 회사 내부망, 홈 서버, 테스트 네트워크에서는 사설 주소를 실제로 사용할 수 있으므로 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16을 구분 없이 모두 차단해서는 안 됩니다.
domain: 지정 도메인에서 fallback 우선 사용하기
fallback-filter:
geoip: true
geoip-code: CN
domain:
- '+.example.net'
- '+.example.org'
도메인 목록은 소수의 재현 가능한 이상 사이트를 처리하는 데 적합합니다. +.example.net과 같은 표기는 해당 도메인과 하위 도메인을 매칭하지만, 실제 문법은 사용하는 커널 버전과 호환되어야 합니다. 목록을 무한히 늘려서는 안 됩니다. 수백 개의 도메인을 수동으로 지정해야 한다면 주 업스트림, 규칙 세트 또는 네트워크 출구 선택을 다시 점검해야 한다는 신호일 수 있습니다.
fake-ip와 redir-host 중 무엇을 선택할까
enhanced-mode는 Clash가 애플리케이션에 어떤 결과를 전달할지 결정합니다. 일반적으로 fake-ip과 redir-host를 사용합니다. 두 방식 모두 프록시 전달과 함께 사용할 수 있지만 도메인 보존 방식, 호환성, 진단 방법이 다릅니다.
fake-ip: 예약 주소를 먼저 반환하고 커널에서 도메인 매핑하기
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
Fake IP 모드는 198.18.0.23과 같은 임시 주소를 예약 주소 풀에서 반환합니다. 애플리케이션이 이 주소에 연결하면 Clash가 내부 매핑을 통해 원래 도메인을 찾아 도메인 규칙과 프록시 정책을 적용합니다. 실제 DNS 결과를 기다린 뒤 연결을 만드는 단계를 줄이고, 대상 IP만 보이는 트래픽도 도메인으로 복원하기 쉬워집니다.
198.18.0.0/15는 벤치마크 용도로 예약된 네트워크 대역이며, 프록시 커널에서 Fake IP 주소 풀로 자주 사용합니다. 로컬 네트워크, 기업 VPN 또는 테스트 환경에서 같은 대역을 이미 사용한다면 커널이 허용하면서 충돌하지 않는 범위로 변경해야 합니다. ping 결과가 198.18로 시작한다고 해서 도메인 해석이 잘못된 것은 아닙니다. 요청을 Clash가 처리하고 있는지가 핵심입니다.
fake-ip-filter: 특수 도메인은 실제 주소 반환하기
fake-ip-filter:
- '*.lan'
- localhost.ptlogin2.qq.com
- '+.stun.*.*'
- '+.stun.*.*.*'
로컬 네트워크 기기 검색, 프린터, 일부 게임 연결, STUN, 시간 동기화, 실제 주소를 읽어야 하는 애플리케이션은 Fake IP와 맞지 않을 수 있습니다. 이때 fake-ip-filter에 예외를 추가할 수 있습니다. 필터 항목은 실제 장애를 기준으로 하나씩 추가하고 변경 후 시스템 DNS 캐시를 비워야 합니다. 지나치게 긴 목록을 그대로 복사하면 많은 도메인이 Fake IP를 우회해 도메인 매핑 효과가 떨어집니다.
redir-host: 실제 IP를 반환해 호환성을 높이는 방식
enhanced-mode: redir-host
redir-host는 실제 해석 주소를 애플리케이션에 반환합니다. Fake IP와 충돌하고 항목별 필터링이 어려운 오래된 소프트웨어나 특수한 로컬 네트워크 환경에 적합하지만, 도메인 규칙의 안정적인 매칭 여부는 스니핑, 연결 메타데이터, 구체적인 트래픽 가로채기 방식에 더 크게 좌우됩니다. 문제를 진단할 때 fake-ip에서 redir-host로 잠시 전환해 볼 수 있습니다. 문제가 즉시 사라진다면 Fake IP 대역 충돌과 필터 목록을 우선 확인하세요.
TUN 모드에서도 DNS 하이재킹이 필요한 이유
시스템 DNS를 127.0.0.1:1053으로 설정하는 것만으로는 모든 프로그램이 이를 따르지 않습니다. 일부 애플리케이션은 8.8.8.8:53으로 UDP 요청을 직접 보내고, 일부 기기는 라우터가 배포한 DNS를 사용합니다. TUN 모드는 IP 트래픽을 가로채고, DNS 하이재킹은 매칭되는 53번 포트 요청을 Clash DNS 모듈로 전달합니다.
mihomo 설정에서 자주 사용하는 TUN 구성은 다음과 같습니다. 지원 필드는 커널과 클라이언트의 래퍼 방식에 따라 달라질 수 있습니다. 그래픽 클라이언트가 TUN 설정을 자동 생성한다면 구독 YAML과 화면 설정이 서로 덮어쓰지 않도록 인터페이스의 스위치를 우선 사용하세요.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
enable은 TUN 가로채기를 활성화합니다.stack: mixed는 커널이 지원하는 혼합 네트워크 스택을 사용합니다.auto-route는 필요한 라우팅을 자동으로 추가합니다.auto-detect-interface는 현재 출구 네트워크 인터페이스를 식별합니다.any:53은 가로챈 트래픽의 일반적인 53번 포트 DNS 요청과 매칭됩니다.
DNS 하이재킹은 주로 기존 UDP/TCP 53번 포트를 대상으로 합니다. 애플리케이션에 내장된 DoH는 HTTPS 443번 포트를 사용하므로 네트워크 계층에서는 일반 HTTPS와 비슷하게 보이며, dns-hijack만으로 일괄 변경할 수 없습니다. 브라우저에서 “보안 DNS”를 활성화했다면 문제를 진단할 때 잠시 끄고 요청을 브라우저와 Clash 중 어디서 해석하는지 확인하세요.
일상적인 사용에 적합한 mihomo 설정 방향
일상적인 데스크톱과 모바일 환경에서는 “로컬 업스트림은 일반적인 해석을 담당하고, 암호화된 후보는 이상 결과에 대응하며, Fake IP는 도메인을 매핑하고, TUN 하이재킹은 기존 DNS를 가로챈다”는 방향으로 시작할 수 있습니다. 아래 예시는 구조적 관계를 설명하기 위한 것이며 모든 네트워크에 같은 서버를 사용해야 한다는 뜻은 아닙니다.
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
use-hosts: true
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
fallback:
- https://1.1.1.1/dns-query
- https://dns.google/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 0.0.0.0/32
- 127.0.0.0/8
- 240.0.0.0/4
fake-ip-filter:
- '*.lan'
- localhost
- '+.stun.*.*'
- '+.stun.*.*.*'
로컬 네트워크에 IPv6 출구가 없다면 ipv6을 false로 설정해 애플리케이션이 AAAA 레코드를 받은 뒤 연결할 수 없는 경로를 시도하지 않게 할 수 있습니다. 안정적인 네이티브 IPv6를 사용할 수 있고 프록시 노드와 규칙도 IPv6를 올바르게 처리한다면 활성화해도 됩니다. 단, 통신사가 IPv6 주소를 할당했는지만 볼 것이 아니라 기본 경로, DNS 응답, 프록시 출구가 모두 정상인지 테스트해야 합니다.
mihomo는 nameserver-policy, proxy-server-nameserver, direct-nameserver 같은 확장 필드도 제공합니다. 이를 사용하면 특정 도메인, 프록시 노드 도메인, 직접 연결 요청에 각각 다른 해석기를 지정할 수 있습니다. 이러한 필드는 이미 해석 경로를 명확히 분리한 설정에 적합합니다. 기본 설정이 아직 정상 작동하지 않는 상태에서 고급 필드를 한꺼번에 모두 추가하면 순환 해석이 발생하거나 노드 도메인이 잘못된 출구를 사용할 수 있습니다.
프록시 노드가 도메인일 때 추가로 확인할 점
구독의 서버 주소가 node.example.com처럼 도메인으로 되어 있다면 커널이 먼저 이를 해석해야 프록시 연결을 만들 수 있습니다. 해당 도메인을 해석하는 DNS가 아직 연결되지 않은 프록시를 통해서만 접근하도록 설정되어 있다면 “프록시가 있어야 노드를 해석할 수 있고, 노드가 있어야 프록시를 만들 수 있는” 순환이 발생합니다. mihomo에서는 proxy-server-nameserver를 사용해 노드 도메인에 직접 연결 가능한 해석기를 별도로 지정할 수 있습니다.
proxy-server-nameserver:
- 223.5.5.5
- https://dns.alidns.com/dns-query
DNS 이상을 단계별로 진단하는 방법
1단계: 설정이 커널에 로드되었는지 확인하기
- YAML을 저장한 뒤 편집기만 닫지 말고 클라이언트의 “설정 다시 불러오기”를 실행하세요.
- 커널 로그를 열고
DNS,listen,timeout,parse를 검색하세요. - YAML 들여쓰기 오류가 발생했다면
dns:아래가 일관되게 공백으로 들여쓰기되었는지, 목록 항목 앞의 하이픈이 남아 있는지 확인하세요. - 현재 선택한 구독이 자동 업데이트 후 로컬 변경 사항을 덮어쓰지 않았는지 확인하세요.
YAML은 들여쓰기에 민감합니다. 아래처럼 fallback을 실수로 nameserver 목록 안에 들여쓰면 의도한 구조를 표현할 수 없습니다. 각 단계에 공백 2개를 사용하고 Tab은 사용하지 않는 것이 좋습니다.
2단계: Clash 수신 포트에 직접 쿼리 보내기
Windows에서는 PowerShell이나 명령 프롬프트에서 nslookup을 사용할 수 있고, macOS와 Linux에서는 dig를 사용할 수 있습니다. 쿼리 대상을 수신 주소로 지정하면 “Clash DNS 자체가 실패한 경우”와 “시스템이 요청을 Clash로 전달하지 않은 경우”를 구분할 수 있습니다.
nslookup example.com 127.0.0.1
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA
nslookup은 일반적으로 53번 포트에 접속합니다. Clash가 1053번 포트에서만 수신한다면 포트 지정이 가능한 도구를 사용하거나 클라이언트가 시스템의 53번 포트 요청을 1053번으로 전달하도록 해야 합니다. Fake IP 모드에서 198.18.x.x를 받는 것은 정상입니다. 계속 시간 초과가 발생한다면 포트 사용 여부, 방화벽, 업스트림 연결 가능성을 확인하세요.
3단계: 해석 가능 여부뿐 아니라 업스트림 응답 측정하기
한 번 성공적으로 응답했다고 해서 경로가 안정적이라는 뜻은 아닙니다. 20회 정도 연속 쿼리해 간헐적인 시간 초과가 발생하는지 확인하세요. 로컬 네트워크의 일반 DNS는 보통 5~30ms, 지역을 가로지르는 DoH는 80~250ms까지 걸릴 수 있습니다. 실제 수치는 접속 네트워크에 따라 달라지므로 한 번의 최저값보다 시간 초과율과 변동 폭이 중요합니다.
- DoH만 시간 초과되는 경우: 시스템 시간, TLS 연결, DoH 도메인의 부트스트랩 해석을 확인하세요.
- 일반 UDP DNS와 DoH가 모두 시간 초과되는 경우: 현재 네트워크, 기본 경로, 방화벽을 확인하세요.
- 쿼리는 성공하지만 웹페이지가 열리지 않는 경우: 프록시 규칙, 노드 연결, TUN 라우팅을 계속 확인하세요.
redir-host로 전환한 뒤 복구되는 경우: Fake IP 대역 충돌과 필터 항목을 확인하세요.- 로컬 네트워크 도메인만 실패하는 경우: 내부망 도메인에 전용 해석 정책을 설정하거나 필요한 Fake IP 예외를 추가하세요.
4단계: 기존 캐시를 비운 뒤 다시 테스트하기
업스트림이나 향상 모드를 변경하면 시스템, 브라우저, Clash가 모두 이전 결과를 보관하고 있을 수 있습니다. Windows에서는 ipconfig /flushdns를 실행하고, systemd-resolved를 사용하는 Linux에서는 resolvectl flush-caches를 실행하세요. 브라우저에도 별도의 호스트 캐시가 있을 수 있습니다. 캐시를 정리한 뒤 설정을 다시 불러오고 같은 도메인으로 재테스트해 이전 기록을 새 설정의 결과로 잘못 판단하지 않도록 하세요.
이 필드를 입력할 때 최종 확인 목록
enable이 활성화되어 있고 수신 포트가 로컬의 다른 DNS 서비스와 충돌하지 않습니다.default-nameserver에 프록시가 연결되기 전에도 직접 접속할 수 있는 서버가 지정되어 있습니다.nameserver에는 안정적인 업스트림 2~3개만 남기고 중복 서비스를 과도하게 쌓지 않습니다.fallback은 서로 다른 해석 관점을 제공하는 용도이며, 시간 초과 뒤의 보조 항목으로 기계적으로 사용하는 것이 아닙니다.fallback-filter의 GeoIP, 네트워크 대역, 도메인 조건이 현재 네트워크 환경에 맞습니다.fake-ip-range가 기업 VPN, 홈 네트워크 또는 테스트 네트워크 대역과 충돌하지 않습니다.fake-ip-filter에는 실제 주소가 꼭 필요한 도메인만 추가합니다.- TUN 모드가 활성화된 경우
dns-hijack과 클라이언트 자동 설정이 중복되거나 충돌하지 않는지 확인합니다. - 프록시 노드가 도메인을 사용하는 경우 노드 도메인의 부트스트랩 해석이 아직 연결되지 않은 프록시에 의존하지 않는지 확인합니다.
- 변경할 때마다 한 그룹의 필드만 조정하고 변경 전후의 쿼리 결과와 로그를 기록하세요.
Clash DNS 설정의 핵심은 모든 네트워크에 맞는 고정 템플릿을 찾는 것이 아니라, 해석 경로, 후보 결과, 필터 조건, 향상 모드, 트래픽 가로채기를 검증 가능한 흐름으로 연결하는 데 있습니다. 먼저 최소한의 필드로 쿼리 연결을 확인한 뒤 Fake IP, fallback, TUN 하이재킹을 단계적으로 추가하면 문제가 발생했을 때 어느 단계인지 정확히 찾을 수 있습니다.