DNS 泄漏的判断:先分清解析与连接

网页通过代理打开,不代表域名解析也经过代理。应用可能先向路由器或运营商 DNS 查询地址,再把 HTTPS 连接交给 Clash;也可能把域名直接交给代理,由远端解析。这两条路径的网页表现相同,DNS 暴露范围却不同。排查时要同时看应用如何解析、请求由谁接管、上游 DNS 经哪条路由发送。

本文把“DNS 泄漏”限定为:本来要求经代理或指定加密解析器处理的查询,意外发给了本地网络或其他未预期的解析器。大陆站点按配置直连并使用本地 DNS,属于分流策略,不应仅凭检测页出现本地解析器就判断故障。先明确目标:是只保护代理域名,还是希望除节点域名等必要查询外,所有应用 DNS 都走指定路径。

常见的四条旁路

  • 只有系统代理:应用不遵守系统代理时,UDP 53 查询仍可能直达路由器。
  • 浏览器安全 DNS:浏览器向自己的 DoH 服务发送 HTTPS 请求,绕过内核 DNS 模块;该连接是否走代理仍由接管与规则决定。
  • 多套 DNS 配置:订阅、客户端覆写和系统网络设置同时生效,修改的文件并非最终运行配置。
  • IPv6 或其他 VPN:另一张网卡、IPv6 路由或 VPN DNS 策略提供了未纳入接管的路径。

检测步骤:网页结果、内核日志与系统查询交叉验证

检测前记录客户端名称、内核类型、系统代理状态、TUN 状态和当前模式。本文后面的 respect-rules、proxy-server-nameserver 示例面向支持这些字段的 mihomo 内核,不应原样套进旧版 Clash。图形客户端版本与内核版本是两项信息,可在客户端“关于”页和启动日志中分别确认。

第一步:建立同一网络下的对照

  1. 先关闭其他 VPN、网络加速器和代理扩展,记录浏览器安全 DNS 是否开启。
  2. 暂时关闭 Clash 接管,在 dnsleaktest.com 执行 Extended test,记录解析器 IP、网络归属和检测时间。
  3. 启用准备检查的配置,保持浏览器设置不变,再执行相同测试。也可以用 browserleaks.com/dns 交叉检查。
  4. 随后暂时关闭浏览器安全 DNS,再测一次,用来区分“浏览器自己的解析链路”和“系统、内核的解析链路”。测试结束后按实际需求恢复设置。

检测站通常让浏览器访问随机子域名,再从权威 DNS 一侧观察递归解析器。结果里的 IP 是解析器的出口,不一定是代理节点 IP。使用公共 DNS 时,解析器所在城市与代理出口城市不一致很常见;服务采用 Anycast 或转发架构,也可能一次显示多个地址。应核对运营者和预期链路,而不是只比较国家名称。

第二步:确认 DNS 模块确实响应

下面的查询针对本文示例中的本地监听端口 1053。它只验证内核 DNS,不代表系统和浏览器都已使用该端口。在启用 fake-ip、且域名未被过滤时,A 查询通常应返回 198.18.0.0/16 范围内的映射地址。

# Windows PowerShell 或命令提示符
nslookup -port=1053 example.com 127.0.0.1

# macOS / Linux,需系统提供 dig
dig @127.0.0.1 -p 1053 example.com A

接着查看客户端“日志”页,临时将日志等级设为 debug,重新发起一次查询和网页访问;再到“连接”页检查目标域名、命中规则及最终策略。日志格式因内核版本不同而异,重点是有无解析失败、连接超时或循环解析提示。排查结束后恢复 info,避免持续记录过多域名信息。

第三步:区分缓存与真实旁路

修改后仍出现旧解析器时,先重载配置,再清理系统 DNS 缓存并重启测试浏览器。Windows 可执行 ipconfig /flushdns;使用 systemd-resolved 的 Linux 可执行 resolvectl flush-caches。这些命令不会清除所有应用的内部缓存,因此仍需重新运行使用随机域名的检测。

需要进一步确认时,可以在物理网卡上抓包,用 Wireshark 显示过滤器 dns || tcp.port == 853 || udp.port == 853 检查传统 DNS、DoT 或 DoQ 的相关流量。DoH 通常使用 443 端口,不能仅靠此过滤器识别;需要结合目的地址和内核连接记录。网卡上出现代理服务器连接是正常现象,不能把所有出站流量都当成泄漏。

配置字段对照:nameserver、fallback 与 respect-rules

字段作用排查重点
enable启用内核 DNS 模块。启用后还要确保应用查询能到达它。
listen提供本地 DNS 监听入口。127.0.0.1:1053 不会自动改写系统 DNS。
enhanced-mode选择 fake-ip 等处理模式。映射机制与上游连接路径是两回事。
nameserver设置默认解析上游。检查协议、可达性,以及它最终走直连还是代理。
fallback提供另一组解析上游。配合过滤条件选择结果,不是单纯等主上游失败才查询。
fallback-filter依据地址或域名等条件筛选结果。筛选结果不等于阻止另一组上游收到查询。
respect-rules让 DNS 上游连接遵循路由规则。只写 true 不够,还要配置节点域名解析并检查规则顺序。
proxy-server-nameserver专门解析代理服务器域名。避免建立代理前又依赖该代理解析节点的循环。
default-nameserver用于解析 DNS 上游自身的域名。属于引导解析,不是默认业务查询上游;也要纳入隐私边界。

例如,同时配置运营商 UDP DNS 与境外 fallback,即使最后采用境外解析结果,也不意味着运营商完全没有收到查询。若目标是减少向本地明文 DNS 暴露业务域名,应先移除不必要的明文上游,而不是只调整 fallback-filter。

nameserver-policy 还能为特定域名指定不同上游。已有订阅若保留了这个字段,部分域名可能不走你刚修改的默认 nameserver。排查时应查看最终运行配置,而非只看新增片段。加密 DNS 则保护设备到解析服务之间的查询内容,解析服务本身仍能处理并看到域名。

mihomo fake-ip 配置段:明确上游与代理路由

以下是可合并到现有 mihomo 配置的 DNS 片段,不是完整订阅。它使用 IP 地址形式的 Cloudflare DoH 上游,减少为解析服务域名做引导查询的需求。使用前确认该解析服务符合你的网络政策,并且代理节点能访问它。原配置若有 fallback 或 nameserver-policy,应一并检查,不能假定粘贴片段会自动删除旧字段。

# DNS 配置片段:替换或合并现有 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:
    - "*.lan"
    - "localhost"
  respect-rules: true
  nameserver:
    - https://1.1.1.1/dns-query
  proxy-server-nameserver:
    - https://1.1.1.1/dns-query

这里的 ipv6: false 是为了先把内核 DNS 的 AAAA 结果从排查变量中移开,不等同于关闭系统 IPv6,也不能阻止其他应用自行获取 IPv6 地址。需要 IPv6 时,应在确认接管和出口支持后恢复,并单独测试 IPv6 链路。

把业务 DNS 上游送进真实代理策略

respect-rules: true 会让业务 DNS 上游连接遵循规则。若配置有大陆直连、其他直连或兜底直连,必须明确该上游应该去哪。下面这条规则需放在已有 rules 列表的靠前位置,先于宽泛的 IP 规则与 MATCH。示例假定现有策略组确实叫 PROXY;名称不同就改成你的真实策略组名,不要新增第二个 rules 键。

# 规则片段:插入现有 rules 列表,保留原有其他规则
- IP-CIDR,1.1.1.1/32,PROXY,no-resolve

还需在“代理”页确认 PROXY 当前选中的是代理节点,而不是 DIRECT。上述规则用于业务解析上游的连接;proxy-server-nameserver 属于建立代理所需的节点域名解析路径,不能要求它依赖尚未建立的同一代理。该示例的节点引导解析使用直连加密 DoH,本地网络仍可观察到与解析服务的连接,解析服务仍会处理节点域名。

fake-ip-filter 只添加确有需求的域名

需要真实地址的局域网设备或特定应用,可以加入 fake-ip-filter。过滤后改为返回真实地址,并不自动代表直连,也不是阻止 DNS 泄漏的开关。不要为了修复一个设备,把所有域名都加入过滤列表,否则会失去 fake-ip 保留域名映射的主要收益。

TUN 与浏览器设置:把查询纳入接管范围

系统代理主要影响遵守代理设置的应用,并不能普遍接管 UDP DNS。希望接管更多应用时,可以在具备系统权限的前提下使用 TUN。Windows 通常需要客户端服务模式或管理员权限;macOS、Linux 也需要对应的授权或权限配置。先确认虚拟网卡成功创建,再谈 DNS 劫持,避免只打开界面开关就认为接管已经完成。

# 可选 TUN 配置片段:与上面的 dns 段配合
tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

这段配置用于把进入 TUN 的常规 UDP、TCP 53 查询交给内核 DNS,实际效果仍取决于操作系统、路由与内核支持。系统 DNS 设置通常只接受服务器 IP,不能填写 127.0.0.1:1053 这种带端口地址;没有 TUN 时,若要让系统直接使用本地解析器,需要另外设计 53 端口监听,并处理权限及端口冲突。

  • Chrome:“设置”→“隐私和安全”→“安全”→“使用安全 DNS”。诊断时暂时关闭,再比较检测结果。
  • Firefox:“设置”→“隐私与安全”→“DNS over HTTPS”。检查保护级别和指定提供者;不同版本的中文名称可能略有差异。
  • Android:检查系统“设置”中的“私人 DNS”。菜单位置随厂商变化,它的加密查询不属于普通 UDP 53 劫持范围。

浏览器 DoH、系统 DoT 使用独立加密连接,dns-hijack 不会把它们拆解成内核普通 DNS。可以保留这些功能,但必须验证对应连接是否按预期走代理。关闭它们只是诊断方法,不是唯一的长期方案。

修改后无法联网:按依赖链排查

现象先检查处理方向
本地 1053 查询超时配置加载错误、DNS 启用状态、端口占用。先让本地查询成功,再检查网页检测结果。
节点使用域名时无法连接proxy-server-nameserver 是否可达。修复节点引导解析,避免解析与代理互相依赖。
节点连接正常,域名访问超时DoH 上游路由和策略组当前选择。确认上游连接命中代理,代理能访问解析服务。
只有部分局域网应用异常是否收到 fake-ip、是否需要真实局域网地址。添加最小范围的过滤与局域网绕行规则。
检测仍出现未预期解析器浏览器 DoH、私人 DNS、其他 VPN 和 IPv6。逐项关闭做对照,定位旁路后再决定保留方式。

每次只改一个层面:先 DNS 上游,再规则,再 TUN,最后处理浏览器和系统的独立解析。一次同时换节点、开 TUN、改系统 DNS,很难判断是哪项生效。若启用 TUN 后整机断网,先关闭 TUN 恢复网络,再检查默认路由、权限和其他 VPN 冲突,不要继续叠加不同 DNS 地址。

最终复测清单

  1. 本地 1053 查询能返回预期映射地址,内核日志没有持续解析超时。
  2. 业务 DoH 连接命中指定代理策略,节点域名解析有独立可用的引导路径。
  3. 网页检测结果的解析服务符合预期;不以“解析器 IP 必须等于节点 IP”为标准。
  4. 浏览器安全 DNS、系统私人 DNS、IPv6 和局域网应用分别完成测试。
  5. 重启客户端、更新订阅后再次复测,确认覆写持久生效。

DNS 防泄漏配置的关键不是把某个字段设为 true,而是让接管、映射、上游和路由形成可验证的链路。更换网络、节点或客户端内核后,都应重复这一轮对照。需要补充端口、策略组和启动设置,可以查阅进阶手册的端口说明与帮助中心的故障排查。