目录
DNS 污染与 DNS 泄漏:网页打不开的常见原因
网页打不开、证书报错,很多时候问题出在第一步:查地址。DNS 污染是查到了错误的 IP,DNS 泄漏是连着加密通道、查询却仍然发给了本地网络。用问路打比方讲清两者的原理、检测方法和客户端的处理方式,配时序图逐步说明。
网络原理系列:① 打开一个网页时发生了什么 → ② 网络分层模型 → ③ 常见网络协议 → ④ 代理是什么 → ⑤ 加密隧道是什么 → ⑥ 加密隧道与代理的区别 → ⑦ HTTPS 加密了什么 → ⑧ 系统代理与 TUN 模式 → ⑨ 分流是什么 → ⑩ DNS 污染与泄漏 → ⑪ 晚高峰为什么变慢 → ⑫ 延迟、丢包与带宽
在浏览器里输入一个网址,第一件事是查地址:把域名换成 IP 地址,这一步叫 DNS 解析。如果这一步出了问题,后面的连接、加密、加载都无从谈起。两个最常见的问题是:
- DNS 污染:查到的是错误的 IP,连过去要么连不上,要么证书报错;
- DNS 泄漏:明明连着加密通道,DNS 查询却绕过了通道,仍然发给了本地网络,你访问了哪些网站一目了然,也照样可能被污染。
- ① 出门前先问路DNS 查询:域名换成 IP
- ② 有人抢答伪造的回答先到,被当真
- ③ 走到空房子DNS 污染:网页打不开
- ④ 探头向路边问路DNS 泄漏:查询绕过了通道
- ⑤ 在隧道里问可信的地址簿加密 DNS + 加密通道
先打个比方:出门前先问路
DNS 就像路口的问路亭,里面放着一本大地址簿。你要去一个地方,先问亭子里的人「这个地方在哪」,拿到地址再出发。
- 正常问路:你问,亭子查地址簿,告诉你正确地址。
- 有人抢答:你刚问出口,路边一个人抢在亭子前面塞给你一张假地址。你没法分辨真假,就先信了先到的那张。
- 结果:你按假地址走到一座废弃的空房子,门是锁的。这就是 DNS 污染:网页打不开,但网络本身是通的。
- 坐在隧道里探头问路:你已经坐进了密封的隧道车,可还是把头伸出窗外,向路边的亭子大声问路。旁边有人拿本子记下你要去哪,抢答的人也照样能塞假地址。这就是 DNS 泄漏。
- 正确做法:把问题封进信封,在隧道里交给隧道另一头可信的地址簿,拿回正确的地址,整个过程外面看不到。
DNS 查询是怎么完成的
一次典型的 DNS 解析(详细过程见 常见网络协议):
- 程序问操作系统:
www.example.com的 IP 是多少? - 系统先查本机缓存,没有的话,发给网络里配置的 DNS 服务器(通常是路由器或运营商自动下发的);
- 这个服务器如果也没有缓存,就逐级询问根服务器 → 顶级域(.com)服务器 → 网站自己的权威服务器,拿到答案后返回并缓存一段时间。
问题在于,传统 DNS 查询是 UDP 53 端口上的明文,而且没有签名:
- 路上任何一台设备都能看到你在查哪个域名;
- 程序只认「最先到达、格式正确」的回答,后面到达的真回答会被丢掉。
(DNSSEC 可以给 DNS 结果加签名,但目前大部分网站和客户端都没有启用校验,实际起不到保护作用。)
DNS 污染:拿到了错误的地址
DNS 污染指 DNS 查询得到了错误的结果。常见有两种方式:
| 方式 | 原理 |
|---|---|
| 抢答(在途伪造) | 路上的设备看到你在查某个域名,立刻伪造一个回答发给你,比真正的 DNS 服务器更早到达 |
| 缓存投毒 | 错误的记录被写进了 DNS 服务器的缓存,之后所有问这台服务器的人都拿到错误的地址 |
被污染后的典型表现:
- 网页一直转圈,最后提示「连接超时」或「连接被重置」:伪造的 IP 根本不是那个网站;
- 浏览器提示「您的连接不是私密连接」等证书错误:连到的服务器拿不出这个网站的证书(HTTPS 在这里起了保护作用,见 HTTPS 加密了什么);
- 同一个网站,有时能打开、有时打不开,和缓存有关。
怎么判断是不是 DNS 污染
在命令行里分别用本地 DNS 和加密 DNS 查同一个域名,对比结果:
# 用系统默认的 DNS 查询
nslookup www.example.com
# 用加密的 DNS over HTTPS 查询(返回 JSON)
curl -s "https://cloudflare-dns.com/dns-query?name=www.example.com&type=A" -H "accept: application/dns-json"
如果两边的 IP 完全不同,而且本地查到的 IP 归属和网站毫不相干(可以在 IP 查询网站上看归属),基本可以判断是被污染了。注意:大型网站用 CDN,不同地方查到不同 IP 是正常的,要看 IP 是否属于这个网站的服务商。
为什么换个 DNS 服务器不管用
很多教程会让你把 DNS 改成某个公共 DNS。但只要查询还是明文的 UDP 53,它在路上照样能被看到、被抢答,改的只是「问哪个亭子」,没改变「在大街上喊」这件事。真正有效的是:
- 加密 DNS:DNS over HTTPS(DoH)、DNS over TLS(DoT),查询内容被加密,路上看不到、也无法伪造;
- 让 DNS 查询走加密通道:查询先进入加密通道,在服务器那一侧再发出,本地网络完全接触不到。
DNS 泄漏:查询绕过了加密通道
DNS 泄漏指:你已经连上加密通道,网页流量都在通道里,但 DNS 查询却还在走本地网络,发给了本地的 DNS 服务器。后果有两个:
- 隐私:本地网络虽然看不到网页内容,却能从 DNS 查询看到你访问的每一个域名;
- 照样被污染:查到的还是错误地址,即使后面的连接走加密通道,连的也是错误的 IP,网页照样打不开。
常见原因:
| 原因 | 说明 |
|---|---|
| 只用了系统代理 | 系统代理只接管遵守代理设置的程序,其他程序的 DNS 查询完全不受影响(见 系统代理与 TUN 模式) |
| IPv6 绕过 | 客户端只接管了 IPv4,系统却通过 IPv6 向 DNS 服务器发起查询 |
| 系统向所有网卡并发查询 | 部分系统为了加快速度,会同时向每块网卡的 DNS 服务器发查询,谁先回用谁 |
| 程序自带 DNS | 浏览器开启了「安全 DNS」、部分 App 内置了固定的 DNS 服务器 |
怎么检测 DNS 泄漏
搜索「DNS leak test」可以找到在线检测网站。它们的原理是:让你的浏览器解析一批随机生成的子域名,再看是哪些 DNS 服务器来问了这些子域名。
- 结果里只有海外的公共 DNS 服务器:没有泄漏;
- 结果里出现了你本地运营商的 DNS 服务器:有查询绕过了加密通道。
开着分流时,本地常用网站本来就会用本地 DNS 解析(为了更快、拿到就近的 CDN 地址),这是设计如此,不算泄漏;检测网站用的随机子域名不在本地网站清单里,应该走加密通道解析。
时序图:有保护和没保护的 DNS 查询
| 步骤 | 发生了什么 |
|---|---|
| ①–③ | 没有保护时,程序把明文的 DNS 查询直接发给本地 DNS。本地网络能看到查询的域名,路上的设备还可能抢先送回一个伪造的地址;真正的回答晚到一步,被程序丢弃 |
| ④–⑤ | 开启 TUN 模式后,程序照常发出 DNS 查询(目的端口 53),客户端把它截下来,交给自己的 DNS 模块处理 |
| ⑥–⑨ | 海外域名:客户端用加密的 DNS(DNS over TLS)发起查询,并且整条查询都走加密通道,由服务器一侧发往公共 DNS,结果原路加密送回 |
| ⑩ | 客户端把正确的地址返回给程序,程序再按分流规则发起连接 |
| ⑪–⑫ | 本地常用网站:客户端直接向本地 DNS 查询,拿到离你最近的 CDN 地址,速度最快 |
穿山甲怎么处理 DNS
- 接管所有 DNS 查询:TUN 模式下,发往 53 端口的查询都由客户端处理,不管程序设置的是哪个 DNS 服务器,都不会从本地网络漏出去;
- 海外域名走加密 DNS + 加密通道:使用 DNS over TLS 查询公共 DNS,查询在加密通道里转发,路上无法看到,也无法伪造;
- 本地常用网站就近解析:开启「智能分流」时,本地常用网站用本地 DNS 解析,避免拿到海外的 CDN 地址;
- 只解析 IPv4 地址:避免程序通过 IPv6 绕过加密通道。
如果你连着穿山甲仍然遇到证书错误或网站打不开,先断开重连并重启浏览器,清掉旧的 DNS 缓存;再检查浏览器是否开启了「安全 DNS」并指定了其他服务器。更多排查方法见 连不上怎么办。
相关阅读
常见问题
把 DNS 改成公共 DNS(比如 8.8.8.8)能解决 DNS 污染吗?
通常不能。普通 DNS 查询是明文的,不管发给哪个服务器,途中都能被看到和抢答。需要用加密的 DNS(DNS over HTTPS / DNS over TLS),或者让 DNS 查询走加密通道。
DNS 泄漏检测网站显示了本地运营商的服务器,是不是有问题?
如果此时用的是全局模式,说明有泄漏,可以检查系统或浏览器有没有单独设置 DNS。如果用的是分流模式,检测网站使用的随机域名不在本地网站清单里,正常应该显示海外的 DNS 服务器;显示本地运营商则说明有程序绕过了客户端。
开着加密通道,为什么有的网站还是提示证书错误?
可能是之前被污染的地址还留在系统或浏览器的 DNS 缓存里。断开重连、重启浏览器,或者在命令行清除 DNS 缓存后再试。
穿山甲会记录我查询了哪些域名吗?
不会。DNS 查询在加密通道里转发到公共 DNS 服务器,穿山甲服务器只统计流量用量,不记录访问的网站和查询的域名。