DNS 泄漏检测与配置

讲解如何判断 Clash 是否存在 DNS 泄漏,并逐项说明 dns 段的 nameserver、fallback 与 nameserver-policy 写法,给出可直接套用的防泄漏配置。

先确定 DNS 泄漏的判断标准

Clash DNS 泄漏通常指:本应交给指定解析器或经代理传输的域名查询,绕过预期路径,发给了本地网络、运营商或其他解析服务。判断前必须写清预期。例如,国内域名允许直连解析,其他域名需要通过代理访问指定 DoH 服务。没有这条边界,仅凭检测页出现某个国家或服务商名称,无法得出泄漏结论。

一次访问至少涉及三条独立路径:应用把查询交给谁、Clash 把查询发给哪个上游、连接上游时使用直连还是代理。nameserver-policy 只解决按域名选择上游的问题;它本身不是流量接管开关,也不等于让 DNS 连接经过代理。

观察结果可以得出的结论还需检查
检测页显示公共 DNS 服务商测试查询到达该服务的递归解析节点访问该节点的连接是否走代理
物理网卡出现发往路由器的 UDP 53 查询存在本地明文 DNS 查询是否属于允许直连的域名或启动解析
返回地址位于 198.18.0.0/16可能使用了 Fake-IP 映射真实查询使用的上游及出站路径
浏览器正常,其他程序解析失败不同应用可能使用不同解析入口系统 DNS、浏览器安全 DNS 与 TUN 接管范围

建立可复现的 DNS 检测流程

1. 记录基线,再开启代理

  1. 关闭其他 VPN、代理和网络加速工具,记录当前网卡的 DNS 地址。Windows 可运行 ipconfig /all;macOS 可运行 scutil --dns;使用 systemd-resolved 的 Linux 可运行 resolvectl status。
  2. 记录浏览器是否开启安全 DNS。先用系统解析模式做一轮测试,再单独测试浏览器 DoH,避免把两条路径混在一起。
  3. 在未开启 Clash 时运行一次 DNS 检测,记录解析服务商、解析器地址和当前时间。开启 Clash 后用同一网络、同一浏览器重新测试。
  4. 同时打开客户端日志或连接列表,观察测试期间的域名、目标地址、命中规则及出站策略。检测页是线索,本机记录才用于解释实际路径。

公共 DNS 可能使用任播地址,递归节点的位置也可能与代理出口不同。检测页列出多个解析地址,既可能来自多个上游,也可能来自同一服务的节点池。不要把地址数量或地理位置直接当成泄漏次数。

2. 单独验证 Clash 的 DNS 监听

后面的配置把 DNS 监听在 127.0.0.1:1053。该地址仅供本机访问,1053 是 DNS 端口,不是 HTTP 代理端口。应用若仍向路由器的 53 端口查询,不会因为这里启用了监听就自动改道。

# macOS / Linux,需已安装 dig
dig @127.0.0.1 -p 1053 example.com A
dig @127.0.0.1 -p 1053 example.com AAAA

# Windows
nslookup -port=1053 example.com 127.0.0.1

命令能返回结果,说明本机到 Clash 的 DNS 入口可用;它不证明系统 DNS 已经被接管。若出现超时,先检查配置是否加载、内核是否运行以及 1053 端口是否冲突,不要立即更换代理节点。

3. 检查物理网卡上的明文查询

在有权限的设备上,可以使用抓包工具过滤 udp.port == 53 || tcp.port == 53。Linux 也可执行下面的命令;其中 any 会包含虚拟接口,判读时应区分物理网卡与 TUN 接口。

sudo tcpdump -ni any '(udp port 53 or tcp port 53)'

如果看到发往局域网 DNS 的查询,要核对具体域名是否属于允许直连的范围。没有观察到 53 端口流量,也不能证明所有 DNS 都经过代理:DoH 通常走 HTTPS 的 443 端口,DoT 通常使用 TCP 853,均不在这个过滤条件内。

理解 nameserver 与解析引导

dns.enable 开启内核 DNS 服务;listen 指定监听地址;nameserver 提供常规查询的上游。上游可以是普通 DNS 地址,也可以是内核支持的加密 DNS URL。将普通 DNS 换成 DoH,保护的是客户端到 DoH 服务之间的传输,并不会隐藏查询内容于该解析服务。

  • default-nameserver:主要用于解析 DNS 上游自身的域名,解决“先知道解析器地址”的启动问题;不是所有普通域名的默认分组。
  • proxy-server-nameserver:在 mihomo 中为代理节点域名提供专用解析入口,避免节点尚未连通就必须依赖该节点解析自身地址。
  • nameserver:处理未被专门策略覆盖的常规查询。
  • nameserver-policy:让指定域名或受支持的域名集合使用特定解析器。

下面示例使用 IP 形式的 DoH 地址做引导。所在网络必须能够连接这些地址,且内核的 TLS 验证必须成功。若网络阻断相应服务,应选择当地可达且可信任的解析器,并重新评估其直连范围,不要通过关闭证书验证绕过问题。

可套用的 mihomo DNS 配置

这是一份用于合并到现有配置的片段,不包含节点和订阅。示例将常规域名交给 Cloudflare DoH,将 .cn 后缀域名交给阿里 DoH,并通过规则区分 DNS 服务连接的出站方式。.cn 只代表域名后缀,不等于全部国内网站。

应用前,确认现有配置中有名称完全一致的 PROXY 策略组,并为它选好可用节点。若你的策略组名称不同,必须替换规则中的 PROXY。把下方规则插入已有 rules 列表的前部,保留原有业务规则和末尾兜底;不要创建第二个同名 YAML 键。

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  respect-rules: true
  default-nameserver:
    - https://1.1.1.1/dns-query
  proxy-server-nameserver:
    - https://1.1.1.1/dns-query
  nameserver:
    - https://cloudflare-dns.com/dns-query
  nameserver-policy:
    "+.cn":
      - https://dns.alidns.com/dns-query

# 合并到现有 rules 的前部,不要覆盖后续业务规则。
rules:
  - DOMAIN,cloudflare-dns.com,PROXY
  - DOMAIN,dns.alidns.com,DIRECT
  - IP-CIDR,1.1.1.1/32,DIRECT,no-resolve

respect-rules: true 使常规 DNS 上游连接遵循路由规则。示例用明确的域名规则让 Cloudflare DoH 经 PROXY 出站,阿里 DoH 直连;IP 规则为引导地址保留直连路径。代理节点域名的专用解析也保留为启动依赖,因此不能宣称该配置让每一次 DNS 查询都经过代理。

ipv6: false 在这里限制的是内核 DNS 的 AAAA 应答,不会关闭操作系统 IPv6,也不是 IPv6 流量防泄漏开关。需要 IPv6 的环境应单独验证 IPv6 路由、TUN 接管和上游支持,再决定是否启用。

nameserver-policy 的匹配与边界

在 mihomo 的域名匹配语法中,"+.example.com" 可以覆盖该域名及其子域。建议为包含特殊字符的策略键加引号,并用两个空格缩进。策略值可以写成解析器列表;选用多个解析器时,不应把列表顺序理解成严格的主备顺序。

dns:
  nameserver-policy:
    "+.example.com":
      - https://cloudflare-dns.com/dns-query
    "+.cn":
      - https://dns.alidns.com/dns-query

这段仅演示策略写法,应合并到上一段的 dns 内,而不是另起一个重复键。example.com 是用于验证匹配的示例域名,正式使用时按实际业务域名调整。不要依靠大量交叠的宽泛策略猜测优先级;保持范围清楚,并分别测试主域和子域。

企业内网域名需要单独处理

公司内部域名通常只能由办公网络 DNS 解析。可以将真实内部后缀映射到内网 DNS,并为该 DNS 地址保留直连路由;使用 Fake-IP 时,还需根据应用需求评估是否加入 fake-ip-filter。不要把内部域名发给公共解析器,也不要把公共 DNS 返回的失败结果误判为节点故障。

将域名加入 fake-ip-filter 只是改变返回真实地址还是映射地址,不会自动指定上游,更不会强制直连。解析器选择、Fake-IP 例外与连接路由是三个配置层,应分别验证。

fallback 不是防泄漏开关

fallback 提供另一组解析上游,fallback-filter 参与结果选择。不能简单理解为“主 DNS 完全失败以后才访问备用 DNS”:相关查询可能并行发生,具体行为受内核及过滤条件影响。如果两个上游分别位于不同信任边界,查询本身就可能被发送给两方。

下面是针对异常地址结果的独立写法示例。它应追加到已有 dns 段内,不替换整个配置。使用 Quad9 时,还要把对应连接的出站策略纳入检查;仅声明 HTTPS 地址不会自动指定代理。

  fallback:
    - https://dns.quad9.net/dns-query
  fallback-filter:
    geoip: false
    ipcidr:
      - 0.0.0.0/32
      - 127.0.0.0/8

这里关闭基于 GeoIP 的筛选,只演示对指定异常地址范围的过滤。它不是完整的污染识别规则;某些安全过滤服务有意返回空地址,某些测试域名也可能合法指向回环地址。明确需要时才添加条件,不能把更多过滤项等同于更可靠。

系统代理、TUN 与浏览器 DoH 的遗漏点

系统代理不会接管全部 DNS

HTTP 代理可以让代理端处理请求中的目标域名,但未使用系统代理的程序仍可能调用系统解析器。SOCKS 应用是否把域名交给代理,也取决于其远程解析选项。开启系统代理后网页可用,不代表命令行工具、游戏和后台服务都使用了同一解析路径。

TUN 的 DNS 劫持有协议边界

需要接管不遵循系统代理的应用时,可在支持的平台开启 TUN。下面是常见的 mihomo 配置片段;自动路由通常需要相应系统权限,且是否能接管局域网目标 DNS 还取决于平台路由和客户端实现。

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

这些劫持项针对传统 DNS 的 UDP/TCP 53 端口,不会解密浏览器 DoH,也不会把所有 443 端口连接转成内核 DNS 查询。浏览器自带的 DoH 仍然是一条独立连接:它可能被 TUN 路由到代理,但其域名查询内容不会因此交给 nameserver-policy 处理。

浏览器与系统缓存要分开测试

以桌面 Chrome 为例,可在「设置」→「隐私和安全」→「安全」中检查「使用安全 DNS」;界面文案可能随版本变化。为了验证 Clash 内核 DNS,先暂时关闭自定义安全 DNS。若保留浏览器 DoH,则应另外核对该 DoH 服务连接的出站策略。

Windows 可运行 ipconfig /flushdns 清理系统缓存;使用 systemd-resolved 的 Linux 可运行 resolvectl flush-caches。浏览器缓存与内核缓存可能仍然存在,重启相应进程后再测。不要用缓存命中的一次快速响应证明上游已经切换。

按症状完成最后复测

症状优先检查验证动作
1053 端口查询超时DNS 监听、配置错误、端口冲突查看启动日志,直接查询本机监听
只有浏览器出现不同解析器浏览器 DoH 或浏览器代理设置切换为系统解析后重复同一测试
开启 TUN 后仍有路由器 DNS 查询目标路由、平台接管限制、其他虚拟网卡在物理网卡抓包并核对查询进程
切换节点后无法解析节点域名解析与上游路由循环检查专用节点解析器能否独立连接
订阅更新后设置消失修改了会被替换的远程配置改用持久化覆写并检查最终配置

最后按相同顺序复测:确认本机 1053 监听可用,确认系统或 TUN 把目标查询送入内核,确认策略选中了预期上游,再确认该上游连接命中了正确出站。保留测试时间、查询域名、解析器和策略记录。四层结果一致,才说明这条查询路径符合预期;单次检测页截图不能代表所有应用、所有网络和 IPv6 场景。

Clash 客户端下载