先判断问题是不是 DNS 泄漏

DNS 泄漏通常指域名查询没有进入预期的 Clash 或 mihomo DNS 处理链,而是被操作系统、路由器、浏览器内置安全 DNS,或者网络接入商提供的解析器直接处理。网页流量即使已经经过代理,域名查询仍可能从本地网络单独发出。外部观察者因此能够看到查询目标,用户也可能遇到错误解析、污染结果、规则命中异常或同一网站在不同程序中表现不一致。

看到本地运营商的 DNS 服务器并不必然等于配置失效。需要先明确预期:如果配置中的 nameserver 本来就是本地公共 DNS,那么检测页显示对应服务商是正常结果;如果预期使用指定的 DoH、DoT 或远端解析器,检测页却反复出现路由器地址、宽带运营商解析器或公司网络 DNS,才需要继续排查。

常见症状

  • 浏览器访问正常,但终端中的 curl、软件更新器或游戏平台无法连接同一域名。
  • 切换代理节点后,DNS 检测结果始终显示本地宽带运营商的解析器。
  • 规则中使用域名匹配,但日志里只出现 IP,导致 DOMAIN-SUFFIX 规则没有按预期工作。
  • 开启 TUN 后部分网站返回错误地区内容,关闭 TUN 又恢复。
  • 同一域名在浏览器、nslookup 和 Clash 日志里得到不同地址。
  • 配置使用 fake-ip,系统查询却直接返回公网 IP,而不是 198.18.0.0/16 范围内的地址。

先记录基线,不要立即改配置

  1. 记录当前客户端、内核版本和正在使用的配置文件名称。
  2. 确认运行模式是规则、全局还是直连,并记录 TUN 与系统代理的开关状态。
  3. 清理浏览器和系统 DNS 缓存,再重复测试两次。
  4. 分别测试浏览器、命令行和一个独立应用,避免把单个程序的行为当成系统结论。
  5. 查看 Clash 日志中是否出现 DNS 请求、规则匹配和连接目标。

只开启系统代理时,操作系统的普通 DNS 查询不一定会被接管。HTTP 或 SOCKS 代理负责的是应用连接,系统解析器仍可能向网卡配置的 DNS 服务器发送 UDP 53 请求。TUN 模式配合 DNS 劫持能够覆盖更多应用,但前提是 TUN、路由、DNS 监听地址和劫持规则都实际生效。

用浏览器检测页与命令行交叉验证

浏览器检测页的正确用法

打开常见 DNS leak test 页面后,先执行标准测试,再执行扩展测试。测试前关闭其他代理扩展,保留一个浏览器窗口,并刷新检测页。结果通常会列出解析器的 IP、网络组织和地区。把这些信息与配置里的 DoH、DoT 或普通 DNS 服务商进行对照,而不是只看地区是否与代理节点一致。

浏览器可能启用自己的安全 DNS。Chrome、Edge 和 Firefox 都能绕开操作系统解析器,直接向浏览器指定的 DoH 服务发送请求。因此,浏览器检测页只能说明该浏览器当时的路径,不能单独证明整个系统都由 Clash 接管。

  • Chromium 系浏览器检查「设置」→「隐私和安全」→「安全」→「使用安全 DNS」。
  • Firefox 检查「设置」→「隐私与安全」→「DNS over HTTPS」。
  • 测试 Clash DNS 接管时,可暂时关闭浏览器安全 DNS,完成验证后再按实际方案决定是否恢复。
  • 如果保留浏览器 DoH,需要把它视为一条独立解析路径,不能再用它验证 Clash 的 dns 段。

直接查询 Clash DNS 监听端口

假设配置写了 listen: 127.0.0.1:1053,安装了 dig 的 Windows、macOS 或 Linux 可以直接向该端口查询:

dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

fake-ip 模式下,A 记录通常会返回 198.18.0.0/16 中的保留地址,例如 198.18.0.23。这个结果不是目标网站的真实地址,而是内核建立域名映射所使用的虚拟地址。后续连接命中该地址时,内核会还原原始域名,再按规则选择代理策略。

如果配置使用 enhanced-mode: redir-host,返回的通常是真实公网 IP。此时不能用是否出现 198.18.x.x 判断泄漏,需要结合日志、抓包和上游解析器结果确认路径。

检查系统当前使用的 DNS

Windows PowerShell 可以查看各网卡的 DNS 地址:

Get-DnsClientServerAddress |
  Where-Object {$_.ServerAddresses.Count -gt 0} |
  Format-Table InterfaceAlias, AddressFamily, ServerAddresses

如果结果仍是路由器地址,例如 192.168.1.1,这在仅使用系统代理时很常见。开启 TUN 后是否需要改成环回地址,取决于客户端实现;不少 mihomo 图形客户端通过 DNS 劫持接管 UDP 53,而不是永久修改网卡 DNS。不要在不了解客户端行为时手工把所有网卡改成 127.0.0.1,否则内核退出后可能造成整个系统无法解析域名。

Linux 使用 systemd-resolved 时,可以执行:

resolvectl status
resolvectl query example.com

macOS 可以查看系统解析器顺序:

scutil --dns
dscacheutil -q host -a name example.com

用抓包确认有没有直连 53 端口

检测结果仍不明确时,可在测试期间抓取 DNS 流量。Linux 上使用以下命令观察传统 UDP、TCP DNS:

sudo tcpdump -ni any 'port 53'

Windows 可用系统自带的 pktmon,也可以在网络分析工具中设置过滤条件 dnsudp.port == 53。执行测试查询后,如果看到物理网卡直接向路由器或运营商 DNS 发送数据包,说明仍有传统 DNS 绕过预期链路。DoH 使用 443 端口、DoT 使用 853 端口,单独过滤 53 无法发现它们,需要结合目标 IP、进程和 Clash 日志判断。

理解 fake-ip、redir-host 与 DNS 劫持

fake-ip 的处理过程

  1. 应用向系统请求解析域名。
  2. 查询被发送到 Clash DNS 监听器,或被 TUN 的 DNS 劫持规则捕获。
  3. 内核返回一个 198.18.0.0/16 范围内的虚拟地址,并保存虚拟地址与域名的映射。
  4. 应用连接该虚拟地址,TUN 或透明代理层截获连接。
  5. 内核恢复原始域名,执行域名规则,再按策略组建立真实连接。

这种方式可以减少本地提前解析造成的规则信息丢失,也便于按域名执行分流。它并不意味着上游 DNS 不再存在。内核仍可能需要解析代理服务器域名、直连目标或某些被排除的域名,因此 default-nameservernameserverproxy-server-nameserver 和规则行为仍需正确配置。

redir-host 的适用边界

redir-host 会向应用返回真实 IP,兼容性通常较直观,但域名到连接的关联可能更依赖嗅探、缓存和映射。使用大量域名规则、TUN 接管和复杂分流时,mihomo 一般更适合采用 fake-ip。遇到局域网设备发现、打印机、游戏登录、企业内网或依赖真实 DNS 结果的应用,可以先把特定域名加入 fake-ip-filter,而不是直接关闭整个 fake-ip 模式。

fake-ip-filter 应该放什么

过滤列表中的域名会跳过虚拟地址处理。应以实际故障为依据,避免使用覆盖范围过大的通配规则。常见起点如下:

fake-ip-filter:
  - "*.lan"
  - "*.local"
  - "localhost"
  - "time.*.com"
  - "time.*.gov"
  - "ntp.*.com"
  - "+.stun.*.*"
  - "+.stun.*.*.*"

*.local 常用于 mDNS 和局域网服务发现,NTP、STUN 等协议也可能依赖特殊解析或直接地址行为。不同 mihomo 版本和客户端自带模板可能已经包含一组默认过滤项。合并订阅配置时要先查看最终生效配置,避免自定义列表覆盖客户端提供的兼容规则。

DNS 劫持不是恶意篡改

在 TUN 配置中,dns-hijack 表示把指定目标的 DNS 请求重定向到内核处理。例如 any:53 用于接管发往任意地址的 53 端口请求。它解决的是应用绕过系统 DNS、直接查询固定服务器的问题。浏览器 DoH 走 HTTPS,目标端口是 443,不会被 any:53 捕获。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

不同内核版本对字段格式和协议支持可能存在差异。修改前应在客户端的「设置」→「内核」或「关于」中确认实际使用的是 mihomo,并通过配置校验功能检查语法。只编辑订阅原文件通常不够,订阅更新可能覆盖改动,优先使用客户端提供的覆写、合并或 Mixin 功能。

一份可作为起点的 mihomo DNS 配置

以下配置适合用于理解字段关系。监听端口设为 1053,避免与系统已有的 53 端口服务直接冲突。实际接管方式由客户端的 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

  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29

  nameserver:
    - https://dns.alidns.com/dns-query
    - https://doh.pub/dns-query

  fallback:
    - tls://1.1.1.1:853
    - https://1.1.1.1/dns-query

  fallback-filter:
    geoip: true
    geoip-code: CN
    ipcidr:
      - 240.0.0.0/4

  fake-ip-filter:
    - "*.lan"
    - "*.local"
    - "localhost"
    - "time.*.com"
    - "time.*.gov"
    - "ntp.*.com"
    - "+.stun.*.*"
    - "+.stun.*.*.*"

default-nameserver:解决上游服务器自身的域名

default-nameserver 用于解析 DoH、DoT 上游服务器或其他基础连接所需的域名,通常填写可直接访问的 IP 形式 DNS。它不是所有业务域名的唯一解析器。若只写域名形式的 DoH 地址,却没有可工作的引导解析器,可能出现循环依赖:需要先解析 DoH 域名才能使用 DoH,但当前又没有解析它的可用服务器。

nameserver:主要解析路径

nameserver 是常规域名查询的主要上游。示例使用 HTTPS DNS,能加密设备到解析器之间的查询内容。两个上游用于可用性冗余,不代表查询一定按照列表顺序逐个执行;具体并发、缓存和结果选择由内核实现及版本决定。

普通 UDP DNS 也可以写成 223.5.5.5,但查询内容会以传统 DNS 形式传输。DoT 使用类似 tls://1.1.1.1:853 的写法,DoH 使用完整的 HTTPS 地址。配置加载成功不代表网络一定允许访问对应端口,还要查看日志中是否存在超时、TLS 握手失败或证书错误。

fallback 与 fallback-filter:按结果筛选备用解析

fallback 提供另一组解析器,fallback-filter 决定何时采用备用结果。示例中的 geoip: truegeoip-code: CN 会结合 IP 地理数据库判断结果;240.0.0.0/4 等特殊地址段可作为异常结果过滤条件。

这套机制依赖 GeoIP 数据的准确性。CDN 地址、Anycast 地址和新分配网段可能被错误归类,因此不能把地区判断当作绝对标准。如果某个网站只在启用 fallback 后异常,先查看两组解析器分别返回什么地址,再调整域名策略或过滤条件。

ipv6:按网络条件明确开启

示例使用 ipv6: false,适合本地没有稳定 IPv6、代理节点不支持 IPv6 或希望先缩小排查范围的情况。如果本地和代理链路都完整支持 IPv6,可以改为 true,同时检查 TUN 路由、代理出口和 AAAA 查询。只关闭 DNS 的 AAAA 返回并不能修复所有 IPv6 绕行问题,系统已有的 IPv6 连接和应用内置解析仍需单独检查。

按顺序修复 DNS 绕过问题

第一步:确认最终生效配置

订阅内容、客户端覆写和运行时设置可能共同生成最终配置。进入客户端的「配置」→「当前配置」或「配置」→「查看运行配置」,确认 dns.enableenhanced-mode、监听地址与 TUN 设置确实存在。菜单名称因客户端不同会略有差异,但检查对象必须是内核实际加载的配置,而不是订阅下载目录中的原始 YAML。

第二步:检查端口是否监听

Windows 可以执行:

Get-NetTCPConnection -LocalPort 1053 -ErrorAction SilentlyContinue
Get-NetUDPEndpoint -LocalPort 1053 -ErrorAction SilentlyContinue

macOS 或 Linux 可以执行:

lsof -nP -iTCP:1053 -iUDP:1053
ss -lntup | grep 1053

如果没有监听结果,先看内核日志。常见原因包括 YAML 缩进错误、端口已被占用、客户端未加载编辑后的配置,以及安全软件阻止内核绑定端口。若改用其他端口,例如 1054,直接查询命令和客户端接管设置也要同步调整。

第三步:分别验证直连查询与系统查询

  1. 使用 dig @127.0.0.1 -p 1053 确认 Clash DNS 本身可响应。
  2. 使用不指定服务器的 dig example.comnslookup example.com 检查系统默认路径。
  3. 在 TUN 开启和关闭状态下分别测试,并记录返回地址。
  4. 打开浏览器检测页,确认浏览器安全 DNS是否影响结果。
  5. 观察内核日志是否出现测试域名,以及最终命中的规则和策略。

直接查询 Clash 正常,而系统默认查询仍走路由器,说明问题位于接管层,不在 nameserver 本身。此时应检查 TUN 是否真正启动、是否获得所需系统权限、DNS 劫持是否存在,以及当前网卡是否被排除。若直接查询也超时,则先修复 DNS 监听器或上游连接。

第四步:清理缓存后复测

Windows 清理系统 DNS 缓存:

ipconfig /flushdns

macOS 可执行:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

Linux 的缓存机制取决于发行版。使用 systemd-resolved 时可执行:

sudo resolvectl flush-caches

随后完全退出并重新打开浏览器。只刷新网页不会清除浏览器自己的主机缓存和已有连接。对于长期保持连接的聊天、游戏平台和同步工具,也应退出进程后再启动。

第五步:处理浏览器和应用自带 DoH

如果命令行与系统查询都已进入 Clash,但浏览器检测仍显示另一组解析器,优先检查浏览器安全 DNS。部分安全软件、企业客户端和移动应用也会内置 DoH。它们的 HTTPS 请求可能按普通网页流量经过 Clash,也可能被规则设置为直连,但无论哪种情况,都不会进入 Clash 的本地 DNS 模块。

处理方式有两种:关闭应用自带 DoH,让系统统一交给 Clash;或者保留应用 DoH,并明确为其设置路由规则。前者便于集中控制和故障排查,后者适合需要应用独立解析策略的场景。不要同时维护多套未知上游,否则检测结果会随应用和域名变化。

常见错误配置与对应修正

只写 nameserver,没有开启 DNS

dns:
  enable: false
  nameserver:
    - https://dns.alidns.com/dns-query

enable: false 时,后续上游设置不会建立预期的本地 DNS 服务。将其改为 true,再检查监听端口和接管方式。

把监听地址暴露到局域网

listen: 0.0.0.0:1053 会在所有接口监听。需要让局域网设备把这台机器当作 DNS 服务器时才考虑这种写法,并配合防火墙限制来源。单机使用优先绑定 127.0.0.1:1053,减少不必要的局域网访问面。

把 fake-ip 返回值当成污染结果

198.18.x.x 是 fake-ip 的正常虚拟地址范围。看到该地址后,应继续测试应用连接和规则命中,而不是把它写入 hosts 或直接加入直连规则。若某个应用确实不兼容,把对应域名精确加入 fake-ip-filter

同时让多个程序占用 53 端口

本地广告过滤器、虚拟机软件、容器服务和其他代理工具都可能监听 53 端口。两个程序不能在相同地址和协议上稳定占用同一端口。可以让 Clash 监听 1053,再由前置 DNS 转发到它;也可以停用冲突服务,由 Clash 统一接管。变更后需同时检查 UDP 与 TCP 监听情况。

误以为系统代理等于全局 DNS 接管

系统代理主要影响支持 HTTP 代理设置的应用。DNS、游戏流量、命令行工具和不读取系统代理的程序可能继续直连。需要更完整接管时使用 TUN,并确认自动路由、网卡检测、DNS 劫持和系统权限全部生效。TUN 也不是简单的“更强代理”开关,它会改变网络栈路径,排查时应一次只修改一个选项。

修复后的验收清单

  • 内核日志没有 DNS 上游超时、监听失败或配置字段错误。
  • dig @127.0.0.1 -p 1053 能在正常延迟内返回结果。
  • fake-ip 模式下,测试域名返回 198.18.0.0/16 范围地址。
  • TUN 开启后,系统默认查询能在 Clash 日志中找到对应域名。
  • 物理网卡抓包不再出现未预期的直连 UDP 或 TCP 53 查询。
  • 浏览器安全 DNS 的开关状态与当前方案一致,不再形成未知的独立路径。
  • DNS 检测页展示的解析服务与 nameserverfallback 设计相符。
  • 局域网、NTP、STUN 或企业内网域名若不兼容,已使用精确的 fake-ip-filter 规则处理。
  • 订阅更新后覆写仍能保留,重启客户端与设备后结果不变。

DNS 泄漏排查的核心是拆分链路:先确认 Clash DNS 是否能响应,再确认操作系统查询是否进入内核,最后检查浏览器和应用是否存在独立 DoH。检测页、命令行、日志和抓包必须相互印证。只更换一个 nameserver 地址通常不能解决接管层问题,只有监听、劫持、上游和应用行为同时一致,解析路径才算稳定。