---
title: "DNS污染和DNS劫持怎么区分：用 dig 和 nslookup 判断解析是否被篡改"
description: "一张表讲清 DNS 污染与 DNS 劫持在位置、表现和影响范围上的差别，再给出 dig、nslookup、PowerShell 和 RDAP 的命令步骤，判断你拿到的解析结果是否被改过、是在哪一段被改的。"
url: https://cdnping.org/blog/dns-pollution-vs-hijacking-detect
language: zh-CN
published: 2026-10-22
category: "排障指南"
tags: ["DNS污染","DNS劫持","dig","nslookup","RDAP","网络排障"]
source: cdnping.org
license: Free to quote and summarize with a link to the url above.
---
# DNS污染和DNS劫持怎么区分：用 dig 和 nslookup 判断解析是否被篡改

DNS污染和 DNS 劫持的结果都是“域名解析到了不该去的 IP”，区别在于篡改发生在哪里。污染发生在传输路上：查询包经过的某台设备抢在真正的解析服务器之前回了一个假应答。劫持发生在端点：你的 hosts 文件、路由器或运营商的解析服务器本身返回了改过的结果。判断方法是把同一个域名分别交给本地解析器、多个公共解析器和加密 DNS 去查，比较答案，再用 RDAP 查应答 IP 归属谁。下面先列差别，再给可以照做的命令。

## DNS 污染和 DNS 劫持到底差在哪？

| 对比项 | DNS 污染 | DNS 劫持 |
|---|---|---|
| 篡改位置 | 传输链路上的旁路设备 | 本机 hosts、路由器、运营商解析器或被替换的 DNS 设置 |
| 工作方式 | 监听到查询后抢先发出伪造应答，真实应答晚到被丢弃 | 解析器直接返回改过的记录，或把你的 53 端口流量重定向到别的解析器 |
| 换一个明文公共 DNS | 往往仍然错，因为路过同一段链路 | 如果只是本地解析器被改，换了通常就对了；透明重定向的情况除外 |
| 用 TCP 或加密 DNS 查 | 加密 DNS 一般能拿到正确结果 | 加密 DNS 绕开了被改的解析器，通常也正确 |
| 向不跑 DNS 的 IP 发查询 | 可能仍然收到“应答”，这是污染的典型特征 | 一般超时，除非存在透明重定向 |
| 影响范围 | 经过该链路的所有用户，通常针对特定域名 | 某台设备、某个家庭网络或某个运营商的用户 |
| 常见的应答特征 | 应答返回得比到解析器的往返时间还快；同一查询收到两个应答 | 把不存在的域名解析成广告页 IP；返回 0.0.0.0、127.0.0.1 或内网地址 |

两者也可能同时存在，所以下面的流程按段逐一排除。

## 开始之前：先确认问题真的出在 DNS

很多“打不开”其实和解析无关。先跑一次 [cdnping 在线测速](/)，它记录的“首次连接”包含 DNS 与 TLS 握手，“往返”是连接复用后 3 次请求的中位数。如果首次连接很慢、往返正常，问题可能在解析或握手；如果往返本身就慢，更像是链路问题，可以接着看 [traceroute 和 mtr 结果怎么看](/blog/traceroute-mtr-how-to-read)。打不开某个 AI 服务时，也可以先按 [ChatGPT 挂了吗？三步判断是服务故障还是自己的网络问题](/blog/is-chatgpt-down-or-my-network) 排除服务端故障。

还要记住一点：解析结果不一致不等于被篡改。下面几种情况都是正常的：

- 域名用了 CDN 或按地区调度（GeoDNS），不同解析器、不同城市拿到的 IP 本来就不同。
- 解析器带上了客户端网段信息（ECS），返回离你近的节点。
- 记录刚改过，各解析器缓存的 TTL 还没过期。DNS 服务商自身的同步延迟也会造成这种短时不一致。例如 cdnping 从 Cloudflare 官方状态页同步到的事件里，2026-10-15 15:33（UTC）有一条“DNS Update Delays”，等级 minor，持续约 165 分钟（来源：cdnping /status 对官方状态页的 15 分钟同步，窗口为 2026 年 9 月 17 日以来）。这段时间里新改的记录在不同解析器上看到的结果可能不一样，但这不是污染。

因此要看的是 IP 归属对不对、应答是谁发的，单看 IP 是否相同说明不了问题。

## 第一步：对比本地解析器和多个公共解析器

下文用 `example.com` 代表你要检查的域名，命令里的 IP 都是公开的解析服务地址。

macOS / Linux：

```bash
D=example.com
# 系统默认解析器（路由器或运营商下发的那个）
dig +short $D A
# 几个公共解析器，走明文 UDP 53
for s in 223.5.5.5 119.29.29.29 1.1.1.1 8.8.8.8; do
  echo "== $s"; dig +short +time=3 +tries=1 @$s $D A
done
```

Windows（PowerShell）：

```powershell
$D = "example.com"
Resolve-DnsName $D -Type A -DnsOnly
foreach ($s in "223.5.5.5","119.29.29.29","1.1.1.1","8.8.8.8") {
  "== $s"; Resolve-DnsName $D -Type A -Server $s -DnsOnly -QuickTimeout
}
```

只有 `nslookup` 时，写成 `nslookup example.com 223.5.5.5`，逐个替换最后的服务器地址即可。

先检查本机有没有被改。`cat /etc/hosts`（Windows 是 `C:\Windows\System32\drivers\etc\hosts`）里如果有这个域名，解析根本不会发出去，这属于本机层面的“劫持”，可能是你自己或某个软件写进去的。

怎么读结果：

- 只有系统默认解析器的答案异常，公共解析器都一致：大概率是路由器或运营商解析器的问题，偏向劫持。
- 所有明文查询都返回同一个可疑 IP：可能是链路上的污染，也可能是 53 端口被透明重定向，第二步区分。
- 答案各不相同，但都属于同一家 CDN：通常正常，第四步用 RDAP 确认。

## 第二步：确认查询是不是真的到了你指定的解析器

`dig @1.1.1.1` 并不保证包真的到了 1.1.1.1。有些路由器或网络会把所有 UDP 53 流量重定向到自己的解析器。可以用解析服务提供的“自我介绍”记录来验证：

```bash
# Cloudflare 返回处理这次查询的机房代码；被重定向时通常拿不到或格式不对
dig +short @1.1.1.1 id.server CH TXT
# Google 返回替你向权威服务器发起查询的解析器出口 IP
dig +short @8.8.8.8 o-o.myaddr.l.google.com TXT
# 走默认解析器，看真正干活的是谁
dig +short whoami.akamai.net A
```

第三条返回的是“解析器的出口 IP”，不是你的出口 IP。把它拿去第四步查 RDAP，如果归属是你没设置过的运营商或陌生主体，说明默认解析链路和你以为的不一样。浏览器里也能看到类似信息：[cdnping /ip](/ip) 的 DNS 泄漏检测会列出实际替你查询的解析器 IP 和归属，原理见 [DNS 泄漏与 WebRTC 泄漏](/learn/dns-leak-webrtc-leak)。

再测一个必然不存在的域名：

```bash
dig +short nx-$(date +%s).example.com A
```

正常结果应该是空（状态 NXDOMAIN）。如果返回了一个 IP，说明默认解析器把“不存在”改写成了某个页面地址，这是解析器层面劫持的明确证据。完整状态可以去掉 `+short`，看 `status:` 那一行。

## 第三步：对比 UDP、TCP 和加密 DNS

链路上的抢答大多针对 UDP。同一个解析器分别用 UDP、TCP 和 DoH 查，三者对照：

```bash
D=example.com
dig +short @1.1.1.1 $D A          # UDP
dig +short +tcp @1.1.1.1 $D A     # TCP
curl -s -H 'accept: application/dns-json' \
  "https://cloudflare-dns.com/dns-query?name=$D&type=A"   # DoH，JSON 格式
curl -s "https://dns.alidns.com/resolve?name=$D&type=1"   # DoH，JSON 格式
```

Windows 上 TCP 查询用 `Resolve-DnsName $D -Server 1.1.1.1 -TcpOnly`，或 `nslookup -vc example.com 1.1.1.1`。

| UDP 结果 | TCP 结果 | DoH 结果 | 倾向的结论 |
|---|---|---|---|
| 可疑 | 正常 | 正常 | 链路上有针对 UDP 的抢答，偏向污染 |
| 可疑 | 可疑 | 正常 | 明文 53 端口整体被重定向或篡改 |
| 可疑 | 可疑 | 可疑 | 先怀疑域名本身的记录或 CDN 调度，再查 RDAP |
| 正常 | 正常 | 正常 | 解析没问题，回到连接层排查 |

还有一个直接的污染检测：向一台你确认没有运行 DNS 服务的境外主机发查询，例如你自己的一台云主机，53 端口没有开放。

```bash
dig +time=3 +tries=1 @<你的主机IP> example.com A
```

正常情况下应该超时。如果收到了带 IP 的应答，那这个应答只能来自路上的设备。配合抓包能看得更清楚：

```bash
sudo tcpdump -n -i any udp port 53 and host 1.1.1.1
```

另开一个终端执行一次 `dig @1.1.1.1 example.com`。如果一次查询收到两个应答，先到的那个与 DoH 结果不一致，就是被抢答了。

## 第四步：用 RDAP 查应答 IP 归属谁，并看应答时间

拿到可疑 IP 以后，不要只看它“像不像”，要查它注册在谁名下。RDAP 是 WHOIS 的结构化替代，返回 JSON。下面用的 rdap.org 会把请求重定向到负责该网段的地区注册机构（RIR）的 RDAP 服务：

```bash
IP=203.0.113.10   # 示例地址，换成你拿到的 IP
curl -sL "https://rdap.org/ip/$IP" | jq '{handle, name, country, startAddress, endAddress}'
```

判断方式：

- 应答 IP 的网段属于该网站或它公开使用的 CDN：结果可信，不同 IP 只是调度差异。
- 网段属于与该网站无关的主体，或属于你的运营商：结果被改过的可能性高。
- 应答是 `0.0.0.0`、`127.0.0.1`、`10.0.0.0/8`、`192.168.0.0/16` 这类地址：可能是链路上的抢答，也可能是本地或运营商的过滤策略，RDAP 查不到公网归属本身就是信号。

[cdnping /ip](/ip) 的出口 IP 情报也走 RDAP 展示网段注册信息，可以拿来对照命令行的结果。

应答时间也有参考价值。`dig` 输出末尾的 `Query time` 是这次查询的耗时。先 `ping 1.1.1.1` 记下往返时间，如果某次查询的 `Query time` 明显小于这个往返时间，说明应答不可能来自那台解析器，只能是路上的设备回的。这条规则只用于对比同一时刻的两个数，不需要记任何固定阈值。

## 一张可以照抄的检查表

1. 检查 hosts 文件，排除本机写死的记录。
2. 用系统默认解析器和 3 到 4 个公共解析器查同一域名，记下答案。
3. 用 `id.server`、`o-o.myaddr`、`whoami.akamai.net` 确认查询真的到了目标解析器。
4. 查一个随机不存在的子域名，看是否返回 NXDOMAIN。
5. 同一解析器分别用 UDP、TCP、DoH 查询，对照表格。
6. 向一台不运行 DNS 的主机发查询，看是否收到应答。
7. 用 RDAP 查可疑 IP 的归属，结合 `Query time` 与 ping 往返时间判断。
8. 把以上结果截图或保存文本，方便向运营商或网络管理员反馈。

## 确认之后怎么处理？

如果结论是劫持，处理对象很明确：hosts 里的条目删掉；路由器里的 DNS 设置改回你信任的解析器，顺便改掉路由器的默认管理密码；运营商解析器改写 NXDOMAIN 的，可以向运营商反馈，或改用可信的加密 DNS。具体设置步骤见 [DNS over HTTPS 配置指南](/blog/dns-over-https-setup-guide)，改完后回到 [/ip](/ip) 看 DNS 泄漏检测里列出的解析器是否已经变成你设置的那个。

如果结论是链路上的污染，本文只讲到确认为止。它不在你的设备或路由器上，单靠改本机设置不一定能处理，具体怎么做请遵守所在地的法律法规和网络服务条款。对开发工作来说，更现实的做法是把这一步记进排障记录，然后继续检查其他层：开发工具连不上时，可以按 [Claude Code 连接超时和报错怎么排查](/blog/claude-code-connection-troubleshooting) 的四层清单往下走，完整的自检顺序见 [开发者网络自检清单（2026 版）](/blog/developer-network-self-check-2026)。
