引子
当我们不挂梯子的时候访问 www.google.com 会发生什么? 没错,大概率是访问不到的,我的火狐浏览器会一直显示在连接但是连接不到,那么这是为什么呢?
这是因为我们的 DNS 受到了污染,也有可能遭到了劫持,至于这两者是什么意思,就请慢慢往下看吧。

DNS是什么
全称 domain name system
还是拿 www.google.com 举例,这是一个 url,当我们在浏览器中输入它的时候,我们电脑中的软件会根据它将其翻译为一个具体的 IP 地址,然后访问这个 IP 从而访问到真实的网站。
这整个过程就是域名解析,没错,DNS 就是一个翻译器的角色。至于它怎么翻译的,我们稍后会说。
那我们顺便来解释一下这个 url 吧,很明显它通过 dot 分为了几个部分,因为互联网上的域名是树形结构组成的,从 .com开始是顶级域名,往左边依次递减;平时常见的 .cn .org等都是顶级域名。
好的,知道了这些,我们就来解释一下从我们的电脑视角出发,域名解析的过程是怎么样的。
从客户端的视角出发
发起对 url 的访问请求后
- 浏览器会先检查自己有没有缓存过这个域名的 IP 地址(这叫浏览器缓存),如果没有进入下面步骤:
- 找本地 DNS 缓存(其他程序访问过留下的);
- 找 Host 文件
/etc/hosts,查看这个 url 是否有写好的对应 IP 地址; - 如果有,那直接获取这个地址;如果没有,会去查我们是否有配置(在hosts中)指定的 DNS 服务器地址(比如我们常见的 8.8.8.8,或者路由器自动配置的)
- 如果有,电脑会向这个 DNS 服务器发送 DNS 查询请求,等待其返回我们想要的 IP 地址
- 最终拿到 IP 地址并访问。
从服务器的角度出发
刚刚我们的电脑把解析任务都交给指定的 DNS 服务器了,那么它具体做了什么呢?
- 我们平时配置的服务器都是递归(本地)服务(解析)器,而这个 DNS 服务器可能也有缓存,如果有就直接回复
- 如果没有,递归就会去找根域名服务器帮忙,询问:“请问 .com 顶级域名的服务器在哪里?”
- 根服务器会返回 .com 顶级域名服务器的地址,然后到了顶级域名服务器再问 “ google.com 的权威服务器在哪里?”
- 到了权威服务器后,“www.google.com 这个域名的 IP 地址是 xxxx”
- 最后,递归服务器问了一圈拿到了这个 IP 地址后给到电脑,电脑再给到浏览器,浏览器再拿去访问,同时缓存。
这里需要注意的是,缓存是个很重要的东东,因为这一串访问是十分耗费时间的;
同时如果某个域名对应的 IP 地址变了或者这个域名不再使用了该怎么办?在我们的递归服务器上会对这些记录有周期记录,其生命周期一过就会重新去找各位大哥服务器寻找最新的 IP 。
可能发生的问题
看了上面的两类流程后,你觉得可能会发生什么问题吗?我所说的问题不是解析不到 IP 的问题,有没有可能我们拿到假的 IP 地址?
拿一个案例来说,很早以前,据坊间流言,有的网络中访问 www.google.com最终会呈现出百度的首页,这是为什么呢?
这就引出了我们接下来要说的两个问题:DNS 污染 与 DNS 劫持。
DNS劫持
回答我们上面案例中的问题,这是因为我们的 DNS 被污染了——在某些运营商的网络下,它会给我们自动设置 DNS 递归服务器地址.
And by default, the OS will just use whatever resolver the network told it to. When the computer connects to the network and gets its IP address, the network recommends a resolver to use.
在我们进行 DNS 解析的过程中,它会将递归服务器中有关 www.google.com的对应 IP 地址悄悄地“更改”为百度的 IP 地址(至于其为什么这么做,肯定是与百度有合作的啦)
这就造成我们每次访问谷歌的时候在递归服务器的缓存中都是百度的 IP 地址,自然就跳转到了百度的首页。
这整个过程就是 DNS 劫持。
如何做到劫持
劫持通常都是 ISP(运营商)干的好事,如果我们用它自动设置的递归服务器地址,那么就得按照这个服务器上的规则来,它一旦修改了某个域名对应的 IP 地址,我们自然就被劫持了。
That’s because the resolver itself — the one that the network gives to you — could be untrustworthy.
如何应对劫持
最简单的的方法就是修改我们 hosts 文件中的 DNS递归服务器的地址,不再是运营商为我们自动分配的,比如改成8.8.8.8,8.8.4.4这些常见的地址。
这些是谷歌提供的地址,谷歌不至于劫持我们的 DNS 请求吧,这就可以避免 ISP 根据其递归服务器地址来劫持我们的请求。 Firefox的应对方法是使用 Cloudflare 作为他们的递归服务器,因为 Cloudflare 承诺保证用户的隐私性。
但是这并不能解决所有问题,因为 DNS 查询的明文性,还是会有可能直接拦截 UDP/53 端口并进行重定向。

那怎么办?诶,还有对策,但是这里的对策涉及到了其他知识点,我们先放放,待会儿再说。
DNS污染
除了劫持这种直接的手段以外,还存在更高明的手段,就算我们修改了递归服务器的地址,DNS 污染也能让我们访问不到正确的网站。
这是因为在 DNS 应答的过程中存在时间差,我们得等 DNS 递归服务器去外面兜一圈,但是等到它回来发现家都被偷了!

其实 DNS 污染还有一个更加可怕的名字,DNS 投毒。至于为什么,请看下面的内容。
如何做到污染
This means that every server that you ask to help with domain name resolution sees what site you’re looking for. But more than that, it also means that anyone on the path to those servers sees your requests, too.
上面说过,DNS 查询的过程是明文的(UDP/53)。 所以这条查询路上的中间人可以监听你的 DNS 请求包,并快速伪造一个虚假的 DNS 响应包抢在真正的回应前返回,这样我们就会拿到错误的 IP 地址。
那为什么又叫做投毒呢?假如我们不用国外的递归服务器,还是用国内 ISP 的,ISP 并没有发生劫持。 但是我们要访问一些国外的网站,那这些请求就一定要出海,在这个过程中有人对我们进行 DNS 污染,这会导致什么后果呢?还记得我们前面说到的重要的缓存吗?这就会让国内的服务器上记录这些域名与其错误的 IP 地址,那久而久之,广而广之,所有的国内服务器是不是已经全部被污染了!
最终,我们从任何一个国内服务器访问这些网站都会定向到假的 IP 地址,这就达到了恐怖的投毒效果,火烧连营啊!

如何应对污染
从原理看我们已经发现了DNS 过程的脆弱性了,DNS 查询过程是明文的,我们对其加密不就好了吗?
这样,就引出了 DNSSEC, DoT, DoH 这三种更为高级的 DNS 技术。来看看怎么回事。
高级的DNS
DNSSEC
这是出现较早的一种方法,它的目的是保证数据的完整性,确保 DNS 的响应不被篡改。怎么做到的呢?
增加了数字签名机制,会在每一级使用数字签名来证明下一级的可信性。
回到我们服务器的角度,DNS 递归解析器内置了根域的公钥,根服务器会返回 .com的DNSKEY,NS记录,用根的公钥验证.com的DNSKEY,用这个DNSKEY 验证 NS 记录,依次类推。
整个过程就是:上一级用数字签名告诉你:“下一级公钥是真的”,从根开始,逐级验证,一环都不能断。 所以完整性由上级域保证,其他人就无法篡改我们的内容了,就算你返回一个假的响应包过来,没有签名验证,我们客户端的递归服务器是不要的。
但是,诶,是不是还有些问题?我们只保证了数据的完整性,但是数据的加密没有得到保证
- 别人依然能看到我们这个 DNS 请求是往哪里去的,隐私在别人面前暴露无疑。
- 劫持仍有可能发生,因为我们本机与递归服务器之间还有一段传输过程,这一段传输过程没人管啊。
因为上述缺点,引出下面两个更加强大的方式。

DoT
全称 DNS over TLS,通过TLS协议加密DNS查询和响应,防止窃听和篡改.(关于TLS如何做到这一点,见这篇文章)
专用端口 853 运行 DNS over TLS,与传统明文 DNS(UDP 53端口)隔离;TLS握手:客户端与递归服务器建立加密连接。
协议栈如下:
--------
DoT
--------
TLS
--------
TCP
--------
IP
--------
缺点在于853端口可能被 ISP 禁用,客户端也就是我们的电脑或者浏览器需要支持 DoT,目前很多的浏览器更多地在用 DoH,至于为什么请往下看。
DoH
全称 DNS over HTTPS,诶,相比于 DoT多了什么?多了HTTP!(HTTPS=HTTP+TLS)
协议栈如下:
--------
DoH
--------
HTTP
--------
TLS
--------
TCP
--------
IP
--------
同时还可以做到将 DNS 查询伪装成普通 HTTPS 流量,绕过审查和干扰(DNS查询通过HTTP/2或HTTP/3传输,端口443,与网页流量混合)
由于集成了 HTTP 的缘故,像 Firefox, Chrome 等浏览器都集成这个功能,但是比 DoT来说更大了。
并且有的浏览器和服务商也根据 DoH 对 DNS 的过程进行了优化,例如循环访问的过程只携带部分信息。QNAME minization(我们上面举例的过程其实就做到了QNAME minization)
潜在问题
在 HTTPS的过程中,有这样一个问题:你访问网站时最开始的 SNI 还是明文,可能被 ISP 知道你访问了什么站;但一旦 TLS 建立成功,你访问服务器上其他站点的过程是加密的,也更私密了。
这一点我们在后续有关HTTPS的文章中详细讨论。
总结
DNS 作为域名与 IP 地址之间的翻译器,会通过一系列的 recursive resolve 来进行翻译。 在这个过程中可能会遇到 DNS 劫持和污染,为了防止这些问题,其采用了 DNSSEC, DoT, DoH 等策略来对传输的数据进行加密和防止篡改。
最后关于文章一开始说的挂梯子的操作,其为什么可以让我们访问到原本被污染或者劫持的网站,简单来讲是因为 VPN 会加密所有流量(包括 DNS),这样攻击者就无法识别我们这些流量的作用,自然就不能轻易地攻击我们。(关于 VPN 如何加密后面考虑出一篇文章)
这里是LTX,感谢您阅读这篇博客,人生海海,和自己对话,像只蝴蝶纵横四海。
引用
- https://hacks.mozilla.org/2018/05/a-cartoon-intro-to-dns-over-https/
- ChatGPT & DeepSeek