dnsleaktest 显示多个 DNS 服务器?先分清是泄露还是正常现象

dnsleaktest 显示多个 DNS 服务器?先分清是泄露还是正常现象

234
234
2026-10-24 / 0 评论 / 5 阅读 / 5739 字 / 正在检测是否收录...
加密 DNS 主机名:dns.23-4.cn | DoH 地址:https://dns.23-4.cn/dns-query | 配置教程 | 实时战报

跑完一个 DNS 泄露检测,看到页面上列出四五个 DNS 服务器,位置散落在好几个城市甚至不同国家——第一反应通常是「我明明只配了一个加密 DNS,怎么泄露了这么多?」

绝大多数情况下那不是泄露。检测工具列出多个服务器,有三种完全正常的解释,而且这三种的判定方法各不相同。这篇给一套可执行的判定流程,用你自己机器上的命令,不依赖任何第三方页面的结论。

下面所有输出都是我在一台 Ubuntu 20.04(dig 9.18.30)上实际跑出来的。

一、先搞清楚检测工具在测什么

所有 DNS 泄露检测的原理都一样:让你发起 N 次随机子域名的查询,然后问「这些查询最终是谁回答的」。具体做法通常是给你一个独一无二的子域名(比如 abc123.dnsleaktest.com),你查它,它看这次查询从哪个 IP、经过哪台解析器到达。

所以它报告的「DNS 服务器列表」,本质是「你的查询最终落到了哪些递归解析器上」。

关键点:列表里有多个,只说明你的查询分流到了多台解析器,不说明这些解析器不该看到你的查询。

二、三种正常情况,逐个判

情况 1:你有多个出口 IP(多网卡 / 双栈 / 多线)

这是最常见的一种。一台机器同时有 IPv4 和 IPv6,或者接了多条线路,那么:

  • 查 A 记录可能从 IPv4 出口出去;
  • 查 AAAA 记录从 IPv6 出口出去;
  • 检测工具看到两个来源,就报两台服务器。

我手上这台机器就是这样。看它的实际解析路径:

dig +tls @dns.23-4.cn example.com

实测输出(注意 SERVER 那一行是 IPv6):

;; ANSWER SECTION:
example.com.        162    IN    A    104.20.23.154
example.com.        162    IN    A    172.66.147.243

;; Query time: 28 msec
;; SERVER: 240e:95d:3020:43::4006#853(dns.23-4.cn) (TLS)

而如果强制走 IPv4 传输:

dig +tls -4 @dns.23-4.cn example.com | grep SERVER

SERVER 行会变成 IPv4 地址。两个不同的服务器地址,落在检测工具眼里就是「两个 DNS 服务器」。但它们是同一个服务,只是走了不同协议栈。

判定方法:把两条路径分别打出来,看 SERVER 行。

echo "--- IPv4 传输 ---"
dig +short +tls -4 @dns.23-4.cn example.com
echo "--- IPv6 传输 ---"
dig +short +tls -6 @dns.23-4.cn example.com

实测这台机器两条都通,解析结果完全一致:

--- IPv4 传输 ---
104.20.23.154
172.66.147.243
--- IPv6 传输 ---
104.20.23.154
172.66.147.243

如果检测工具报的服务器数正好是 2,且你确实是双栈,基本可以判定是这种情况,不是泄露。

情况 2:服务端有多台节点(Anycast / 负载均衡)

加密 DNS 服务商通常会在多个地点部署节点,用 Anycast 让你的查询落到「网络距离最近」的那台。你从不同时间、不同网络去查,落到的节点会不一样。

这类「多个服务器」的特征是:IP 会变,但都属于同一个服务商、同一个域名。

判定方法:反复查同一件事,看 IP 是否漂移。

for i in 1 2 3 4 5; do
  dig +short +tls @dns.23-4.cn example.com | head -1
  sleep 1
done

如果每次拿到的解析结果稳定(这里是 A 记录,跟解析器 IP 无关),说明服务本身没问题;要判断节点是否漂移,得看 SERVER 行:

for i in 1 2 3 4 5; do
  dig +tls @dns.23-4.cn example.com 2>/dev/null | grep -oP 'SERVER: \K[^#]+'
done | sort | uniq -c

出现多个 IP 但都在同一个网段/同一家,就是 Anycast 正常表现。

情况 3:你的设备根本没在用你以为的那个 DNS

这一种确实是问题,但它不是「泄露」,而是「没生效」。

典型场景:你在路由器上配了加密 DNS,但设备的 DHCP 又下发了一个 DNS;或者系统里同时有 systemd-resolved 的 stub 和上游配置。这时不同程序的查询走不同路径。

判定方法:看系统实际在用什么。

# 现代 Ubuntu / Debian
resolvectl status | grep -E "Current DNS|DNS Servers"

# 看 stub 监听(127.0.0.53 说明走的是 systemd-resolved)
ss -tlnp | grep ':53 '

实测我这台机器,两条输出放一起看很有意思:

  Current DNS Server: 2400:3200::1
         DNS Servers: 114.114.114.114

LISTEN 0  4096  127.0.0.53%lo:53  0.0.0.0:*  users:(("systemd-resolve",pid=895990,fd=13))

这台机器实际在用 114.114.114.114——明文 UDP DNS,不是加密 DNS。 我在这台机器上用 dig +tls @dns.23-4.cn 测得很通,但那只证明「命令行能连上」,完全不代表这台机器在用它。这两个事实同时成立,一点都不矛盾。

/etc/resolv.conf 里写着 nameserver 127.0.0.53——这只是指向本机 stub,真正的上游在 resolvectl status 里。很多人看到 127.0.0.53 就以为「没配加密 DNS」,其实那只是中间层;反过来,也有人看到 dig 能通就以为配好了,其实上游还是明文。

这两件事必须分开查,这也是「检测工具报多个服务器」最常见的一个真实来源。

三、什么时候才是真泄露

真泄露的定义很明确:你的查询在你没有授权的地方被解析了。特征是这样的:

特征说明
检测工具报的服务器里,有运营商/ISP 的 IP说明部分查询走了明文 UDP 53
用加密 DNS 和不加密时,报的服务器不一样说明加密 DNS 只覆盖了部分查询
你在设备上抓包,能看到发往 53 端口的明文查询最硬的证据
同一个域名,不同时刻解析结果不同(且不是 TTL 到期)可能被不同解析器分流

最可靠的一条是抓包。在设备上(不是服务器上)跑:

sudo tcpdump -i any -n 'udp port 53 or tcp port 53' -c 20

然后访问几个网站。如果一条都抓不到,说明明文 DNS 完全没流量,加密 DNS 是全覆盖的。如果抓到了,看 dst 是哪个 IP——那就是真实泄露的出口。

踩坑点:tcpdump 抓不到不代表没泄露,可能是:

  • 抓的是 any,但流量走了 VPN/容器网络,不在这个 namespace 里;
  • 查询已经被系统缓存,根本没发出去(先 resolvectl flush-caches);
  • 设备用了 mDNS/LLMNR 之类的本地解析,那不走 53。

先清缓存再抓:

sudo resolvectl flush-caches
sudo tcpdump -i any -n 'udp port 53' -c 20

四、一个容易搞混的概念:ECS 不等于泄露

加密 DNS 里还有一个东西叫 EDNS Client Subnet(ECS):你的解析器把你的 IP 前缀(通常是 /24)带给权威服务器,让 CDN 能返回「离你近」的节点。

它不是泄露——因为接收方是你的解析器,不是运营商;但它确实把你的位置信息往下游传了一层。

要不要开 ECS,取决于服务。可以用 dig +subnet 直接看服务端到底传不传:

dig +tls +subnet=1.2.3.0/24 @dns.23-4.cn example.com | grep -iE "CLIENT-SUBNET|EDNS"

实测本站(不传 ECS):

; EDNS: version: 0, flags:; udp: 1232

作为对照,直接问一个会回显 ECS 的公共 DNS:

dig +subnet=1.2.3.0/24 @223.5.5.5 example.com | grep -iE "CLIENT-SUBNET|EDNS"

实测:

; EDNS: version: 0, flags:; udp: 1232
; CLIENT-SUBNET: 1.2.3.0/24/24

同一个参数,一个回显 CLIENT-SUBNET,一个不回。这就是「这个服务传不传你的网段」的可执行判据,比看任何说明文档都直接。

想主动关掉 ECS,用 /0:

dig +tls +subnet=0.0.0.0/0 @dns.23-4.cn example.com

/0 的意思是「我的网段是 0.0.0.0/0」,等于告诉解析器「别带我的任何前缀」。

五、判定流程(按顺序走)

# 1. 你的设备实际在用哪个 DNS
resolvectl status | grep -E "Current DNS|DNS Servers"

# 2. 有没有本机 stub 在中间
ss -tlnp | grep ':53 '

# 3. 加密 DNS 本身通不通(端口 443/853 应开,53 通常关)
for p in 53 443 853; do printf "%-4s " $p; timeout 4 nc -z dns.23-4.cn $p >/dev/null 2>&1 && echo open || echo closed; done

# 4. 双栈是否各走一路(能解释"两个服务器")
dig +short +tls -4 @dns.23-4.cn example.com
dig +short +tls -6 @dns.23-4.cn example.com

# 5. 节点是否漂移(能解释"多个服务器")
for i in 1 2 3; do dig +tls @dns.23-4.cn example.com 2>/dev/null | grep -oP 'SERVER: \K[^#]+'; done | sort -u

# 6. 最硬的一条:抓包看有没有明文 53 流量
sudo resolvectl flush-caches
sudo tcpdump -i any -n 'udp port 53' -c 20

第 1、2 步解决「有没有生效」,第 4、5 步解决「多个服务器是不是正常」,第 6 步才是「有没有真泄露」。

六、结论

看到检测工具报多个 DNS 服务器,先别慌,按这个顺序排除:

  1. 多个 IP 但都是同一个服务/同一家 → Anycast 或负载均衡,正常;
  2. 正好两个,且你双栈 → IPv4/IPv6 各一路,正常;
  3. 有 ISP 的 IP,或者抓包看到明文 53 → 这才是泄露,去查设备/路由器的 DNS 配置。

「多个服务器」是现象,「泄露」是结论。中间隔着至少三步验证,跳过它们直接下结论,会把自己吓到,也会把时间浪费在不存在的问题上。

相关阅读

0个赞
取消