NDS泄露

tim-qtp2025年2月8日...大约 16 分钟DNSTUN/TAPVPN虚拟网卡

开始之前先用 https://ipleak.net/open in new window 这个网站查看一下你的DNS请求是否有泄露。

如果列表中有国内的DNS服务器,那肯定泄露了。即使没有国内的 DNS,如果同一个节点使用全局模式和分流模式的检测结果不同,出现了新的 DNS 提供商,也大概率泄露了。并且直接把 DNS 泄露检测的网站添加到分流规则中来绕过 DNS 泄露,是一种掩耳盗铃的做法。

DNS 的泄露会导致运营商或者防火墙知道你在访问 GoogleYouTubeFacebook 等网站,说白了就是知道你在科学上网。另外,像 Netflix 这种对地区敏感的应用,会通过 DNS 来判断你的实际所在地。如果存在泄露,将会被判定为使用了代理工具,可能无法使用他们的服务。

这篇主要讲讲为什么 DNS 会泄露,以及移动端和 PC 如何解决 DNS 泄露,顺便能解决有时无法访问部分网站的情况。

但是开始之前还有一个名词叫DNS污染:

DNS 污染的原理

  1. 正常 DNS 查询流程
    • 你的设备向 DNS 服务器发送查询请求(如 facebook.com)。
    • DNS 服务器返回正确的 IP 地址(如 31.13.71.36)。
  2. DNS 污染的流程
    • 攻击者或干扰者伪造 DNS 响应,返回一个错误的 IP 地址(如 1.2.3.4)。
    • 你的设备接收到伪造的响应,并尝试连接错误的 IP 地址。
    • 结果可能是无法访问目标网站,或者被重定向到钓鱼网站。

DNS 污染的实现方式

  1. 中间人攻击(MITM)
    • 攻击者在你的设备和 DNS 服务器之间拦截并篡改 DNS 响应。
  2. 伪造 DNS 服务器
    • 攻击者运行一个恶意 DNS 服务器,返回虚假的 IP 地址。
  3. 网络运营商或政府干扰
    • 某些国家或地区通过 DNS 污染技术屏蔽特定网站(如 Google、Facebook)。

如何防止 DNS 污染?

  1. 使用加密 DNS
    • 启用 DNS-over-HTTPS(DoH)或 DNS-over-TLS(DoT),加密 DNS 查询,防止被篡改。
    • 例如:在浏览器中启用 DoH(如 Firefox 的加密 DNS 功能)。
  2. 更换可靠的 DNS 服务器
    • 使用受信任的公共 DNS 服务器,如:
      • Google DNS:8.8.8.88.8.4.4
      • Cloudflare DNS:1.1.1.11.0.0.1
  3. 使用 VPN
    • VPN 可以加密所有网络流量,包括 DNS 查询,防止 DNS 污染。
  4. 手动修改 hosts 文件
    • 对于经常访问的网站,可以在本地 hosts 文件中直接绑定域名和正确的 IP 地址。

接下来讲解DNS泄露!

DNS泄露(DNS Leak)是指在使用虚拟专用网络(VPN)时,设备的DNS请求并没有通过VPN隧道加密发送,而是通过用户的默认DNS服务器(通常由本地互联网服务提供商提供)发送。这样就暴露了用户正在使用VPN访问的内容,使用VPN的意义就大打折扣,甚至可能有攻击者通过伪造DNS记录,窃取到本该通过VPN通道发送的内容,

DNS 原本是一个非常简洁明了的协议,就是负责将域名解析成 IP

但是为了实现分流,让这个原本简单的协议在代理中应用变得异常复杂。有些不正确的配置以为自己没漏,实际上早已露出了鸡脚。

要解释清楚 DNS 泄露是怎么产生的,就需要先来了解 DNS 的工作流程。先来创建一个最常见的家庭网络环境。你在运营商拉了一条宽带,它会给你分配一个光猫。一般来讲,你会单独再买一台路由器连着光猫,路由器通过 PPPoE 拨号,获取运营商分配的公网 IPDNS 服务器。假设公网 IP2.2.2.2DNS 服务器一般会分配两个,假设其中一个的 IP3.3.3.3。同时,路由器作为局域网的网关,会有自己的内网 IP 地址,假设为 192.168.0.1。家里的所有网络设备都会连接到这台路由器,路由器通过 DHCP 为每一台网络设备分配一个内网 IP 以及默认网关、DNS 等信息。一般情况下,默认网关和 DNS 服务器都是路由器。这是最常见的家庭网络拓扑。

首先,浏览器会检查浏览器 DNS 缓存里是否有百度的 IP,发现缓存列表中并没有。除去浏览器的 DNS 缓存,操作系统本身也有 DNS 的缓存列表,可以通过 ipconfig /displaydns 查询,其中包含我们在系统 hosts 文件中手动添加的绑定记录。

如果在操作系统 DNS 缓存中也没有找到,浏览器会构建一条 DNS 查询的应用层数据包,内容是百度的 IP 地址是多少。 DNS 服务的默认端口是 53,默认传输方式是 UDP,所以传输层会以 UDP 的方式进行封装,并且目标端口是 53。网络层会封装源 IP 和目标 IP,源 IP 是本机电脑的 IP,目标 IP 是本机电脑配置的 DNS 服务器,也就是路由器的 IP 192.168.0.1。接着封装 MAC 地址,并从网口发出数据,会来到路由器。

路由器一看目标 IP 是自己,于是会一层层地解封装,得到电脑的 DNS 请求。

路由器同样首先检查自己的 DNS 缓存列表中是否有百度的 IP 地址,发现并没有。

于是会构建一条 DNS 查询的应用层数据包,内容同样是 baidu.comIP 地址是多少,目标 IP 为路由器配置的上游 DNS 服务器 3.3.3.3,并将其发送到互联网。

数据包会来到运营商给我们分配的 DNS 服务器 3.3.3.3,收到数据后,得知了路由器想要百度的 IP,同样先检查自己的缓存列表,没有的话,再询问其他上游 DNS 服务器。运营商的 DNS 一般会配置多个上游 DNS 服务器,具体发给哪一台,会根据自己的负载均衡策略选择。

假设发给了 IP6.6.6.6 的服务器,并且假设这台服务器没有配置 DNS 转发,所以不会将请求转发给其他 DNS 服务器,而是负责帮我们查询百度的 IP。这里查询过程不详细描述。

我们只需要知道,最终这台 DNS 服务器会找到解析 baidu.com 这个域名的权威 DNS 服务器,并把这条请求交给他。

记住红色部分是我们当前两台服务器通信的 IP。百度的权威服务器收到请求后,他这里会有 baidu.com 这个域名绑定的 IP,于是将 IPTTL 返回给这台 DNS 服务器。

TTLDNS 中表示缓存时间,假设为十分钟。

这台 DNS 收到数据后会缓存下来,并将结果告诉了运营商的 DNS。运营商的 DNS 同样也会将结果缓存,并发回给我们的路由器。路由器也是同样的操作,缓存下来,并将结果发回给我们的电脑。

但是家用路由器的性能有限,可能为了节省内存,会将 TTL 值设置得相对较小,比如 30 秒。

当浏览器获取到 IP 之后,才正式地开始发起访问百度的请求。

如果 TTL 值到期了,则会将记录从缓存中移除,又得重新发起 DNS 请求,获取百度的 IP 了。

为什么需要 DNS,以及 DNS 的执行流程相信大家都清楚了。接下来就是我们今天的主题,为什么会存在 DNS 泄露。DNS 泄露的说法只有在我们使用代理之后才存在。

假设我们当前没有使用代理的情况下查询 DNS 泄露,列表中返回了国内的 DNS 服务器,这只能说明这些 DNS 服务器负责帮我们进行了 DNS 查询,并不代表 DNS 泄露了。如果此时我将电脑的本地 DNS 服务器改成 1.1.1.1,意思是让 1.1.1.1 负责 DNS 解析,列表中返回了美国的 DNS 服务器,这也不能说明 DNS 没有泄露。

只有当我们通过代理访问目标网站时,电脑给互联网发送了请求目标网站 IP 地址的明文 DNS 请求,这种情况就是 DNS 泄露。

要讲清楚这个问题,就必须先来了解这个网站是如何进行 DNS 检测的。按 F12 调出浏览器的开发者面板,来到网络面板,可以看到网站在不停地发送请求,并且每个请求访问的域名都不一样,目的是为了确保我们的 DNS 缓存以及所有上游 DNS 缓存中都没有这条记录。

根据之前的讲解,当浏览器中没有找到缓存,会构建查询域名 IPDNS 请求。

由于域名完全随机,上游 DNS 也不可能会有缓存,请求将被转发到运营商的 DNS。由于运营商配置了多个上游 DNS 服务器,可能会交给不同的上游。

假设交给了第二台,这台 DNS 负责去寻找这个域名的 IP,最终会找到这个域名的权威 DNS 服务器。

由于设置了泛解析,查询任何子域名都能获取到 IP。权威服务器在返回结果给你的时候,偷偷做了一个动作,记录下了 DNS 服务器的 IP 地址,并且告诉了查询 DNS 泄露的网站。

由于每个访问者使用网站进行查询时,域名是完全随机的,也就是说,每个人发起 DNS 查询的域名都不一样,所以网站根据这条查询记录就能知道是你在使用这个 DNS 服务器,再根据 IP 归属地得知这个服务器的地理位置。

由于网站在不停地发送新的域名进行探测,运营商的 DNS 可能会使用不同的上游 DNS,所以可以探测到多个不同的 DNS 服务器 IP 地址。

另外,虽然 1.1.1.1 是任播 DNS,但我们国内使用的话会被反向优化到美国,用美国的 DNS 服务器,那么它的上游 DNS 也肯定是美国的 IP

所以当我将本地的 DNS 改成 1.1.1.1 之后,DNS 泄露查询到的都是美国的 DNS 服务器。

所以 DNS 泄露的并不是你的电脑 IP,而是你上上上上上上游的 DNS 服务器 IP

这里可能松了一口气,觉得并没有什么大不了。但那么再来看一下使用代理之后是一个什么情况。

首先,浏览器要访问谷歌,由于配置了系统代理,浏览器不再进行 DNS 查询,而是直接将访问网站的请求交给我们的代理客户端。

代理客户端拿到请求之后,此时会有两种情况:

  • 一种是不发起 DNS 请求就能判断它是走直连还是走代理,这种情况基本不存在 DNS 泄露;

  • 另一种情况是发起 DNS 请求,获取到 IP 之后,再来根据 IP 判断是走直连还是走代理,这种情况大概率存在 DNS 泄露。即使你配的 DNS1.1.1.1 或者 8.8.8.8 这种国外的 DNS 提供商,只要发起了 DNS 请求,那就泄露了,还会迷惑你,因为查不到国内 DNS,还以为没有泄露。

假设 Clash 使用了 IP 规则进行分流,所以需要先得到谷歌的 IP 地址,于是会发起 DNS 请求,内容是谷歌的 IP 地址是多少。

当这条请求发给互联网的 DNS 服务器之后,问题就发生了。DNS 请求是完全明文的,除非你使用 DoT 或者 DoH 进行加密,或者有些客户端默认会将 DNS 请求通过节点加密进行远程 DNS,这两种情况都会增加延迟,不算是好的方案。

大部分用户都不会进行加密和远程 DNS,也就是说,运营商或者中间任何一台路由器都可以看到你的意图是访问谷歌。后面的情况也就不用我细说了。当你要完谷歌的 IP 之后,马上给其他服务器发送一堆加密数据,鬼都知道你在干啥,甚至可能根据这个行为来封禁节点服务器。

再假设 Netflix 这种对地区要求高的网站,偷偷地发送了一个 DNS请求,如果存在 DNS 泄露,负责跟 Netflix 的权威 DNS 服务器对话的这台 DNS 服务器的 IP 归属地就会和当前访问 Netflix 网站的代理 IP 不是同一个地区,那就判定你在使用 VPN 工具,禁止观看。

当然这是我的假设,实际上 Netflix 有没有这样做,我并不清楚,猜的。从技术角度来讲这是可以实现的,并且是一个非常强的代理特征。这就是 DNS 泄露以及 DNS 泄露所导致的问题。

问题已经提出来了,那要怎么解决呢?

DNS 泄露的原因就是在代理的情况下,本地发送了 DNS 请求,那只要让本地不发送 DNS 请求,直接将数据加密后发给节点服务器,就能避免了。因为加密的数据中已经包含了域名,节点服务器会负责 DNS 并帮我们访问网站

本地进行 DNS 请求获取 IP 的行为只是为了匹配分流规则,所以只要我们的分流规则配置合理,就可以避免发起 DNS,从而降低延迟,解决 DNS 泄露。

v2rayN 的用户比较简单,直接使用客户端提供的绕过大陆路由方式,就能解决 DNS 泄露的问题。更进一步,可以进入路由设置,将域名策略改成 AsIs。如果你以前手动修改过绕过大陆的路由规则,可以双击进入修改,将配置恢复成官方规则即可。

Clash 麻烦一点,因为分流规则都写在订阅文件中。

解决这个问题的话要通过订阅转换,可以使用你信得过的订阅转换地址。在订阅链接中填入你的订阅地址或者节点,远程配置随便选择一个,点击生成订阅,会自动复制到剪贴板。

[custom]
;解决DNS泄露,无分流群组
ruleset=🚀 节点选择,[]DOMAIN-SUFFIX,xn--ngstr-lra8j.com
ruleset=🚀 节点选择,[]DOMAIN-SUFFIX,services.googleapis.cn
ruleset=🚀 节点选择,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/Ruleset/GoogleCNProxyIP.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/LocalAreaNetwork.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/UnBan.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/ChinaDomain.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/ChinaMedia.list
ruleset=REJECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/BanAD.list
ruleset=REJECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/BanProgramAD.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/ChinaCompanyIp.list
ruleset=DIRECT,https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/ChinaIp.list
ruleset=DIRECT,[]GEOIP,CN,no-resolve
ruleset=🚀 节点选择,[]FINAL

custom_proxy_group=🚀 节点选择`select`[]♻️ 自动选择`[]DIRECT`.*
custom_proxy_group=♻️ 自动选择`url-test`.*`http://www.gstatic.com/generate_204`300,,50

enable_rule_generator=true
overwrite_original_rules=true

然后 将 config 远程配置文件的网址删除,把https://cf.buliang0.cf/clash-rules/nodnsleak.iniopen in new window复制过去,将其粘贴到 Clash for Windows 中进行订阅下载。

如果下载失败,可以尝试将远程配置网址进行 URL 编码,或者换一个订阅转换后端。这条就是防 DNS 泄露的订阅地址,使用 Clash 内核的客户端都可以使用这个配置文件。这样设置后,使用系统代理就不会出现 DNS 泄露了。

如果使用 TUN 模式,则还需要进一步设置。

内置 DNS 要使用 fake-ip 模式,不要使用 Clash 已经弃用的 redir-host 模式。默认就是 fake-ip,不要去改它。

还没有完,和系统代理不一样,由于 TUN 模式是操作网络层,对于 DNS 的处理会更复杂。即使规则已经走全局,也还是会发起 DNS 请求。正常情况下,Clash 的虚拟网卡会进行拦截,但由于 Windows 系统默认会将 DNS 请求发给所有网卡上配置的 DNS 服务器,微软美其名曰把它叫做智能 DNS 优化,实际上会造成 DNS 泄露,因为 Clash 拦截不了物理网卡的 DNS 请求。

解决这个问题需要进行简单的设置。在开始菜单中搜索组策略,找到禁用智能多宿主名称解析,双击打开,选择“已启用”,点击应用。这样就可以禁用多网卡的 DNS请求了。

如果你的电脑是win家庭版,可以通过运行以下方式开启策略组:

@echo off
pushd "%~dp0"
dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txt
dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientTools-Package~3*.mum >>List.txt
for /f %%i in ('findstr /i . List.txt 2^>nul') do dism /online /norestart /add-package:"C:\Windows\servicing\Packages\%%i"
pause

然后用管理员身份运行

  1. 安卓的 v2rayNG 是勾选“启动本地 DNS”,启用虚拟 DNS,其实就是 fake-ip。将域名策略改成 AsIs,预定义规则设置绕过局域网以及大陆地址。其他配置按安装时默认的选项即可。记得要断开 VPN 重连,规则才会生效。
  2. Clash 除了要使用刚才的那个远程配置文件进行订阅转换之外,还需要其他设置。进入覆写,将 DNS 策略改成“强制启用”,增强模式改成 fake-ip。点击 nameserver,添加 DNS 服务器,填国内的即可,比如 114。你可以添加多个,这样就算是配置好了。
  3. 最后是 iOS 小火箭。小火箭的默认配置可以避免 DNS 泄露,但是分流不是很完善。可以使用 https://cf.buliang0.cf/shadowrocket-rules/nodnsleak-pk.iniopen in new window 这个配置文件。点击添加配置,将地址粘贴上去,点击下载,选中刚才的这个地址,点击使用配置。最后只需要将全局路由设置为配置模式即可。

这样操作之后就能解决大部分 DNS 泄露的问题了。你可以重新检测 DNS 泄露的情况,只要全局模式和分流模式都是同样的 DNS 提供商,则大概率没有泄露。

没泄漏的情况下,如果看到了多个国家的 DNS 服务器,是你节点配置的上游 DNS 问题。如果是自建的节点,可以修改节点服务器的上游 DNS 解决这个问题。不过也可能是这个网站的 IP 归属地数据库更新不及时导致的。

另外,由于本地基本不再发起 DNS 请求,速度也会有一定的提升,也能解决 DNS 污染导致有些网站无法访问的情况。至于这样做为什么能阻止 DNS 请求,有没有缺点,下节讲 DNS 分流再来细说。

最后再来说一下浏览器的 WebRTC 泄露,会绕过代理直接泄露本机的真实 IP。访问这个网址可以进行查询。如果存在泄露,安装这款浏览器插件,禁用浏览器的 WebRTC 功能,可以防止 IP 地址泄露。