先认识四个角色
访问一个网站时,我们输入的是域名,而网络连接通常需要目标 IP 地址。DNS(域名系统)把域名与资源记录联系起来。它是一套分层、分布式的命名系统,并不是一张存放在某一台服务器上的巨大通讯录。
- 客户端与递归解析器:应用通过系统解析接口或自己的解析方式发出查询。递归解析器接收查询,利用缓存或继续查找,最终返回答案或错误。
- 根服务器:处于 DNS 层级的起点。对于常见的公网域名查询,它通常提供相应顶级域的委派信息。
- 顶级域(TLD)服务器:例如负责
.com的服务器,提供该顶级域下某个域的权威服务器信息。 - 权威 DNS 服务器:负责特定区域的数据,返回自己管理的记录,或进一步的子域委派。
这里的“递归”描述的是客户端希望解析器替自己得到最终结果;解析器向不同层级服务器逐步询问时,通常采用迭代查询。根服务器不会替客户端把后面的流程全部跑完。
一次解析的完整旅程
以查询 www.example.com 的 A 记录为例。为了看清各个角色,先假设没有可用缓存,也没有额外的子域委派。下面是一条教学用的简化路径,真实请求不一定经过每一步。
- 客户端发起查询。应用所在设备把请求交给选定的递归解析器,询问这个名称的 A 记录。
- 解析器询问根服务器。根服务器返回
.com的委派信息,而不是目标网站的 IP。 - 解析器询问 .com 服务器。它得到
example.com的权威 DNS 服务器信息。 - 解析器询问权威服务器。权威服务器返回相应记录。如果答案是 CNAME,解析器可能还需要解析它指向的另一个名称。
- 返回并缓存结果。解析器把结果交给客户端,并根据相关记录的 TTL 管理缓存。客户端随后可以使用地址发起连接。
A 与 AAAA:A 记录对应 IPv4 地址,AAAA 记录对应 IPv6 地址。一个名称可以有多个地址记录;最终如何尝试连接,由客户端和网络条件共同决定。
缓存改变了什么
DNS 层级让数据能够分散管理,缓存则减少了反复查询。递归解析器如果已经保存了仍可使用的答案,就可能直接回复,不必再次从根开始。浏览器、操作系统和解析器都可能拥有各自的缓存。
TTL(生存时间)以秒为单位,告诉缓存一份资源记录可以保留多久。看到的剩余 TTL 会随时间减少。TTL 不是“修改后全世界同步生效的倒计时”:旧答案可能仍在缓存中,不同记录和不同解析器的状态也不相同。
对“不存在”的回答也可能进行负缓存。因此,新增一条此前不存在的记录后,也不应假设所有客户端会立刻看到它。排查时需要区分“权威服务器现在提供什么”和“递归解析器当前缓存了什么”。
用 dig 观察 DNS
在 Debian 中,dig 由 dnsutils 包提供。以下命令使用公开的示例域名,目的是观察结构;不预设它在任何时间都返回同一组地址。
sudo apt update
sudo apt install dnsutils查看记录与响应信息
dig www.example.com A
dig www.example.com AAAA
dig example.com NS先观察响应头中的 status,再看 ANSWER SECTION 的名称、TTL、类型与值。SERVER 表示这次查询实际询问的服务器。NOERROR 也可能没有所查询类型的答案;NXDOMAIN 表示查询的名称不存在,SERVFAIL 则表示服务器未能完成解析。
观察委派路径
dig +trace www.example.com A+trace 让 dig 自己沿委派链进行迭代查询,帮助观察根、TLD 与权威层级;它并不是远程递归解析器内部执行过程的抓包。该命令需要直接访问多个 DNS 服务器,在受限网络中可能超时。
几个容易混淆的概念
- DNS 不只负责网站地址。MX、TXT、NS 等记录承担不同用途,查询时的记录类型同样重要。
- CNAME 不是 HTTP 跳转。它是 DNS 层的名称别名;浏览器是否改变地址栏,需要看 HTTP 响应等后续行为。
- DNS 不只使用 UDP。传统 DNS 也支持 TCP,截断响应等情形可能触发 TCP 重试;DoT、DoH 则提供不同的加密传输方式。
- DNSSEC 与加密传输目的不同。DNSSEC 验证数据的来源真实性与完整性,不负责隐藏查询内容;加密传输也不等于 DNSSEC 验证。
排查解析问题时,一个有用的顺序是:确认查询名称与类型,再比较缓存答案和权威答案,最后检查委派、网络可达性及验证错误。把问题拆到对应层级,比反复清空缓存更有帮助。