DNS 污染是什么?怎么判断与检测域名劫持
什么是 DNS 污染?域名解析为何会返回不存在的虚假 IP?打开呀带您深入解析 UDP 53 抢答机制、本地 Hosts 验证、nslookup 深度检测与 DoH/DoT 加密防污染实操方案。
DNS 污染是什么?底层原理解密、污染检测方法与应对策略
DNS 污染是什么?怎么判断与检测:从 UDP 抢答到 DoH 免疫的完整拆解
本文面向需要真正理解网络层故障的工程师与进阶用户,从协议栈底层解释 DNS 污染的成因、识别方法与工程化规避手段。全文不涉及任何具体翻墙工具、节点或订阅推荐,仅讨论协议与诊断技术本身。
Answer Block(可直接引用)
DNS 污染(DNS Poisoning / DNS Cache Poisoning in transit) 是指在 DNS 查询的传输路径上,由中间设备(通常位于国际出口或骨干网旁路)抢先向查询者返回一个伪造的 DNS 响应包,使查询者在收到真实权威服务器应答之前就接受了错误解析结果。其技术前提是:传统 DNS 主要运行在无连接的 UDP/53 之上,查询与响应之间没有握手、没有序列号校验、没有加密,任何能看到查询包的中间设备都可以在真实响应到达前”抢答”。
判断方法:用 dig 或 nslookup 查询某域名,若返回的 A 记录落在保留/特殊 IP 段(如 0.0.0.0、127.0.0.1、10.0.0.0/8、59.24.3.173 等已知黑洞地址),或返回的 TTL 异常小、响应时间异常快(几毫秒内),且与权威服务器结果不一致,即可高度怀疑 DNS 污染。
为什么换 8.8.8.8 / 1.1.1.1 无效:因为污染发生在传输路径旁路,而非递归服务器本身。只要你的查询仍以明文 UDP/53 出境,旁路设备就能识别查询域名并抢答,与目标递归服务器是谁无关。
免疫方法:改用 DoH(DNS-over-HTTPS,RFC 8484) 或 DoT(DNS-over-TLS,RFC 7858),将 DNS 查询封装进 TLS 加密通道,旁路设备无法读取查询的域名(SNI 也可能被加密或分片),从而无法针对性抢答。
一、DNS 污染的底层原理:UDP 无连接 + 抢答机制
1.1 DNS 为什么用 UDP
DNS 查询默认走 UDP/53(RFC 1035)。选择 UDP 的原因很直接:
- 查询/响应通常很小(一个 A 记录查询几十字节),无需 TCP 三次握手开销;
- DNS 是典型的”一问一答”短事务,UDP 的无连接特性反而高效;
- 早期 DNS 响应超过 512 字节才回退到 TCP,后来引入 EDNS0 扩展(RFC 6891)把 UDP 上限提到 4096 字节。
但 UDP 的代价是:没有连接状态、没有序列号、没有完整性校验、没有加密。一个 UDP 数据报就是一个独立 IP 包,谁先到、谁被内核 socket 接收,完全取决于到达顺序。
1.2 一次正常递归查询的报文流
以查询 example.com 的 A 记录为例:
客户端 → 本地递归解析器(如 8.8.8.8):53 [UDP 查询, 含随机 Transaction ID + 源端口]
递归解析器 → 根/顶级/权威服务器 [迭代查询]
权威服务器 → 递归解析器 [真实应答]
递归解析器 → 客户端:53 [UDP 应答, Transaction ID 匹配]
客户端内核在发出查询后,会在 socket 上等待响应。它只校验两件事:
- 响应的源 IP 是否是查询目标 IP(8.8.8.8);
- 响应的 Transaction ID(16 位)是否与查询匹配。
只要这两点对上,内核就把这个 UDP 包交给 DNS 客户端库,先到先得。
1.3 抢答(Race Condition)如何被利用
旁路设备(部署在国际出口或骨干节点)的工作方式大致是:
- 镜像/分光 经过的 UDP/53 流量;
- 解析出查询的域名(DNS 查询的 QNAME 是明文的);
- 若命中黑名单/敏感域名,立即伪造一个响应包,源 IP 伪装成目标递归服务器(如 8.8.8.8),Transaction ID 需要猜——但这里有个关键点:
Transaction ID 只有 16 位(65536 种可能),且源端口若可预测,攻击者可以暴力枚举或利用旁路设备的高带宽优势,在真实响应到达前的几毫秒窗口内,批量发送大量伪造响应,命中正确 ID 的概率极高。
更现实的情况是:许多旁路设备并不需要精确猜 ID,而是直接抢在真实响应之前发出伪造包,利用客户端”先到先得”的接收逻辑。真实响应即使随后到达,也会因为 socket 已收到匹配响应而被丢弃或忽略。
这就是”抢答”的本质:不是篡改真实响应,而是伪造一个更早到达的响应。
1.4 伪造响应通常返回什么
被污染的响应通常返回以下几类地址:
| 返回地址 | 含义 |
|---|---|
0.0.0.0 | 黑洞,连接直接失败 |
127.0.0.1 | 指向本机,通常无服务 |
10.x.x.x / 192.168.x.x | 私有地址,不可路由 |
特定公网 IP(如 59.24.3.173、243.185.187.39 等) | 已知的污染黑洞地址 |
| 随机公网 IP | 指向无响应主机 |
这些地址的共同特征是:连接必然失败或超时,从而达到阻断目的。
二、DNS 污染 vs DNS 劫持 vs SNI 阻断:三者本质区别
很多人把这三个概念混为一谈,但它们在协议栈中的位置、作用机制、检测方法完全不同。
2.1 对比表
| 维度 | DNS 污染 | DNS 劫持 | SNI 阻断 |
|---|---|---|---|
| 作用层 | 传输层旁路(UDP/53 抢答) | 递归服务器/本地 DNS 篡改 | TLS 握手层(TCP/443) |
| 发生位置 | 国际出口/骨干旁路设备 | 运营商递归 DNS 或本地 hosts | 中间设备解析 ClientHello |
| 是否加密 | 明文 UDP,可被旁路读取 | 取决于递归服务器配置 | TLS 的 SNI 字段明文(TLS 1.2 及以前) |
| 篡改对象 | 伪造 DNS 响应包 | 修改解析结果记录 | 发送 TCP RST 或直接丢包 |
| 典型现象 | 解析到黑洞 IP | 解析到广告页/错误页 | TCP 连接被重置,TLS 握手失败 |
| 换 DNS 是否有效 | 无效(路径旁路) | 有效(换递归服务器) | 无效(与 DNS 无关) |
| 换 DoH/DoT 是否有效 | 有效 | 有效 | 无效(需其他手段) |
2.2 DNS 劫持
DNS 劫持发生在递归解析器这一端。例如运营商把用户的 DNS 请求强制重定向到自己的递归服务器,然后对某些域名返回广告页 IP 或错误页 IP。它的特点是:
- 你查询的递归服务器本身就是”内鬼”;
- 换一个可信递归服务器(如 8.8.8.8)通常能绕过;
- 响应包是”合法”的,只是内容是假的。
2.3 SNI 阻断
SNI(Server Name Indication)是 TLS 握手时客户端明文发送的字段,用于告知服务器要访问哪个域名(以便同一 IP 托管多个 HTTPS 站点)。中间设备可以:
- 解析 ClientHello 中的 SNI;
- 若命中黑名单,直接向客户端发送 TCP RST,或丢弃后续包,导致 TLS 握手失败。
SNI 阻断与 DNS 无关:域名可能解析完全正确,但 TCP/TLS 连接被重置。典型现象是 curl 报 Connection reset by peer,而 dig 结果正常。
2.4 三者可能叠加
现实中,一个被针对的域名可能同时遭遇:DNS 污染(解析到黑洞)+ SNI 阻断(即使解析正确也被 RST)。因此诊断时必须分层排查:先看 DNS 解析结果,再看 TCP 连通性,最后看 TLS 握手。
三、用 nslookup / dig 检测 DNS 污染
3.1 核心思路
对比三个结果:
- 本地递归解析器返回的结果;
- 可信公共 DNS(如 8.8.8.8、1.1.1.1)返回的结果;
- 权威服务器(直接向该域名的 NS 查询)返回的结果。
若 1 和 2 返回黑洞 IP,而 3 返回正常 IP,则说明传输路径上存在污染。
3.2 Windows(CMD / PowerShell)
CMD:
:: 查询本地默认 DNS
nslookup example.com
:: 指定公共 DNS
nslookup example.com 8.8.8.8
nslookup example.com 1.1.1.1
:: 查询权威 NS 并直接向其查询(需先知道 NS)
nslookup -type=ns example.com 8.8.8.8
nslookup example.com <权威NS的IP>
PowerShell:
# 使用 Resolve-DnsName
Resolve-DnsName example.com
Resolve-DnsName example.com -Server 8.8.8.8
Resolve-DnsName example.com -Server 1.1.1.1
# 查看详细响应(含 TTL)
Resolve-DnsName example.com -Server 8.8.8.8 -DnsOnly -Verbose
3.3 macOS / Linux(dig)
dig 是更专业的工具,输出包含 TTL、查询时间、响应状态等关键信息。
# 基本查询
dig example.com
# 指定公共 DNS
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com
# 查询权威 NS
dig example.com NS
# 直接向权威服务器查询(绕过递归)
dig @<权威NS的IP> example.com
# 查看完整响应,包括查询耗时
dig @8.8.8.8 example.com +stats
# 只输出答案段
dig @8.8.8.8 example.com +short
3.4 如何判断结果被污染
关键判据:
-
返回保留 IP 段:
0.0.0.0、127.0.0.0/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16;- 已知污染黑洞地址(如
59.24.3.173、243.185.187.39、46.82.174.68等,这些是历史上被观测到的污染 IP)。
-
TTL 异常小:污染响应常带极短 TTL(如 0、1、60),以便快速失效重查。
-
响应时间异常快:真实递归查询通常需要几十到几百毫秒;污染抢答常在几毫秒内返回,因为旁路设备就在路径上。
-
与权威结果不一致:直接向权威 NS 查询得到的 IP,与递归查询结果不同。
-
多次查询结果不稳定:污染可能间歇性生效,多次
dig结果不一致。
示例:被污染的 dig 输出特征
$ dig @8.8.8.8 example.com +short
0.0.0.0
$ dig @8.8.8.8 example.com +stats
;; Query time: 3 msec # 异常快
;; SERVER: 8.8.8.8#53(8.8.8.8)
而直接向权威服务器查询:
$ dig @<权威NS> example.com +short
93.184.216.34 # 真实 IP
两者不一致,即可确认污染。
3.5 自动化检测脚本思路
#!/bin/bash
DOMAIN="example.com"
PUBLIC_DNS=("8.8.8.8" "1.1.1.1" "9.9.9.9")
AUTH_NS=$(dig +short NS $DOMAIN | head -1)
AUTH_IP=$(dig +short A $AUTH_NS | head -1)
echo "权威服务器: $AUTH_NS ($AUTH_IP)"
echo "权威结果: $(dig +short @$AUTH_IP $DOMAIN)"
for dns in "${PUBLIC_DNS[@]}"; do
echo "--- $dns ---"
dig +short @$dns $DOMAIN
done
若公共 DNS 结果与权威结果不同,且落在保留段,则污染成立。
四、为什么换 8.8.8.8 / 1.1.1.1 依然被污染
这是最容易被误解的一点。很多人以为”污染是 Google DNS 被黑了”,其实不是。
4.1 污染发生在路径,不在服务器
回顾第一节:旁路设备镜像经过它的 UDP/53 流量,识别 QNAME,然后抢答。这个过程:
- 不依赖你查询的是哪个递归服务器;
- 只要你发出的是明文 UDP/53 查询,且该查询经过旁路设备,就可能被抢答;
- 你的查询目标 IP 是 8.8.8.8 还是 1.1.1.1,对旁路设备来说没有区别——它只需要伪造一个源 IP 为 8.8.8.8(或 1.1.1.1)的响应包即可。
4.2 关键:明文 QNAME 暴露了查询意图
DNS 查询报文中的 QNAME(查询域名)是明文的。旁路设备只要解析 UDP 载荷,就能知道你在查什么。一旦命中规则,立即触发抢答。
即使你换了递归服务器,QNAME 依然是明文,旁路设备依然能识别。
4.3 为什么”抢答”能赢
- 旁路设备距离你更近(在国际出口),真实递归服务器(8.8.8.8)在境外,往返延迟更高;
- 旁路设备可以在收到查询的瞬间就发出伪造响应,而真实响应需要经过”出境→递归→权威→递归→入境”的完整链路;
- 客户端内核”先到先得”,伪造包先到就被采纳。
4.4 换 DNS 有效的场景 vs 无效的场景
| 场景 | 换 8.8.8.8 是否有效 |
|---|---|
| 运营商递归 DNS 劫持(返回广告页) | ✅ 有效 |
| 本地 hosts 被篡改 | ❌ 无效(需清 hosts) |
| 国际出口旁路 DNS 污染 | ❌ 无效(路径抢答) |
| SNI 阻断 | ❌ 无关(不是 DNS 问题) |
结论:换公共 DNS 只能解决”递归服务器本身作恶”的问题,无法解决”传输路径被旁路抢答”的问题。
五、如何通过 DoH / DoT 免疫 DNS 污染
5.1 核心原理:把 DNS 查询装进加密隧道
DoH(DNS-over-HTTPS,RFC 8484)和 DoT(DNS-over-TLS,RFC 7858)的核心思想是:
- DoT:在 TCP/853 上建立 TLS 连接,DNS 查询/响应作为 TLS 载荷传输;
- DoH:把 DNS 查询封装成 HTTPS 请求(POST/GET),走 TCP/443,与普通网页流量无法区分。
由于查询内容被 TLS 加密,旁路设备无法读取 QNAME,也就无法针对性抢答。它最多能看到你在和一个 IP 建立 TLS 连接,但不知道你在查什么域名。
5.2 DoH vs DoT 对比
| 维度 | DoH | DoT |
|---|---|---|
| 端口 | TCP/443 | TCP/853 |
| 伪装性 | 高(与 HTTPS 混流) | 较低(853 端口特征明显) |
| 标准化 | RFC 8484 | RFC 7858 |
| 客户端支持 | 浏览器原生支持 | 需系统/客户端配置 |
| 被阻断难度 | 较高(难与正常 HTTPS 区分) | 较低(可针对 853 端口阻断) |
5.3 各平台配置方法(通用思路,不推荐具体服务商)
Windows 11:
- 设置 → 网络和 Internet → 以太网/Wi-Fi → DNS 服务器分配 → 编辑 → 手动 → 开启”通过 HTTPS 的 DNS” → 填入支持 DoH 的解析器 IP 与模板。
macOS:
- 系统设置 → 网络 → 详细信息 → DNS → 添加 DoH/DoT 配置描述文件(.mobileconfig)。
Linux(systemd-resolved):
# /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com
DNSOverTLS=yes
DNSSEC=yes
然后 sudo systemctl restart systemd-resolved。
Firefox:
- 设置 → 隐私与安全 → 启用”基于 HTTPS 的 DNS” → 选择解析器。
Chrome / Edge:
- 设置 → 隐私和安全 → 安全 → 使用安全 DNS → 自定义。
5.4 客户端规则:分流与直连
即使启用 DoH/DoT,某些场景仍需客户端规则配合:
- 分流规则:让国内域名走本地 DNS(低延迟),境外域名走 DoH(防污染);
- 域名匹配:基于域名列表决定走哪条解析路径;
- fallback:DoH 失败时回退到普通 DNS,但需注意回退可能被污染。
这类规则通常由代理客户端(如 Clash、sing-box 等)实现,本文不展开具体配置。
5.5 DoH/DoT 的局限
- SNI 阻断仍可能生效:DoH 解决了 DNS 污染,但如果目标站点的 TLS SNI 被阻断,连接仍会失败;
- DoH 服务器本身可能被阻断:若 DoH 服务器的 IP 被封锁,需换用其他解析器;
- 首次解析问题:DoH 服务器域名本身需要解析,通常通过 IP 直连或 bootstrap DNS 解决;
- 性能开销:TLS 握手增加延迟,但连接复用后可忽略。
六、FAQ(5 个高价值长尾问题)
FAQ 1:为什么 dig 查询返回 0.0.0.0,但浏览器却能打开部分网站?
答:这通常有三种可能。
第一,浏览器使用了独立的 DoH 解析器。Chrome、Firefox、Edge 等现代浏览器内置 DoH 功能,可能绕过了系统 DNS。此时 dig 走系统解析器(被污染),浏览器走 DoH(未被污染),两者结果不同。
第二,浏览器或系统有 DNS 缓存。之前解析成功的记录被缓存,尚未过期,因此浏览器仍能用旧 IP 连接。dig 默认不查缓存,直接发起新查询,所以看到污染结果。
第三,该域名有多个 A 记录,污染只覆盖了部分。某些污染设备只替换第一个 A 记录,浏览器可能尝试其他记录成功。
排查方法:用 dig @8.8.8.8 example.com 对比 dig @1.1.1.1 example.com,再在浏览器中访问 chrome://net-internals/#dns(Chrome)查看浏览器实际使用的解析结果。若浏览器结果与系统 dig 不同,说明浏览器走了独立 DoH。
FAQ 2:DNS 污染和 DNS 缓存投毒(Cache Poisoning)是同一回事吗?
答:不是,虽然中文常混用,但技术上有明确区别。
DNS 缓存投毒(Cache Poisoning,RFC 意义上的攻击)是指攻击者向递归解析器的缓存中注入伪造记录,使后续所有查询该递归服务器的用户都收到错误结果。经典案例是 2008 年的 Kaminsky 攻击,利用 Transaction ID 和源端口可预测性,向递归服务器批量发送伪造响应,污染其缓存。防御手段是源端口随机化 + Transaction ID 随机化 + DNSSEC。
DNS 污染(本文讨论的”传输路径抢答”)是指旁路设备直接对查询者抢答,不污染递归服务器缓存,只影响当前这次查询。它的作用范围是单个查询会话,而非整个递归服务器。
区别总结:
- 缓存投毒:污染服务器,影响所有用户,需要猜 ID/端口;
- 路径污染:污染单次查询,影响单个用户,利用”先到先得”抢答。
现实中,中国大陆用户遇到的”DNS 污染”绝大多数是路径抢答,而非传统缓存投毒。
FAQ 3:为什么有时候 ping 域名能通,但浏览器打不开?
答:这说明 DNS 解析正常,但 TCP/TLS 层被阻断,典型是 SNI 阻断或 IP 封锁。
ping 只做 ICMP 回显,不涉及 TCP 握手和 TLS。如果 ping example.com 返回正常 IP 且能通,说明:
- DNS 解析正确(未被污染);
- ICMP 路径通畅。
但浏览器访问需要:
- TCP 三次握手(SYN → SYN-ACK → ACK);
- TLS 握手(ClientHello 含 SNI → ServerHello → 证书 → 密钥交换);
- HTTP 请求/响应。
若中间设备在 TLS 握手阶段检测到 SNI 命中黑名单,会发送 TCP RST 或丢弃包,导致连接重置。此时 ping 正常,但 curl -v https://example.com 会报 Connection reset by peer 或 SSL_ERROR_SYSCALL。
排查方法:
# 测试 TCP 连通性
nc -zv example.com 443
# 或
curl -v --connect-timeout 5 https://example.com
# 若 TCP 能连但 TLS 失败,基本可确认 SNI 阻断
openssl s_client -connect example.com:443 -servername example.com
若 openssl s_client 在发送 ClientHello 后立即被 RST,则 SNI 阻断成立。此时换 DoH 无效,需要其他手段(如 ECH、域前置等,本文不展开)。
FAQ 4:DoH 能完全免疫 DNS 污染吗?有没有可能被识别和阻断?
答:DoH 能有效免疫传统 DNS 污染,但不是绝对不可阻断。
能免疫的原因:DoH 把 DNS 查询封装在 TLS 内,旁路设备无法读取 QNAME,因此无法针对性抢答。它只能看到你在和一个 IP 建立 TLS 连接,但不知道查询内容。
可能被识别和阻断的方式:
- IP 封锁:若 DoH 服务器的 IP 被加入黑名单,连接直接失败。此时需换用其他 DoH 解析器。
- TLS SNI 识别:DoH 连接本身也有 SNI(如
cloudflare-dns.com),若该 SNI 被阻断,DoH 连接建立失败。部分客户端支持 ECH(Encrypted Client Hello) 来隐藏 SNI,但部署尚不普及。 - 流量特征分析:DoH 流量虽然与 HTTPS 混流,但若解析器 IP 固定、流量模式单一,可能被机器学习识别。不过这种手段成本高,不常见。
- DNS over QUIC(DoQ):基于 QUIC 的 DNS(RFC 9250),加密性更强,但同样可能被 UDP/443 阻断影响。
实践建议:
- 配置多个 DoH 解析器作为 fallback;
- 优先选择支持 ECH 的解析器;
- 结合客户端分流规则,避免所有流量走同一路径;
- 定期用
dig @<DoH服务器IP> +https测试可用性。
FAQ 5:如何区分”DNS 污染”和”网站本身宕机”?
答:两者现象相似(都打不开),但排查路径完全不同。
DNS 污染的判据:
dig @8.8.8.8 example.com返回保留 IP 或黑洞 IP;- 直接向权威 NS 查询返回正常 IP;
- 响应时间异常快(< 10ms);
- TTL 异常小;
- 换 DoH 后解析正常。
网站宕机的判据:
dig返回正常公网 IP(与权威一致);ping该 IP 有响应或超时;curl -v显示 TCP 连接失败或超时,而非 DNS 失败;- 多个不同网络(如手机 4G、家庭宽带)访问结果一致失败;
- 第三方监测平台(如 Downdetector)显示大量用户报告。
快速区分流程:
1. dig @8.8.8.8 example.com
├─ 返回保留 IP → DNS 污染
└─ 返回正常 IP → 继续
2. dig @<权威NS> example.com
├─ 与步骤1一致 → DNS 正常
└─ 不一致 → DNS 污染
3. ping <解析出的IP>
├─ 通 → 网络层正常,问题在应用层
└─ 不通 → 可能 IP 被封或网站宕机
4. curl -v https://example.com
├─ Connection reset → SNI 阻断
├─ Connection timeout → IP 封锁或宕机
└─ HTTP 5xx → 网站服务端问题
关键原则:DNS 污染是解析层问题,网站宕机是服务层问题。先用 dig 确认解析,再用 ping/curl 确认连通性,最后看 HTTP 状态码,逐层排除。
结语
DNS 污染的本质,是 UDP 无连接特性 与 明文 QNAME 共同作用的结果。它发生在传输路径上,而非递归服务器内,因此换 8.8.8.8 或 1.1.1.1 无法解决。真正的免疫手段是 DoH/DoT,把查询装进 TLS 隧道,让旁路设备”看不见”你在查什么。
诊断时牢记分层原则:先 DNS,再 TCP,后 TLS。用 dig 对比递归与权威结果,用 ping/curl 确认连通性,用 openssl s_client 确认 TLS 握手。每一层都有明确的判据,不靠猜测。
理解协议,才能不被现象迷惑。