DNS 해석, 규칙에 따른 라우팅, 트래픽 가로채기부터 구분하기

Clash DNS 설정은 도메인을 IP 주소로 변환하거나 Fake-IP 모드에서 도메인과 가상 주소를 연결합니다. 규칙은 연결에 적용할 정책을 정하고, 시스템 프록시와 TUN은 어떤 연결이 코어로 들어갈지 결정합니다. 이 세 가지는 서로 연관되어 있지만 서로를 대신할 수는 없습니다. 공용 DNS 주소를 설정했다고 브라우저 요청이 프록시를 거치는 것은 아니며, TUN을 켰다고 모든 암호화 DNS가 가로채지는 것도 아닙니다.

이 글은 Clash Meta에서 발전한 mihomo 코어를 중심으로 설명합니다. 기존 Clash와 클라이언트마다 지원하는 설정 항목이 다를 수 있으며, 특히 tun, proxy-server-nameserver 등의 지원 여부를 확인해야 합니다. 문제를 해결하기 전에 클라이언트의 ‘정보’ 또는 코어 정보 화면에서 실제 코어 이름과 버전을 확인하세요. 클라이언트 제품명만으로 판단하지 마세요.

  • DNS 요청이 들어오는 곳: 앱, 시스템 리졸버 또는 TUN이 가로챈 53번 포트 트래픽입니다.
  • DNS 업스트림:nameserver, fallback 등의 목록에 설정한 DNS 서버입니다.
  • 서비스 연결의 출구:rules와 프록시 정책이 결정하며, DNS 서버가 있는 지역에 따라 정해지지 않습니다.

dns 설정 블록: 검증하기 쉬운 최소 예제부터

디버깅할 때는 먼저 redir-host를 사용해 실제 주소를 확인하고, 업스트림 연결을 검증한 뒤 필요에 따라 Fake-IP로 전환하세요. 아래 예제는 로컬의 127.0.0.1:1053에서 DNS 서비스를 제공합니다. 1053은 예시 포트이며 모든 클라이언트가 기본값으로 사용해야 하는 포트는 아닙니다.

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  nameserver:
    - https://dns.alidns.com/dns-query
  fallback:
    - https://1.1.1.1/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4
항목예제의 의미확인할 사항
enable코어 DNS 모듈 활성화시작 로그에 DNS 초기화 오류가 있는지 확인
listen루프백 주소의 1053 포트에서 수신포트 사용 여부와 테스트 요청의 포트가 올바른지 확인
ipv6이 예제에서는 AAAA 주소를 반환하지 않음운영체제의 IPv6 네트워크를 끈다는 의미는 아님
enhanced-mode실제 주소를 반환하는 해석 모드 사용Fake-IP 모드에서 가상 주소가 반환되는 것은 정상
default-nameserver업스트림 DNS 서버의 호스트 이름 해석부트스트랩 리졸버에 연결할 수 있는지 확인

listen: 127.0.0.1:1053은 로컬에서만 접속할 수 있어 데스크톱 디버깅에 적합합니다. 0.0.0.0:1053으로 변경하면 수신 범위가 넓어집니다. LAN 기기에 서비스를 제공해야 한다면 방화벽에서 접속 출처를 제한해 신뢰할 수 없는 네트워크에 DNS 서버가 노출되지 않도록 하세요.

default-nameserver는 일반 쿼리에 사용하는 ‘세 번째 예비 서버’가 아닙니다. 업스트림에 https://dns.alidns.com/dns-query를 지정하면, 코어가 먼저 호스트 이름에 해당하는 IP를 알아내야 합니다. 예제에서는 숫자 주소로 부트스트랩해 리졸버가 자기 자신에 의존해야 시작되는 상황을 방지합니다. 일반 UDP 부트스트랩 쿼리는 DoH처럼 전송을 암호화하지 않으므로 네트워크의 개인정보 보호 및 연결 가능성을 고려해 선택하세요.

nameserver와 fallback: 단순한 주 서버·보조 서버가 아닌 후보 결과

nameserver는 일반 DNS 해석 결과를 제공

nameserver는 일반 업스트림 서버 목록입니다. 도메인별 정책을 따로 설정하지 않았다면 일반 쿼리는 이 서버들에서 처리합니다. 주소를 여러 개 설정해도 첫 번째 서버부터 순서대로 시도한다는 뜻은 아닙니다. 코어가 여러 업스트림에 동시에 쿼리한 뒤 사용 가능한 결과를 선택할 수 있으므로, 목록 순서로 도메인별 라우팅을 구현하려고 해서는 안 됩니다.

fallback은 별도의 후보 결과를 제공

fallback을 사용한다고 해서 ‘nameserver가 시간 초과된 경우에만 조회한다’고 이해하면 안 됩니다. 일반적인 nameserver/fallback 동작에서는 두 그룹에 동시에 쿼리하고, 최종적으로 fallback-filter에 따라 사용할 결과를 선택할 수 있습니다. 다른 그룹의 결과로 전환할 때 기다리는 시간을 줄일 수 있지만, 반대로 다른 그룹의 서버에도 쿼리 내용이 전달될 수 있습니다.

프록시를 통과하는지는 별개의 문제입니다. fallback에 https://1.1.1.1/dns-query를 입력해도 이 DoH 연결이 자동으로 프록시 노드를 거치지는 않습니다. 실제 아웃바운드 경로는 코어 버전, DNS 업스트림 지정 방식 및 관련 라우팅 설정에 따라 달라집니다. 현재 네트워크에서 해당 서버에 연결할 수 없다면 필터 조건을 계속 바꾸기보다 먼저 연결 가능 여부를 해결하세요.

  • 기본 DNS 해석만 확인하려면 연결 가능한 nameserver 하나만 남기고 fallback과 필터는 잠시 제거하세요.
  • 두 그룹의 결과를 실제로 비교해야 한다면 fallback을 추가하고 필터 조건을 명시적으로 설정하세요.
  • 특정 도메인을 지정한 리졸버로 보내려면 목록 순서에 기대지 말고 nameserver-policy를 사용하세요.

fallback-filter: geoip·ipcidr·domain 조건

fallback-filter는 fallback 결과를 사용할 시점을 판단합니다. 방화벽 규칙도, 서비스 트래픽에 프록시를 지정하는 규칙도 아닙니다. geoip-code: CN을 설정해도 중국 본토 웹사이트가 반드시 직접 연결되거나 다른 지역 웹사이트가 반드시 프록시를 이용하는 것은 아닙니다.

geoip: nameserver가 반환한 주소의 위치 확인

geoip: true와 geoip-code: CN을 설정하면 일반적으로 CN에 속하는 nameserver 결과를 유지하고, 해당 조건에 맞지 않으면 fallback 결과를 선택합니다. 판단 기준은 DNS 서비스 제공자의 위치가 아니라 코어가 사용하는 GeoIP 데이터입니다. 데이터가 없거나 오래되었거나 CDN 주소의 위치 정보가 바뀌면 결과에 영향을 줄 수 있습니다.

ipcidr: 특정 주소 범위에 다른 결과 적용

예제의 240.0.0.0/4는 이 범위에 해당하는 nameserver 결과를 fallback에서 처리하도록 합니다. 이는 의심스러운 주소 범위를 보여주는 예일 뿐, 모든 잘못된 해석을 걸러내지는 못합니다. 192.168.0.0/16 같은 사설 주소 범위를 필터에 무조건 추가하지 마세요. 기업 내부망, 공유기 관리 페이지, 로컬 도메인은 사설 IP를 반환하는 것이 정상일 수 있습니다.

domain: 특정 도메인에 fallback 적용

도메인 필터는 IP 조건과 달리 도메인 단계에서 fallback을 사용하도록 지정할 수 있습니다. 아래는 GeoIP 판단을 끈 별도 예제로, 예시용 예약 도메인인 example.com과 하위 도메인에만 해당 선택 로직을 적용합니다. 실제 환경에서는 이 동작이 필요한 도메인을 입력하세요.

dns:
  fallback-filter:
    geoip: false
    domain:
      - '+.example.com'

domain, ipcidr, 활성화된 GeoIP 조건은 각각 fallback을 적용할 수 있으며, 세 조건을 모두 만족해야 하는 것은 아닙니다. ‘이 도메인만 다른 업스트림을 사용’하게 하려면 필요하지 않은 GeoIP 조건을 명시적으로 끄고, 전체 설정에 다른 필터 항목이 남아 있는지도 확인하세요.

nameserver-policy와 노드 도메인: DNS 해석 경로가 순환하지 않도록 하기

LAN 도메인은 일반적으로 공용 DNS로 보내는 것이 적절하지 않습니다. mihomo에서는 nameserver-policy로 특정 도메인에 사용할 업스트림을 지정할 수 있습니다. 아래의 192.168.1.1은 해당 주소가 실제 로컬 DNS 서버인 네트워크에서만 사용할 수 있습니다. 게이트웨이가 192.168.50.1인 환경에서는 그대로 사용하지 마세요.

dns:
  nameserver-policy:
    '+.home.arpa':
      - 192.168.1.1
  proxy-server-nameserver:
    - 223.5.5.5
    - 119.29.29.29

home.arpa는 홈 네트워크에서 사용하는 특수 도메인 공간입니다. 별도 정책을 지정하면 공용 fallback에 LAN 레코드 해석을 맡기지 않고 로컬 리졸버로 보낼 수 있습니다. policy에 일치하면 전용 해석 경로를 사용하므로 해당 도메인도 일반 nameserver/fallback 선택 절차를 그대로 따른다고 가정하지 마세요.

proxy-server-nameserver는 프록시 노드 서버의 도메인 이름을 해석하는 데 사용합니다. 이는 ‘대상 웹사이트를 어느 노드로 조회할지’와는 다른 문제입니다. DoH 연결에 프록시가 필요한데 프록시 노드의 도메인 해석도 해당 DoH에 의존하면 시작 과정에서 의존성 순환이 발생합니다. 노드 도메인용으로 연결 가능한 별도의 해석 경로를 마련하면 이러한 순환 위험을 줄일 수 있습니다. 구체적인 설정 항목의 지원 여부는 사용 중인 mihomo 버전을 기준으로 확인하세요.

해석 경로 순환을 해결하려고 여러 라우팅 옵션을 한꺼번에 추가하지 마세요. 먼저 노드 도메인 해석과 노드 연결이 가능한지 확인한 다음, 일반 DNS가 서비스 규칙을 따를지 결정하세요. 변경 후에는 클라이언트가 최종 생성한 실행 설정을 확인해 구독 오버라이드가 새 항목을 삭제하지 않았는지 점검하세요.

TUN에서 dns-hijack을 설정할 위치와 프로토콜

dns-hijack은 최상위 tun 설정 블록에 속하며 dns 항목 안에 넣지 않습니다. TUN으로 들어온 트래픽 중 조건에 맞는 DNS 요청을 코어 DNS 모듈로 전달합니다. 아래는 mihomo에서 흔히 사용하는 설정입니다. 사용하기 전에 클라이언트에 가상 네트워크 어댑터 생성과 라우팅 변경 권한이 있는지 확인하세요.

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - 'any:53'
    - 'tcp://any:53'
  • any:53: TUN으로 들어오는 UDP 53번 포트 DNS 요청을 처리합니다.
  • tcp://any:53: TCP 53번 포트를 추가해 TCP 쿼리와 일부 잘린 응답 이후의 재시도를 처리합니다.
  • auto-route: 관련 라우트를 자동으로 설정합니다. 모든 플랫폼에서 로컬 네트워크 트래픽까지 TUN으로 들어온다는 보장은 없습니다.
  • auto-detect-interface: 출구 인터페이스를 자동으로 찾습니다. 네트워크 어댑터가 여러 개이거나 다른 VPN을 사용하거나 라우팅이 복잡하다면 실제 출구를 확인해야 합니다.

dns-hijack은 시스템 DNS 주소를 127.0.0.1:1053으로 바꾸는 설정도, 가로챌 대상을 1053 포트로 지정하는 설정도 아닙니다. 전자는 원래 53번 포트로 전송되는 요청을 처리하고, dns.listen은 별도의 DNS 서비스 수신 주소입니다. 역할이 다르므로 함께 사용할 수 있습니다.

하이재킹을 켰는데도 다른 DNS 연결이 보이는 이유

DoH는 보통 HTTPS 443번 포트를, DoT는 TCP 853번 포트를, DoQ는 UDP 853번 포트를 사용합니다. 일반 DNS의 53번 포트와 다르므로 위의 두 설정만으로 가로채거나 복호화할 수 없습니다. 브라우저에서 ‘보안 DNS’를 사용하거나 Android에서 ‘비공개 DNS’를 켠 경우, 또는 앱 자체 리졸버를 사용하는 경우 쿼리가 암호화된 서비스 연결로 계속 나갈 수 있습니다.

또한 같은 서브넷의 공유기로 향하는 트래픽은 TUN을 통과하지 않고 물리 인터페이스로 직접 나갈 수 있습니다. 플랫폼 라우팅과 시스템 DNS 주소를 함께 확인해 실제 트래픽 처리 경로를 파악하세요. 스위치가 켜져 있다는 이유만으로 판단해서는 안 됩니다. 문제 해결을 위해 앱의 암호화 DNS를 잠시 끄는 경우 현재 설정을 기록하고, 확인을 마친 뒤 필요에 따라 복원하세요.

명령으로 확인하기: 수신 포트, 업스트림, 트래픽 가로채기 순서

아래 명령은 테스트 절차를 재현하기 위한 예시이며 특정 네트워크 환경에서 측정한 결과가 아닙니다. 실제 DNS 결과를 확인할 수 있도록 우선 예제의 redir-host를 유지하고, Fake-IP 가상 주소가 판단을 방해하지 않도록 하세요. 한 번에 한 그룹의 설정만 바꾼 뒤 구성을 다시 불러오세요.

1단계: 코어 DNS 수신 포트에 직접 요청

dig가 설치된 macOS 또는 Linux 터미널에서 UDP와 TCP를 각각 테스트하세요. Windows에서도 적절한 도구를 설치하면 같은 명령을 사용할 수 있습니다. 기본 제공 nslookup도 대화형 모드에서 포트를 설정해 사용할 수 있습니다.

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
nslookup
server 127.0.0.1
set port=1053
set type=A
example.com
exit

NOERROR가 반환되고 ANSWER에 A 레코드가 있으면 해당 쿼리에서 주소 해석이 완료된 것입니다. SERVFAIL은 해석 경로 처리에 실패했다는 뜻이며, 시간 초과가 발생하면 수신 포트·업스트림·방화벽도 확인해야 합니다. NOERROR만 있고 A 레코드가 없다고 바로 실패로 판단할 수는 없습니다. 해당 도메인에 A 레코드가 없을 수도 있습니다.

2단계: 업스트림과 필터 문제 분리

  1. fallback을 잠시 제거하고 nameserver 하나만 남긴 뒤 같은 도메인을 다시 조회하세요.
  2. 테스트할 fallback 서버를 임시로 유일한 nameserver로 지정해 서버 자체가 해석을 수행할 수 있는지 확인하세요.
  3. 두 업스트림을 다시 설정한 뒤 GeoIP, IP 범위, 도메인 조건을 하나씩 활성화하면서 변화를 확인하세요.
  4. 로그에 기록된 업스트림 연결 오류, 시간 초과, 설정 로딩 오류를 바탕으로 원인을 좁히세요. 모든 이상 현상을 DNS 오염 탓으로 돌리지 마세요.

3단계: 수신 포트가 아니라 TUN 동작 확인

127.0.0.1:1053에 직접 쿼리하면 수신 주소가 작동하는지만 확인할 수 있으며 TUN 하이재킹 성공 여부는 알 수 없습니다. 트래픽 가로채기를 테스트하려면 시스템이나 앱에서 일반 DNS 주소의 53번 포트로 요청을 보내고 코어 로그와 연결 정보를 확인해야 합니다. 패킷 캡처가 가능하다면 원본 쿼리가 물리 출구로 나가는지도 확인하세요. 브라우저 DoH를 끄고 테스트하며, 로컬 캐시에 남은 결과 때문에 쿼리 자체가 발생하지 않을 수도 있다는 점에 유의하세요.

Windows에서는 ipconfig /flushdns로 시스템 DNS 캐시를 비울 수 있습니다. macOS에서는 sudo dscacheutil -flushcache와 sudo killall -HUP mDNSResponder를 사용할 수 있습니다. Linux는 배포판마다 캐시 서비스가 다릅니다. systemd-resolved를 사용한다면 resolvectl flush-caches를 실행하세요. 이 명령들은 모든 브라우저 캐시를 지우지는 않으며 클라이언트 내부 DNS 캐시를 새로 고치는 작업을 대신하지도 않습니다.

자주 발생하는 증상과 설정 마무리

증상먼저 확인할 항목다음 조치
1053 포트 쿼리 시간 초과DNS 모듈이 비활성화되었거나 포트 충돌이 발생했거나 업스트림에 연결할 수 없음실행 설정과 시작 로그를 확인하고 업스트림 하나만 따로 테스트
198.18로 시작하는 주소 반환현재 설정에서 Fake-IP가 활성화됨가상 주소 범위와 TUN 라우팅을 확인하고 바로 DNS 오류로 단정하지 않기
LAN 호스트 이름 해석 실패공용 DNS로 쿼리가 전송되거나 사설 주소가 필터링됨내부 도메인에 로컬 해석 정책을 지정하고 필터 목록 확인
노드를 활성화한 뒤 모든 도메인에서 시간 초과노드 도메인 해석과 DNS 아웃바운드 간 의존성 순환노드 도메인 해석과 노드 연결을 각각 따로 테스트
TUN은 켜져 있지만 브라우저가 다른 리졸버를 사용브라우저의 보안 DNS가 켜져 있거나 트래픽이 TUN으로 들어오지 않음암호화 DNS, 시스템 DNS, 라우팅을 각각 확인

설정을 마무리할 때는 용도가 분명한 항목만 남기세요. nameserver는 일반 DNS 해석을 제공하고, fallback은 필터와 함께 다른 결과를 선택합니다. nameserver-policy는 특정 도메인을 처리하며, dns-hijack은 TUN으로 들어온 기존 DNS 요청을 가로챕니다. 마지막으로 구독 업데이트 후 실행 설정을 확인하고, 디버깅 중 임시로 바꾼 브라우저·시스템 DNS·로그 수준 설정을 복원하세요. 단계별로 검증할 수 있는 간결한 설정이 공용 DNS 주소를 계속 추가하는 것보다 관리하기 쉽습니다.