代理客户端的 DNS 泄露问题

1)我最近发现代理客户端会把几乎我访问的每个域名都在本地发送给 DNS 服务商,包括 youtube.com,甚至我不愿意公开给别人的网站。

2)我发现一些客户端不会遵守你设置的 DoH 服务,会把 DNS 查询继续给你系统设置里面的 ISP 运营商。

你以为你上网记录是私密的,但结果全部都公开给了运营商。

在使用 Stash 这个基于 Clash 内核的 iOS 客户端时,我很意外地发现好像大多数域名请求都通过未加密的 DNS 请求发给了阿里 DNS 服务器,甚至包括一些 google.com 这样已经在规则中出现过的域名。这其实是很大的隐私疏失,也可能造成一种虚假的安全感。

DNS 请求在本地被发出并不奇怪。除非一个域名在配置文件的规则当中出现,代理工具需要解析这个域名的 IP 地址,再匹配 GEOIP 数据库得到它位于中国以内或者以外,根据这个来直连或者通过代理发送。

如果一定要分流,又不希望自己的上网记录被发送给 ISP,就要用 DoH。而在 2025 年的 3 月,包括 dns.google 和 1.1.1.1 在内的海外 DoH 服务器已经被封锁,表现为 443 端口不能连接。

怎么测试一个 DoH 服务是否可以正常连通?在终端运行类似下面的指令,

curl -H "Accept: application/dns-json" "https://cloudflare-dns.com/dns-query?name=cloudflare.com&type=A"

(备注,cloudflare-dns.com 是 DoH 服务的域名,而 cloudflare.com 是需要解析的域名。)

正常会返回如下结果,

{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"cloudflare.com","type":1}],"Answer":[{"name":"cloudflare.com","type":1,"TTL":260,"data":"104.16.133.229"},{"name":"cloudflare.com","type":1,"TTL":260,"data":"104.16.132.229"}]}

如果服务被封锁,会得到连接被重置的提示,

curl: (35) Recv failure: Connection was reset

自己创建一个境内可用的海外 DoH 服务有两个思路,

  • 用 CDN 服务代理 Cloudflare DNS 的域名 cloudflare-dns.com 或者 mozilla.cloudflare-dns.com
  • 或者自己租一台位于亚太区域且延迟和丢包率都可以接受的服务器搭建 AdGuard 的 DNS 服务。

但即使有了可用的海外 DoH 服务,一些代理客户端依然会发生DNS 请求泄露的情况,或者默认会替换掉你配置的 DNS 设置。以下是对于各平台代理客户端的 DNS 泄露测试。

我会在代理客户端里面配置使用一个位于新加坡的 Cloudflare DoH URL 作为唯一的 DNS 服务,连接到一个位于新加坡 VMESS 服务,然后访问 https://browserleaks.com/dns 来测试。()

客户端通过?测试结果
Shadowrocket (iOS)DNS 解析用的服务似乎非常随机。测试了连接一个日本 SS 代理服务。
❌ 如果使用 DoH 作为 DNS 服务,而备用 DNS 清空:57 台服务器,4 个 ISP(来自中国网通,新加坡 Cloudflare,中国联通) – 发生了 DNS 泄露
❌ 重置 Tunnel。重置了配置文件,使用系统默认,使用未加密的阿里 DNS 而备用 DNS 清空,选择一个日本代理服务:84 个服务器,5 个 ISP(日本 Cloudflare,日本 i3D.net B.V,日本 Google LLC,中国联通)- 评:WTF?
❌ 继续使用默认配置文件,将 DNS 服务器和备用 DNS 服务器都填写未加密的阿里 DNS:同上,84 个服务器,5 个 ISP(日本 Cloudflare,日本 i3D.net B.V,日本 Google LLC,中国联通)
Stash (iOS)✅ 59 台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露
Outline (iOS)✅ 6 台服务器,1 个 ISP(来自 VPS 所在的日本 Cloudflare) – 未发生 DNS 泄露
Surge (iOS)✅ 25 台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露
Clash Verge Rev (Windows)⚠️❌ Tun 模式下 – 74 台服务器,4 个 ISP(来自中国网通,新加坡 Cloudflare,被标示为两个不同 ISP 的中国联通) – 发生了 DNS 泄露
✅ 代理模式下 – 64 台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露

Also, 当前版本的客户端在 Settings 里面默认开启 DNS overwrite,默认情况下会忽略配置文件的 DNS 配置而将域名解析请求发给系统 DNS、阿里 DNS(加密 DoH 和未加密)、腾讯 DNS(加密 DoH)、Google DNS(未加密)
Outline (Windows)26 台服务器,1 个 ISP(来自 VPS 所在的日本 Cloudflare) – 未发生 DNS 泄露
V2RayN (Windows)* 代理模式下 – 51 台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露
* Tun – 不能正常运作 – failed to read http request > malformed HTTP request “\x00”
Clash Meta (Android)54 台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露
Surfboard (Android)62台服务器,1 个 ISP(来自新加坡 Cloudflare) – 未发生 DNS 泄露
Outline (Android)6 台服务器,2 个 ISP(来自 VPS 所在国日本的 i3D.net B.V.) – 未发生 DNS 泄露

对于 Shadowrocket 的更多测试:

再测试连接一个新加坡 VMESS 代理。
✅ 如果使用未加密的 1.1.1.1 作为 DNS 服务而备用 DNS 清空:61 台服务器,2 个 ISP(来自新加坡 Cloudflare)
❌ 如果使用未加密的 223.5.5.5(阿里 DNS)作为 DNS 服务而备用 DNS 清空:50 台服务器,2 个 ISP(新加坡和美国的 Cloudflare,中国联通) – 看起来设置根本没有生效,重启应用照旧
之后不管如何切换配置文件或者更改设置都得到上述结果。于是重置了 Tunnel 和配置文件。
❌ 填写未加密 1.1.1.1 作为 DNS:59 个服务器,4 个 ISP(中国网通,新加坡 Cloudflare,2 个不同的中国联通)
✅ 填写海外 DoH:51 台服务器,1 个 ISP(新加坡 Cloudflare,美国 Cloudflare)
❌ 再次测试:53 台服务器,2 个 ISP(新加坡 Cloudflare 和中国联通)

发现是,

  1. iOS 平台的 Shadowrocket 存在严重的 DNS 泄露问题,工作非常不稳定,不应该继续使用这个 app;
  2. Outline 会把所有 DNS 请求转发到远程服务器,它在 DNS 泄露上面最不可能出问题如果要使用标准 Shadowsocks 以外的协议;
  3. Clash 内核的客户端在 Windows 端应该避免开启 Tun 模式,一定要改掉 DNS Overwrite 里面的设置(或者直接把 Overwrite 关掉);
  4. 避免使用 Shadowsocks 官方的 Android 和 Windows GUI 客户端,除非你已经在这些平台的系统层级配置好了加密 DNS 服务。

对于中国的很多开发者和服务提供者来说,上网记录安全隐私并不是放在第一位的事情,连通性和响应时间才是。如果重视自己上网记录的隐秘性,就应该在上网之前运行一次 DNS leak test,知道自己的上网记录被分享给了哪些服务商。


Discover more from Poison Ivy

Subscribe to get the latest posts sent to your email.

Leave a Reply