目录
科普原理

DNS 污染与 DNS 泄漏:网页打不开的常见原因

网页打不开、证书报错,很多时候问题出在第一步:查地址。DNS 污染是查到了错误的 IP,DNS 泄漏是连着加密通道、查询却仍然发给了本地网络。用问路打比方讲清两者的原理、检测方法和客户端的处理方式,配时序图逐步说明。

最后更新:

在浏览器里输入一个网址,第一件事是查地址:把域名换成 IP 地址,这一步叫 DNS 解析。如果这一步出了问题,后面的连接、加密、加载都无从谈起。两个最常见的问题是:

  • DNS 污染:查到的是错误的 IP,连过去要么连不上,要么证书报错;
  • DNS 泄漏:明明连着加密通道,DNS 查询却绕过了通道,仍然发给了本地网络,你访问了哪些网站一目了然,也照样可能被污染。
插图:左半边,旅人在问路亭问路,灰袍人抢先塞给他一张假地址,他按假地址走到一座废弃的空房子;右半边,旅人坐在隧道车里探头向路边问路,被路人记下,下方是正确做法:问题封进信封,在隧道里交给可信的地址簿,拿回正确地址
  1. ① 出门前先问路DNS 查询:域名换成 IP
  2. ② 有人抢答伪造的回答先到,被当真
  3. ③ 走到空房子DNS 污染:网页打不开
  4. ④ 探头向路边问路DNS 泄漏:查询绕过了通道
  5. ⑤ 在隧道里问可信的地址簿加密 DNS + 加密通道

先打个比方:出门前先问路

DNS 就像路口的问路亭,里面放着一本大地址簿。你要去一个地方,先问亭子里的人「这个地方在哪」,拿到地址再出发。

  1. 正常问路:你问,亭子查地址簿,告诉你正确地址。
  2. 有人抢答:你刚问出口,路边一个人抢在亭子前面塞给你一张假地址。你没法分辨真假,就先信了先到的那张。
  3. 结果:你按假地址走到一座废弃的空房子,门是锁的。这就是 DNS 污染:网页打不开,但网络本身是通的。
  4. 坐在隧道里探头问路:你已经坐进了密封的隧道车,可还是把头伸出窗外,向路边的亭子大声问路。旁边有人拿本子记下你要去哪,抢答的人也照样能塞假地址。这就是 DNS 泄漏。
  5. 正确做法:把问题封进信封,在隧道里交给隧道另一头可信的地址簿,拿回正确的地址,整个过程外面看不到。

DNS 查询是怎么完成的

一次典型的 DNS 解析(详细过程见 常见网络协议):

  1. 程序问操作系统:www.example.com 的 IP 是多少?
  2. 系统先查本机缓存,没有的话,发给网络里配置的 DNS 服务器(通常是路由器或运营商自动下发的);
  3. 这个服务器如果也没有缓存,就逐级询问根服务器 → 顶级域(.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 服务器。后果有两个:

  1. 隐私:本地网络虽然看不到网页内容,却能从 DNS 查询看到你访问的每一个域名;
  2. 照样被污染:查到的还是错误地址,即使后面的连接走加密通道,连的也是错误的 IP,网页照样打不开。

常见原因:

原因说明
只用了系统代理系统代理只接管遵守代理设置的程序,其他程序的 DNS 查询完全不受影响(见 系统代理与 TUN 模式)
IPv6 绕过客户端只接管了 IPv4,系统却通过 IPv6 向 DNS 服务器发起查询
系统向所有网卡并发查询部分系统为了加快速度,会同时向每块网卡的 DNS 服务器发查询,谁先回用谁
程序自带 DNS浏览器开启了「安全 DNS」、部分 App 内置了固定的 DNS 服务器

怎么检测 DNS 泄漏

搜索「DNS leak test」可以找到在线检测网站。它们的原理是:让你的浏览器解析一批随机生成的子域名,再看是哪些 DNS 服务器来问了这些子域名。

  • 结果里只有海外的公共 DNS 服务器:没有泄漏;
  • 结果里出现了你本地运营商的 DNS 服务器:有查询绕过了加密通道。

开着分流时,本地常用网站本来就会用本地 DNS 解析(为了更快、拿到就近的 CDN 地址),这是设计如此,不算泄漏;检测网站用的随机子域名不在本地网站清单里,应该走加密通道解析。

时序图:有保护和没保护的 DNS 查询

程序 客户端 本地 DNS 加密服务器 公共 DNS 没有保护:明文查询 明文 DNS 查询 1 路上抢答的伪造地址 2 真实地址晚到,被丢弃 3 TUN 模式:客户端接管 DNS DNS 查询(53 端口) 4 截下,交给 DNS 模块 5 加密的 DNS 查询 6 转发查询 7 正确地址 8 加密送回 9 返回正确地址 10 本地常用网站:就近解析 本地解析 11 就近的 CDN 地址 12
粗线表示加密转发的流量,虚线表示返回的结果。程序只认最先到达的回答,所以明文查询很容易被抢答。
步骤发生了什么
①–③没有保护时,程序把明文的 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 服务器,穿山甲服务器只统计流量用量,不记录访问的网站和查询的域名。

还没有安装穿山甲?

支持 iPhone / iPad、Mac、Windows 与 Android。新用户注册即送 7 天会员体验。

下载客户端
← 全部文章