먼저 DNS 요청 경로 확인하기
mihomo DNS를 설정하기 전에 세 가지 흐름을 구분해야 합니다. 앱이 조회를 어디로 보내는지, mihomo가 어느 업스트림 DNS에 질의하는지, 최종 연결이 어떤 규칙으로 전달되는지 확인하세요. nameserver를 암호화 DNS로 바꾸면 가운데 단계만 달라집니다. 브라우저가 자체 보안 DNS를 사용하면 조회가 mihomo DNS 모듈에 아예 도달하지 않을 수 있습니다.
이 문서는 Clash Meta의 후속 프로젝트인 mihomo 코어를 기준으로 합니다. 클라이언트가 인터페이스에서 DNS 또는 TUN 설정을 덮어쓸 수 있으므로 구독 원본이 아니라 실제로 로드된 실행 설정을 확인하세요. 구버전 Clash 코어에서는 여기서 다루는 모든 항목을 지원하지 않을 수 있습니다.
- 현재 설정을 백업하고 시스템 프록시, TUN, DNS 재정의 스위치 상태를 기록합니다.
- 클라이언트의 코어 정보를 확인해 실제로 mihomo가 실행 중인지 확인하세요. 클라이언트 이름만으로 판단하지 마세요.
- 먼저 로컬
127.0.0.1:1053에서 DNS 응답을 확인한 뒤 TUN 가로채기를 설정하세요. - 한 번에 한 묶음의 항목만 조정하세요. 설정을 다시 불러올 때마다 로그를 확인한 뒤 같은 도메인으로 테스트합니다.
nameserver와 default-nameserver: 최소 설정으로 시작하기
아래는 기존 설정에 합쳐 사용하는 DNS 예시이며, 프록시 구독 전체 설정이 아닙니다. 노드나 규칙은 포함하지 않으며 기존 proxies, proxy-groups, rules를 삭제할 필요도 없습니다. 최상위 dns: 항목은 하나만 두고 필요한 필드를 합치세요. 키가 중복되면 실제 적용 결과가 불명확해질 수 있습니다.
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "localhost"
- "*.lan"
- "*.local"
- "+.home.arpa"
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
- https://doh.pub/dns-query
| 항목 | 이 설정의 역할 |
|---|---|
enable | mihomo 내장 DNS 모듈을 활성화합니다. |
listen | 로컬 루프백 주소의 1053 포트에서 DNS 요청을 받습니다. 로컬 네트워크에는 공개되지 않습니다. |
default-nameserver | 업스트림 DNS 서버의 도메인을 먼저 조회합니다. DoH 서버 주소를 처음부터 확인할 수 없는 상황을 방지합니다. |
nameserver | 일반 조회에 사용할 업스트림 DNS를 설정합니다. 예시에는 HTTPS DNS 주소 두 개가 사용됩니다. |
ipv6: false | DNS 모듈에서 AAAA 조회에 빈 결과를 반환해 IPv4 연결 경로를 먼저 확인합니다. 운영체제의 IPv6를 끄는 설정은 아닙니다. |
업스트림 목록을 고정된 주·보조 순서로 보지 마세요
nameserver에 두 항목을 적어도 “첫 번째가 실패한 뒤 두 번째를 사용한다”는 뜻은 아닙니다. 코어가 여러 서버에 동시에 질의해 응답을 활용할 수 있으므로 목록 순서로 엄격한 주·보조 구성을 기대하지 마세요. 먼저 현재 네트워크에서 실제로 연결되는 업스트림을 고르고, 그다음 응답 속도를 고려하세요. 주소를 열 개 넘게 추가하면 문제를 찾기만 더 어려워질 수 있습니다.
default-nameserver도 “모든 웹사이트가 기본적으로 이 DNS를 사용한다”는 뜻이 아닙니다. 주로 DNS 서버 도메인 자체를 어떻게 조회할지 지정합니다. 예시에서는 IP 주소로 초기 조회를 수행하지만, 이후 DoH를 사용한다고 해서 이 첫 조회까지 자동으로 암호화되는 것은 아닙니다.
fallback과 fallback-filter: 시간 초과 대기가 아닌 응답 결과 필터링
fallback은 별도의 업스트림 DNS 목록이지 프록시 정책 그룹이 아니며, 노드 선택용 그룹을 만들지도 않습니다. nameserver와 fallback을 함께 설정하면 코어가 동시에 조회하고 fallback-filter를 기준으로 fallback 응답을 사용할지 판단할 수 있습니다. 이를 “기본 DNS가 시간 초과될 때만 작동하는 예비 DNS”로 이해하면 조회 흐름을 잘못 파악하기 쉽습니다.
IP의 지리적 위치에 따라 응답을 필터링하려면 아래 항목을 앞에서 만든 동일한 dns: 아래에 합치세요. 먼저 각 업스트림이 현재 네트워크에서 연결되는지 따로 확인해야 합니다. 연결할 수 없는 DoH 주소를 적는 것만으로 DNS 오염이나 연결 문제가 해결되지는 않습니다.
fallback:
- https://1.1.1.1/dns-query
- https://8.8.8.8/dns-query
fallback-filter:
geoip: true
geoip-code: CN
ipcidr:
- 240.0.0.0/4
세 가지 조건으로 필터링 방식 이해하기
- 지역 조건:
geoip: true를 활성화하고geoip-code: CN을 설정하면 일반 조회 결과의 IP가 지정한 지역에 속하지 않을 때 fallback 응답을 우선 사용할 수 있습니다. 확인 대상은 도메인 접미사가 아니라 조회된 IP입니다. - IP 대역 조건:
ipcidr에는 일반 조회 결과에서 제외할 IP 대역을 지정합니다. 예시의240.0.0.0/4는 구체적인 필터 조건이며 웹사이트 트래픽의 프록시 라우팅 규칙이 아닙니다. - 데이터 의존성: GeoIP 판정은 코어에서 사용하는 지리 정보 데이터에 의존합니다. 데이터가 없거나 오래된 경우, 또는 CDN 주소의 지역 정보가 바뀐 경우 결과가 달라질 수 있습니다.
이 설정만으로 “한국 도메인은 한국 DNS, 해외 도메인은 해외 DNS”처럼 나뉘지는 않습니다. 도메인은 여러 지역에 배포될 수 있고 CDN도 서로 다른 주소를 반환합니다. 사내 도메인이나 특정 서비스를 확실하게 분기하려면 지리 정보에 의존하기보다 nameserver-policy를 사용하는 편이 명확합니다.
nameserver-policy: 지정한 도메인의 업스트림 DNS 선택하기
회사 네트워크, 가정용 NAS, 프린터에서는 내부 DNS만 조회할 수 있는 이름을 쓰는 경우가 많습니다. 이런 도메인을 공용 DNS에 맡기면 안 됩니다. 아래는 가정용 네트워크 예시입니다. 라우터 주소가 실제로 192.168.1.1이고 home.arpa 내부 레코드를 조회할 수 있을 때만 이 설정을 사용하세요.
nameserver-policy:
"+.home.arpa":
- 192.168.1.1
이 항목도 기존 dns: 아래에 합치는 부분 설정입니다. 일치하는 도메인은 정책에 지정된 업스트림을 사용하므로 일반 nameserver/fallback 필터 흐름을 그대로 따른다고 가정하지 마세요. +.home.arpa는 해당 도메인과 하위 도메인을 매칭합니다. 회사 내부 도메인으로 바꾸기 전에 네트워크 관리자에게 DNS 서버와 접속 요건을 확인하세요.
nameserver-policy와 fake-ip-filter는 서로 다른 문제를 해결합니다. 전자는 DNS를 어디에 질의할지 정하고, 후자는 앱에 가상 주소를 반환할지 정합니다. 내부 도메인에 DNS 정책을 적용한 뒤에도 기기 검색이나 직접 연결에 실제 IP가 필요하다면 해당 도메인을 fake-ip 제외 목록에도 추가하세요.
fake-ip와 redir-host: 가상 주소와 실제 주소 비교
enhanced-mode는 DNS 처리 모드를 지정합니다. fake-ip 모드에서는 앱에 예약 주소 대역의 매핑 주소를 반환합니다. 연결이 다시 mihomo에 도달하면 코어가 매핑을 통해 도메인을 복원한 뒤 규칙과 아웃바운드 처리를 적용합니다. 이 주소는 웹사이트 서버의 실제 IP가 아니며 mihomo를 거치지 않는 기기에서 직접 접속할 수도 없습니다.
| 비교 항목 | fake-ip | redir-host |
|---|---|---|
| 앱이 받는 A 레코드 | 일반적으로 설정된 주소 풀의 매핑 주소 | DNS 조회로 얻은 실제 주소 |
| 도메인 연결 방식 | 가상 주소 매핑으로 도메인 정보 유지 | DNS 캐시 매핑 등의 방식으로 도메인 복원 |
| 연결 조건 | 가상 주소로 향하는 연결은 해당 mihomo 인스턴스로 돌아와야 합니다. | 실제 IP를 받아도 연결은 의도한 프록시 또는 라우팅 경로로 들어가야 합니다. |
| 흔한 호환성 문제 | 로컬 네트워크 기기 검색, 실제 IP를 확인하는 앱, 가로채기를 우회하는 연결 | 공유 IP, 캐시 매핑, 앱 자체 DNS로 인한 도메인 식별 제한 |
fake-ip-filter에 추가할 때
로컬 네트워크 도메인이나 실제 주소가 필요한 기기 검색 서비스는 우선 제외 목록에 추가할 수 있습니다. 기본 블랙리스트 방식에서는 목록에 일치하는 도메인에 fake-ip를 반환하지 않고 실제 주소로 조회합니다. 모든 도메인을 추가하면 설정에 fake-ip가 남아 있어도 실제 동작은 크게 달라집니다.
특정 앱에서만 문제가 생긴다면 전체 모드를 바로 바꾸지 말고 앱이 사용하는 도메인부터 제외하세요. redir-host로 전환한 뒤에는 클라이언트 DNS 캐시를 비우고 관련 앱을 재시작하세요. 필요하면 시스템 DNS 캐시도 갱신해야 합니다. 설정 파일을 바꿔도 기존 198.18.x.x 기록이 모든 앱에서 즉시 사라지지는 않습니다.
TUN DNS 가로채기: 기존 53 포트 DNS 요청 처리하기
여기서 DNS 가로채기란 TUN을 통과하는 지정 DNS 트래픽을 mihomo DNS 모듈로 전달하는 것을 말합니다. 원격 웹사이트의 DNS 레코드를 수정하는 기능은 아닙니다. 데스크톱에서 시스템 프록시를 사용하지 않는 앱까지 처리하려면 먼저 TUN 라우팅을 올바르게 활성화한 뒤 DNS 가로채기를 설정해야 합니다.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
- tcp://any:53
any:53은 TUN을 통과하는 UDP 53 조회를 매칭하고, tcp://any:53은 TCP 53을 추가로 처리합니다. auto-route는 라우트를 자동 설정하고 auto-detect-interface는 아웃바운드 인터페이스를 감지합니다. 실제 가로채기 범위는 운영체제, 라우팅, 클라이언트 구현에 따라 달라집니다. 이 YAML만 보고 모든 DNS가 가로채기된다고 판단하면 안 됩니다.
- 권한 확인: 데스크톱 클라이언트에서 가상 네트워크 어댑터와 라우트를 만들려면 서비스 모드나 적절한 관리자 권한이 필요한 경우가 많습니다. DNS 항목을 바꾸기 전에 권한 오류부터 확인하세요.
- 포트 구분:
listen: 127.0.0.1:1053은 명시적으로 조회를 받는 주소입니다. TUN의 53 포트 가로채기는 코어가 처리하므로 시스템 DNS 주소에 1053을 붙여 입력할 필요가 없습니다. - 암호화 DNS 확인: DoH는 보통 443 포트, DoT는 보통 853 포트를 사용합니다. 53 포트만 매칭해서는 이 연결을 강제로 가로챌 수 없습니다. 문제를 확인하는 동안 브라우저의 ‘보안 DNS’를 잠시 끄고 비교 테스트해 보세요.
- 외부 공개 방지: 로컬 네트워크 기기에 DNS를 제공해야 할 때만 로컬 네트워크 주소에서 수신하도록 설정하고 방화벽도 구성하세요. 테스트 편의를 위해 인터넷에 그대로 공개하지 마세요.
Android 클라이언트는 보통 시스템 VPN 인터페이스로 트래픽을 처리하므로 데스크톱의 자동 라우팅 항목이 그대로 적용되지 않을 수 있습니다. iOS 클라이언트도 자체 네트워크 확장 구현에 따라 동작이 달라집니다. 데스크톱 TUN 설정을 모든 플랫폼에 복사하지 말고 클라이언트에서 제공하는 VPN, DNS, 우회 설정을 사용하세요.
검증 및 문제 해결: DNS 조회, 가로채기, 연결을 따로 확인하기
1단계: 로컬 DNS에 직접 질의하기
설정을 활성화한 뒤 dig가 설치된 시스템에서 아래 두 명령을 실행하세요. 첫 번째는 UDP, 두 번째는 TCP로 질의해 로컬 DNS가 응답하는지 확인합니다. 서버를 명시해 조회하므로 이것만으로 시스템 DNS가 TUN에 의해 가로채기되는지는 확인할 수 없습니다.
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com A +tcp
Windows에서는 기본 제공되는 nslookup으로 포트를 지정해 테스트할 수 있습니다.
nslookup -port=1053 example.com 127.0.0.1
fake-ip 모드에서 필터링되지 않은 일반 A 조회는 보통 198.18.0.1/16 주소 풀의 주소를 반환합니다. 이는 조회가 가상 주소 매핑을 사용했다는 뜻일 뿐, 업스트림의 실제 DNS 조회나 프록시 아웃바운드까지 정상이라는 뜻은 아닙니다. 제외 목록에 있는 도메인은 실제 주소 조회 경로로 확인하세요.
2단계: 연결이 같은 코어로 돌아오는지 확인하기
- 클라이언트의 연결 패널을 열고 HTTPS 웹사이트에 접속한 뒤 해당 도메인이 표시되는지 확인하세요.
- 예상한 규칙이 적용됐는지 확인하고 최종 아웃바운드가 DIRECT인지 프록시 정책 그룹의 노드인지 살펴보세요.
- fake-ip를 받았지만 연결 기록이 없다면 먼저 TUN, 라우팅, 앱 우회 설정을 확인하세요.
- 연결이 코어에 도달했지만 시간 초과가 발생한다면 DNS 모드를 반복해서 바꾸지 말고 노드, 규칙, 업스트림 연결을 확인하세요.
3단계: 증상에 따라 원인 좁히기
| 증상 | 먼저 확인할 항목 | 다음 조치 |
|---|---|---|
| 로컬 1053 포트 조회 시간 초과 | DNS 활성화 여부, 설정 로드 여부, 포트 사용 여부 | 시작 로그에서 수신 주소를 확인한 뒤 다시 조회 |
| DoH 로그에 TLS 오류 표시 | 시스템 시간, 인증서, 업스트림 연결, 초기 DNS 조회 | 시스템 시간을 맞추고 업스트림 하나를 테스트하세요. 문제를 숨기려고 인증서 검증을 끄지 마세요. |
| 웹사이트는 열리지만 NAS 도메인은 접속되지 않음 | 내부 DNS 정책 및 fake-ip 제외 설정 | 내부 도메인에 라우터 DNS를 지정하고 실제 주소가 필요한지 확인 |
| 설정을 바꿨는데 결과가 그대로임 | 클라이언트 재정의 설정, 구독 갱신, 앱 및 시스템 캐시 | 실행 설정을 확인하고 다시 불러온 뒤 캐시를 갱신 |
| 브라우저에서만 다르게 동작 | 브라우저 보안 DNS, 프록시 확장 프로그램, 별도 캐시 | 관련 기능을 잠시 끄고 같은 도메인으로 비교 테스트 |
Windows에서는 ipconfig /flushdns를 실행해 시스템 DNS 캐시를 갱신할 수 있습니다. 브라우저나 앱에 자체 캐시가 남아 있을 수도 있습니다. 진단 로그를 공유할 때는 시간, 오류 유형, 관련 항목만 남기고 구독 URL, 인증 정보, 민감한 내부 도메인은 삭제하세요.
마지막으로 정상 작동을 확인한 DNS 변경 사항을 클라이언트가 지원하는 재정의 또는 설정 병합 입력란에 저장하세요. 구독을 새로 고칠 때 설정이 사라지는 것을 막을 수 있습니다. ‘최소 작동 설정’과 ‘현재 설정’을 각각 기록해 두세요. 문제가 생기면 먼저 이전 설정으로 되돌린 뒤 fallback, 도메인 정책, TUN 가로채기를 하나씩 다시 적용하는 편이 여러 스위치를 한꺼번에 바꾸는 것보다 원인을 찾기 쉽습니다. 설정 파일과 프록시 규칙의 전체 관계는 전체 안내서에서 확인할 수 있습니다.