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 結果怎麼看。打不開某個 AI 服務時,也可以先按 ChatGPT 掛了嗎?三步判斷是服務故障還是自己的網路問題 排除服務端故障。
還要記住一點:解析結果不一致不等於被篡改。下面幾種情況都是正常的:
- 域名用了 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:
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):
$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 流量重定向到自己的解析器。可以用解析服務提供的“自我介紹”記錄來驗證:
# 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 的 DNS 洩漏檢測會列出實際替你查詢的解析器 IP 和歸屬,原理見 DNS 洩漏與 WebRTC 洩漏。
再測一個必然不存在的域名:
dig +short nx-$(date +%s).example.com A
正常結果應該是空(狀態 NXDOMAIN)。如果返回了一個 IP,說明預設解析器把“不存在”改寫成了某個頁面地址,這是解析器層面劫持的明確證據。完整狀態可以去掉 +short,看 status: 那一行。
第三步:對比 UDP、TCP 和加密 DNS
鏈路上的搶答大多針對 UDP。同一個解析器分別用 UDP、TCP 和 DoH 查,三者對照:
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 埠沒有開放。
dig +time=3 +tries=1 @<你的主機IP> example.com A
正常情況下應該超時。如果收到了帶 IP 的應答,那這個應答只能來自路上的裝置。配合抓包能看得更清楚:
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 服務:
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 情報也走 RDAP 展示網段註冊資訊,可以拿來對照命令列的結果。
應答時間也有參考價值。dig 輸出末尾的 Query time 是這次查詢的耗時。先 ping 1.1.1.1 記下往返時間,如果某次查詢的 Query time 明顯小於這個往返時間,說明應答不可能來自那臺解析器,只能是路上的裝置回的。這條規則只用於對比同一時刻的兩個數,不需要記任何固定閾值。
一張可以照抄的檢查表
- 檢查 hosts 檔案,排除本機寫死的記錄。
- 用系統預設解析器和 3 到 4 個公共解析器查同一域名,記下答案。
- 用
id.server、o-o.myaddr、whoami.akamai.net確認查詢真的到了目標解析器。 - 查一個隨機不存在的子域名,看是否返回 NXDOMAIN。
- 同一解析器分別用 UDP、TCP、DoH 查詢,對照表格。
- 向一臺不執行 DNS 的主機發查詢,看是否收到應答。
- 用 RDAP 查可疑 IP 的歸屬,結合
Query time與 ping 往返時間判斷。 - 把以上結果截圖或儲存文字,方便向運營商或網路管理員反饋。
確認之後怎麼處理?
如果結論是劫持,處理物件很明確:hosts 裡的條目刪掉;路由器裡的 DNS 設定改回你信任的解析器,順便改掉路由器的預設管理密碼;運營商解析器改寫 NXDOMAIN 的,可以向運營商反饋,或改用可信的加密 DNS。具體設定步驟見 DNS over HTTPS 配置指南,改完後回到 /ip 看 DNS 洩漏檢測裡列出的解析器是否已經變成你設定的那個。
如果結論是鏈路上的汙染,本文只講到確認為止。它不在你的裝置或路由器上,單靠改本機設定不一定能處理,具體怎麼做請遵守所在地的法律法規和網路服務條款。對開發工作來說,更現實的做法是把這一步記進排障記錄,然後繼續檢查其他層:開發工具連不上時,可以按 Claude Code 連線超時和報錯怎麼排查 的四層清單往下走,完整的自檢順序見 開發者網路自檢清單(2026 版)。