关于 DNS 泄露及其相关误解的说明

尽量澄清 DNS 泄露的常见误解,解析系统代理与 TUN 透明代理模式下泄露的成因,并给出通过优化分流规则和 fake-ip 模式彻底规避泄露的实用方案。

点进这篇文章的人想必基本都对 DNS 泄露这一概念有所耳闻了,其中也不乏谈 DNS 泄露色变者,由于评论区和 Issue 里提出相关问题的人已经有数位,鄙人这次写一篇说明,尽可能将这个问题讲清楚,澄清一些大家对这个概念可能的误解,也为各位编写自己的代理配置提供一个参考。

这个概念已经被一些 VPN 厂商和一大堆 YouTuber 讲烂了,基本的意思是:当你在代理时,电脑却通过本地网络向本地 DNS 请求你正在访问的网址,使得运营商可以依据你的 DNS 请求记录得知你的浏览记录。

搞清楚需求

首先需要想明白的是,我们煞费苦心地防止 DNS 泄露究竟是为了什么——大家的第一反应可能都是:「那还用说!肯定是为了不让审查者看到我们通过代理访问了哪些网站啊!」

其实这个说法并不完全准确,具体还得看情况。不妨想一想:让审查者知道你在刷抖音、聊微信会有什么实质性的危害吗?恐怕没有。但如果让审查者发现你在访问维基百科、浏览 X(推特)或者其他带有明确政治倾向的敏感内容,那问题就有点大了。防止 DNS 泄露的目的,从来不是为了让你在所谓的「DNS 泄露测试」网站上拿到一个全绿的满分,也不是为了隐藏你使用国内常用服务的事实,而是为了不让审查者知道你在访问那些被封禁、被视为敏感的网站和服务。

对于生活在墙内的我们来说,区分什么是敏感内容其实非常简单:直接参考 GFWList1 即可——能让 GFW 专门将其重点关照的,自然就是敏感内容。

那些 DNS 泄露测试的网站,测试用的随机域名甚至连 GFWList 的边都沾不上,本身就毫无敏感性可言。对于一些经过优化的正常代理配置来说,这类域名连看都不想多看一眼,通常会直接被略过并扔给最后的兜底规则(比如 MATCH, DIRECT)去处理,这个过程自然而然地触发了本地 DNS 解析。于是,测试网站便如获至宝般地亮起红灯,警告你「存在 DNS 泄露」。但明白机制的我们自然清楚,很多时候这种所谓的泄露完全是无关痛痒的,只要配置得当,你真正需要保护的敏感访问记录,早就匹配到前面的分流规则被安全地送进加密隧道了。

更有甚者,诸如 Surfshark、ExpressVPN 这类海外商业 VPN 厂商,以及一众跟着恰饭的无良 YouTuber,成天拿这种毫无实际意义的测试结果制造隐私焦虑。可笑的是,这些传统的商业 VPN 客户端往往连最基础的域名分流规则功能都不具备,全靠粗暴的一把梭将所有网络请求强行塞进虚拟网卡。而更讽刺的是,即便是这种简单粗暴的全局代理,他们过去还曾因为自身客户端软件的缺陷,真真切切地导致过 DNS 泄露问题。所以,与其听信这些贩卖焦虑的恰饭营销,不如自己弄懂代理软件的运作原理。

出现泄露的环节

其实现在主流的代理软件都比较成熟,配置得当完全不需要担心 DNS 泄露的问题。问题出就出在很多配置根本就不得当。接下来我将会简要地解释代理软件在系统代理模式和透明代理(虚拟网卡)模式下可能出现 DNS 泄露的环节。

代理软件本身

在使用系统代理的情况下(假设代理地址是socks5://127.0.0.1:78902)用浏览器访问https://www.example.com,会经历如下的请求过程:

  • 第一步:浏览器会把网络请求打包发送给socks5://127.0.0.1:7890
  • 第二步:代理软件收到请求后根据配置的分流规则匹配节点
  • 第三步:代理软件根据匹配结果向节点转发整个网络请求

在整个发起请求的过程中,浏览器将网络请求打包交给代理,不会向本地 DNS 发出请求,这一环节不会产生 DNS 泄露;代理软件将网络请求转发给服务器,整个过程加密,也不会产生 DNS 泄露;真正产生 DNS 泄露的环节,是根据分流规则匹配的过程。

向本地 DNS 发起域名查询这件事情本身并不一定是坏事,但配置不当的分流规则会让代理软件在拿到域名后过早地向本地 DNS 发起查询,导致泄露不应泄露的隐私信息。假设在极端情况下,盖世太保从运营商调取所有人的 DNS 查询记录,凡是查询过域名包含 GFW 封锁列表中的项目者都拉出去枪毙,在这种情况下,为了保全自身,我们需要恰当地配置分流规则。

以使用广泛的 Mihomo 内核为例,在作为客户端开启系统代理模式、使用 Chrome 进行到前文所述的第二步时,内核已知的信息有:

  • 主机3example.com
  • 目标端口:443
  • 网络协议:TCP
  • 发起请求的进程的名称和具体路径:C:\Application\chrome.exe
  • 入站 IP:127.0.0.1
  • 入站名称:DEFAULT-MIXED
  • 入站端口:随机的高位端口

内核不会进行多余的 DNS 请求,根据已知的信息,内核可以在不发起 DNS 解析的情况下,匹配所有基于域名、端口、进程名称以及网络协议匹配的路由规则:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
rules:
  # 基于域名的匹配规则
  - DOMAIN,ad.com,REJECT
  - DOMAIN-SUFFIX,google.com,auto
  - DOMAIN-KEYWORD,google,auto
  - DOMAIN-WILDCARD,*.google.com,auto
  - DOMAIN-REGEX,^abc.*com,PROXY
  - GEOSITE,youtube,PROXY
  # 基于端口的匹配规则
  - DST-PORT,80,DIRECT
  - SRC-PORT,7777,DIRECT
  # 基于进程名称的匹配规则
  - PROCESS-PATH,/usr/bin/wget,PROXY
  - PROCESS-PATH,C:\Application\chrome.exe,PROXY
  - PROCESS-NAME,curl,PROXY
  - PROCESS-NAME,chrome.exe,PROXY
  # 基于网络协议的匹配规则
  - NETWORK,UDP,REJECT
  # 不依赖任何信息的匹配规则
  - MATCH,DIRECT

因此,上述这些种类的规则不会产生 DNS 泄露,因为内核匹配它们的时候根本没必要发起 DNS 解析。

对于剩下种类的规则,需要在第二步获知目标 IP 信息才能让匹配进行下去:

1
2
3
4
5
rules:
  - GEOIP,cn,DIRECT
  - IP-CIDR,127.0.0.0/8,DIRECT
  - IP-SUFFIX,8.8.8.8/24,PROXY
  - IP-ASN,13335,DIRECT

在默认情况下,为了确保匹配的准确性,进行到第二步时,内核不知道目标 IP,只知道目标主机地址www.example.com,此时内核不得不对www.example.com的 IP 地址进行查询,这也就造成了 DNS 泄露。如果在规则的末尾加上no-resolve4,则匹配到基于 IP 的规则时会直接跳过,这就使得no-resolve很适合用来分流 Telegram 等软件的裸 IP 请求。

透明代理的问题(TUN 模式5

透明代理顾名思义即被代理的系统/软件感知不到自己被代理了的代理方式。这种方式非常省事,TUN 模式一开,所有软件通通都能用,无须繁琐的逐一配置不遵循系统代理的软件。代价就是这种省事本身——目标系统/软件都不知道自己被代理了,他们在正常网络上该有的行为都会照常进行,其中自然也包括 DNS 解析,可是目标系统/软件并不知道自己被代理了,他们想要和远端建立连接,总得要先拿到一个 IP 才行吧。为了解决这个问题,以 Mihomo 为例,有两种 DNS 劫持模式,redir-hostfake-ip

redir-host 模式:

fake-ip 模式:

其中redir-host比较老实,既然目标系统/软件发起了 DNS 查询,那就老老实实通过上游 DNS 去查,把查询到的真实的 IP 返回给目标系统/软件。由于这种模式下系统必定会发生一次真实的 DNS 解析请求寻址过程,存在着先天的结构性缺陷,不可避免地会造成 DNS 泄露。原来的 Clash 核心在后续的版本更新中干脆直接砍掉了 redir-host 模式。

不过,继承了 Clash Meta 核心的 Mihomo 内核选择了将其保留下来,并且加入了sniffer6对其进行增强。在redir-host模式下,sniffer依靠嗅探数据包中的特征(比如从 TLS 的 SNI 字段7)尝试将被解析成裸 IP 的流量恢复成连接域名,再用这个域名走一遍分流规则的匹配,补齐了redir-host模式在分流上的诸多短板。但需要特别注意:sniffer 解决的是分流准确性的问题,并不能消除 DNS 泄露本身——DNS 查询请求在 sniffer 介入之前就已经发出去了,运营商该记录的早就记录了。

但这里需要提醒:如果你在透明代理环境下仍然坚持使用redir-host模式,就必须在配置一套无污染的 DNS,具体的例子可以参考我的另一篇文章,否则你的 DNS 访问记录依然会泄露。

相对而言,fake-ip模式则采用了截然不同的解决思路,不仅完美规避了透明代理环境下的 DNS 泄露问题,甚至还能顺带提升浏览器的网页响应速度。

如何规避 DNS 泄露

优化喂给代理软件的分流规则

还是以 Mihomo 内核为例,规则的匹配是从上到下顺序进行的,内核每收到一个请求都会按顺序从上到下一条一条地匹配,直到匹配到目标规则为止。这也就意味着如果一个域名已经被第一条规则匹配,之后的第二、第三、乃至第一千万条规则的匹配流程都不会触发。

基于这一点,我们编写规则时应当要遵循「域名规则在前,IP规则在后」的总原则,即使是针对某个特定服务的规则集,也要为其中的 IP 规则加入no-resolve标记,一个典型的例子如下:

1
2
3
4
5
6
7
DOMAIN-SUFFIX,e-hentai.org
DOMAIN-SUFFIX,ehgt.org
DOMAIN-SUFFIX,ehwiki.org
DOMAIN-SUFFIX,exhentai.org
DOMAIN-SUFFIX,hath.network
DOMAIN-SUFFIX,hentaiverse.org
IP-CIDR,178.175.128.0/21,no-resolve

当使用 GeoSite 和 GeoIP 数据库时,也应当为靠前的 IP 规则添加no-resolve标记。

1
2
3
4
5
6
rules:
  - GEOSITE,telegram,Telegram
  - GEOIP,telegram,Telegram,no-resolve
  - GEOSITE,gfw,Proxy
  - GEOIP,cn,DIRECT
  - Match,Proxy

就以上面的配置规则为例,当我们的设备发起不同类型的网络请求时,Mihomo 内核会按照自上而下的顺序进行规则匹配。具体流程可以通过下面的图表来梳理:

从上述流程图中我们可以清晰地看到规则顺序和 no-resolve 属性的作用。当我们访问 Telegram 服务时,由于命中了靠前的 GEOSITE 或带有 no-resolveGEOIP 规则,请求被直接路由至代理,完全避免了在这一环节产生 DNS 解析。

同理,当我们访问其他任何在 GFW 列表上的网站时,会在匹配到 GEOIP,cn,DIRECT 这条不得不触发本地 DNS 解析的规则之前,就率先匹配到了 GEOSITE,gfw,Proxy 规则。此时代理软件直接将请求转发至节点,后续基于 IP 的规则因为不再执行,相关的 DNS 解析请求也就被成功避免,杜绝了因为 DNS 请求导致敏感浏览记录泄露的可能性,审查者再也不会知道你在访问敏感的网站和服务了。

用 Fake-IP 规避透明代理问题

相比优化分流规则,fake-ip 模式则从根源上解决了透明代理下的 DNS 泄露问题,不仅完美规避了泄露风险,甚至还能顺带提升浏览器的网页响应速度。

原理非常巧妙:当目标软件发起 DNS 查询时,代理软件并不会傻乎乎地去本地或远端上游查询真实 IP,而是直接在本地瞬间返回一个假的内网保留 IP(例如198.18.0.28)。目标软件拿到这个假 IP 后信以为真,紧接着就会拿着这个假 IP 尝试建立连接。

而在代理软件这里,它只需要拦截所有发往自己签发过的这些假 IP 的请求即可。由于代理软件内部维护了一张详细的「假 IP 对应真实域名」的映射表,所以即便目标软件发来的是往假 IP 发送的包,代理软件依然心知肚明你其实想访问的是什么域名。于是,代理软件直接提取出原始域名,将网络请求顺着加密代理隧道发往远端节点去处理。

在整个fake-ip模式的精妙配合下,你的设备对外不仅没有泄露隐私的 DNS 请求,甚至可以说针对这些由代理软件接管的流量根本就没有向外部发起过常规的 DNS 查询,审查者自然无从得知你要访问何处。同时由于免去了本地苦等 DNS 真实响应的时间,还能顺带大幅度降低网页访问的首字节加载延迟(TTFB9),一石二鸟。

太长不想读(小结)

DNS 泄露本身并不可怕,可怕的是不明就里地被焦虑营销牵着鼻子走。理解了机制之后,应对思路其实很清晰:

  • 系统代理模式:遵循「域名规则在前,IP 规则在后」的原则,为所有 IP 类规则加上 no-resolve,敏感域名在触发 DNS 解析之前就已经被分流走了。
  • TUN 透明代理模式:优先选用 fake-ip,从根源上杜绝 DNS 查询外泄,同时还能获得更低的 TTFB。如果坚持使用 redir-host,必须搭配无污染的上游 DNS,且要清楚 sniffer 只能改善分流准确性,无法阻止 DNS 请求本身的泄露。
  • 不要迷信泄露测试网站:测试用的随机域名根本不在 GFW 封锁列表内,触发本地解析是正常且无害的行为,绿灯与否不是衡量配置质量的标准。

  1. 被中国大陆防火长城(Great Firewall, GFW)封锁的域名列表。 ↩︎

  2. SOCKS5 是一种网络代理协议(RFC 1928),工作在会话层,支持 TCP 和 UDP 转发,且允许客户端将域名直接传递给代理服务器解析,而非在本地解析后再连接——这正是它在防止 DNS 泄露方面优于普通 HTTP 代理(非 CONNECT 隧道模式)的关键特性。 ↩︎

  3. 可以理解为域名。 ↩︎

  4. no-resolve 是附加在 IP 类规则末尾的标记,作用是告诉内核:当流量的目标是域名而非 IP 时,跳过此规则,不要为了匹配它而主动发起 DNS 解析。但如果流量本身就是直接连接 IP(如 Telegram 客户端直连服务器 IP),则该规则仍然会正常参与匹配。 ↩︎

  5. 也就是我们所说的虚拟网卡模式 ↩︎

  6. 流量嗅探(Sniffer)是指代理软件通过检查数据包的协议特征来还原目标域名的技术。例如,HTTPS 连接在握手阶段会以明文发送目标域名(即 SNI),HTTP 请求头中也包含 Host 字段,代理软件可以从这些特征中提取出真实的目标域名。 ↩︎

  7. Server Name Indication,TLS 协议的扩展字段。由于同一 IP 上可能托管多个 HTTPS 站点,客户端在 TLS 握手的 ClientHello 阶段需要以明文告知服务器自己要访问哪个域名,以便服务器返回正确的证书。这也是为什么即使使用了 HTTPS,中间人仍然能看到你访问的域名(但看不到具体路径和内容)。 ↩︎

  8. Mihomo 默认使用 198.18.0.0/15 地址段分配假 IP。该地址段由 IANA 在 RFC 2544 中保留,专门用于网络设备基准测试,不会出现在正常的互联网路由表中,因此不会与任何真实的公网地址冲突。整个 /15 段可提供约 131,072 个地址供映射使用。 ↩︎

  9. Time To First Byte,即从客户端发出请求到收到服务器响应第一个字节所经过的时间。在传统模式下,浏览器需要先等待 DNS 解析完成(通常耗时 20-120ms)才能发起 TCP 连接;而 fake-ip 模式下 DNS 响应几乎是瞬时的(<1ms),因此能显著缩短整体的页面加载时间。 ↩︎

采用 CC BY-NC-SA 4.0 协议进行许可
最后更新于 2026 年 5 月 18 日 12:16 +0800