同一个域名,为什么有人访问新服务器,有人还访问旧服务器?
设想你把 www.example.com 的地址从 192.0.2.10 改为 192.0.2.20。权威配置已经更新,但部分用户仍连接旧地址;另一些用户换了网络,查询结果又不同。
DNS(Domain Name System,域名系统)不是每次都向一个全球数据库读取最新值。它通过分层授权分散维护记录,再让解析器缓存结果。得到哪个答案,取决于查询类型、所用解析器、缓存状态及权威配置。 本章用虚构配置解释这些状态,不代表 example.com 的真实解析结果。
先区分问问题的人与维护答案的人
应用需要查询域名时,可使用操作系统的解析接口,由本地 Stub Resolver(存根解析器)向递归解析器发出请求。浏览器也可能使用自己的解析与缓存机制,或选择加密 DNS 服务,因此不存在所有平台都固定遵守的一条“浏览器 → 系统 → 路由器”缓存查找顺序。
递归解析器(Recursive Resolver)替客户端寻找最终答案,通常维护缓存。它可能由网络运营方、企业或公共 DNS 服务提供。权威服务器(Authoritative Server)则负责某个区域的正式数据。一个设备可以承担多种角色,但“替别人查询”与“维护该区域的权威答案”仍是两种职责。RFC 1034 §4、§5
域名按点分层,www.example.com. 的末尾点表示根;.com 是顶级域,example.com 可以作为被委派的区域。DNS 的区域(Zone)是管理范围,并不必然覆盖该域名下所有层级:子域还可以继续委派。
没有缓存时,谁向谁继续查询?
设想客户端要查询 www.example.com 的 A 记录,递归解析器既没有答案,也没有可用的中间委派缓存,但已知根服务器的启动信息。我们省略重试、服务器冗余、别名与额外委派,只观察一条成功路径:
查看 Mermaid 源码
sequenceDiagram
participant C as 客户端
participant R as 递归解析器
participant Root as 根服务器
participant T as com 服务器
participant A as example.com 权威
C->>R: 请求最终答案:www.example.com A
R->>Root: 查询 www.example.com A
Root-->>R: 转介:com 的服务器
R->>T: 查询 www.example.com A
T-->>R: 转介:example.com 的服务器
R->>A: 查询 www.example.com A
A-->>R: A = 192.0.2.10,TTL = 300
R-->>C: 返回答案并按规则缓存客户端请求 R 帮它查到底,这是递归请求。R 收到根和顶级域的转介后,自己继续向下一组服务器查询,这是迭代查询。根服务器并没有替 R 把查询一路转发到 example.com,通常也不掌握所有网站的最终地址。RFC 1034 §4.3.1、§4.3.2
转介通过 NS 等记录指出下一组权威服务器,必要的 Glue(胶水)地址记录帮助解析器联系被委派服务器,避免查服务器地址时陷入循环依赖。图中的返回箭头都是发给 R,不能把它画成“权威 → 顶级域 → 根逐级回传”。
若 R 有可用的 A 缓存,可以直接回答;若只缓存了 example.com 的委派信息,就可以从那里继续,无需从根重新开始。有些解析器把工作转发给上游递归服务,流程还会多一层。现代查询也可能减少向上层服务器暴露的完整名字,图中的完整查询是基础机制示意,而非所有实现的逐字报文。
DNS 返回的不只是一个 IP
一条资源记录通常包括名称、类型、类别、TTL 与类型对应的数据。请求中的 QTYPE 指明要找什么,查 A 和查 AAAA 并非同一个问题。RFC 1035 §3、§4
| 类型 | 表达什么 | 教学示例 |
|---|---|---|
| A | IPv4 地址 | www.example.com → 192.0.2.10 |
| AAAA | IPv6 地址 | www.example.com → 2001:db8::10 |
| CNAME | 名字的别名关系 | www.example.com → edge.example.net |
| NS | 区域的名字服务器 | example.com → ns1.example.com |
| MX | 邮件交换服务器及优先级 | 指向邮件服务器名字 |
| TXT | 文本数据 | 承载约定格式的验证信息等 |
| PTR | 反向查询中的名字指针 | 地址的反向名字对应主机名 |
AAAA 的 IPv6 数据格式见 RFC 3596 §2。一个名字可以有多个地址,客户端不一定按返回列表的固定顺序选择;地址选择、重试和双栈连接策略也会影响最终连接目标。
CNAME 的目标是名字,而不是 IP。查 A 时遇到别名,解析过程还需要继续取得目标名字的 A 记录,返回中可能同时包含别名和最终地址。CNAME 不是 HTTP 重定向:它参与名字解析,不会让浏览器自动把地址栏改成目标名字,也不改变原请求需要匹配的 HTTPS 主机身份。
TTL 是缓存计时,不是全网同步按钮
DNS TTL(Time To Live)通常以秒计,表示相关记录可缓存的时间;它和上一章 IP 报文的 TTL 不是同一字段。缓存返回答案时应反映剩余有效时间,不能每回答一个用户就把同一旧记录的有效期重新加满。
假设 R 在 10:00:00 获得旧 A 记录,TTL 为 300 秒;不考虑预取、过期数据服务或提前驱逐:
| 时刻 | 发生什么 | R 的普通缓存结果 |
|---|---|---|
| 10:00:00 | 从权威获得 .10 | 可缓存至约 10:05:00 |
| 10:01:00 | 权威改为 .20 | R 的旧缓存仍有效 |
| 10:03:00 | 又有用户查询 R | 可以返回 .10,剩余约 120 秒 |
| 10:05:01 | 旧缓存已到期,再次查询 | 需要获取可用新答案;本例得到 .20 |
TTL 到期本身不要求每个缓存立刻发起查询,也不意味着所有缓存同时到期。它们取得旧答案的时刻可能不同,客户端还有独立缓存或已复用的连接。服务端改记录后不会通过普通 DNS 查询流程立即通知所有客户端。RFC 1034 §3.6、§4.3.4
所以迁移前调低 TTL,需要给已缓存的旧 TTL 留出消退时间;迁移发生时才改小,并不能撤销别人先前缓存的有效期。这个建议由缓存计时机制推导,不是承诺“等新 TTL 秒数就全网切换”。
还有实现边界:解析器可提前驱逐缓存、预取更新,或按专门策略提供过期数据以改善故障期间的可用性。RFC 8767规定了 Serve Stale 机制。因此排障时要看具体策略,而不是把本例的简单时间线当作所有 DNS 服务的保证。
动手推进一次缓存时间线
在 10:01:00 修改权威地址,再到 10:03:00 查询 R。重复查询会延长旧缓存吗?最后推进到 10:05:01,先观察缓存,再发起一次查询。
R 在 10:00:00 缓存旧 A 记录,TTL 为 300 秒。推进时间,再修改权威或查询 R。
当前时间:10:00:00
www.example.com
192.0.2.10
TTL:300 秒
192.0.2.10
剩余 300 秒
原到期:10:05:00
10:00:00:R 从权威取得 192.0.2.10,缓存 300 秒。
仅推演一个解析器的成功 A 查询。时间前进不会自动刷新;过期后需查询才获取新答案。不含预取、提前驱逐、Serve Stale、负缓存、客户端独立缓存与连接复用,因此不是全网生效倒计时,也不请求真实 DNS。
“查不到”也可能被缓存
NXDOMAIN 表示所查询名字不存在;NODATA 通常指名字存在,但没有所请求类型的数据。两者不能与 SERVFAIL(服务端未能完成查询)混为一谈,更不能一律解释为“网络断了”。
否定结果可以缓存。按 RFC 2308 §3、§5,相关 SOA 数据参与确定负缓存有效时间;基本值取 SOA 记录 TTL 与 SOA.MINIMUM 的较小值。例如分别为 600 和 120 秒,就得到 120 秒,而不是 600 秒。
如果名字不存在的答案刚被缓存,随后新建记录,用户也可能在负缓存消退前仍查不到。排查“新域名没生效”时,除了 A/AAAA 记录,还要关注返回状态、负缓存和实际使用的解析器。
为什么既有 UDP 53,也有 TCP 53?
传统 DNS 查询常用 UDP,省去建立 TCP 连接的一轮成本;但 DNS 从来不只支持 UDP。常规明文 DNS 服务使用 UDP 或 TCP 的 53 端口,客户端源端口通常不是固定的 53。
早期没有扩展的 UDP DNS 消息上限是 512 字节。EDNS(0) 让查询方通告能接收更大 UDP 消息的能力;这不保证中间路径一定能无损承载更大的报文,也不消除上一章的 MTU 与分片问题。RFC 6891 §4、§6
UDP 响应若被截断,TC 标志提示结果不完整,客户端通常需要用 TCP 重新取得完整响应。TCP 也可直接用于普通查询,并非只有“超过 512 字节”或区域传送时才能使用。现代通用 DNS 实现须支持 TCP,连接也可复用。RFC 7766 §5、§6
因此不能用“DNS 一次查询很小”推导“防火墙只开放 UDP 53 就够了”;大响应、DNSSEC 数据和回退路径都需要考虑。
DoT、DoH 与 DNSSEC 分别保护什么?
DoT(DNS over TLS)在 TLS 连接中传递 DNS 消息,默认 TCP 853;DoH(DNS over HTTPS)把 DNS 消息放入 HTTPS 交互,通常使用 HTTPS 的 443 端口。它们改变传输与隐私条件,仍在询问 DNS 记录。RFC 7858 §3、RFC 8484 §4
例如客户端到递归服务使用加密通道,只能说明这一段受到相应保护,不能推导出递归服务到所有权威的查询也加密。所选递归服务仍能看到它处理的查询;换用浏览器自己的 DNS 服务还可能影响企业内部名字解析。安全模式、认证与回退要按实际配置判断。
DNSSEC(DNS Security Extensions)通过签名及信任链验证 DNS 数据的来源与完整性,并支持认证否定答案;它不负责加密查询内容,也不替代网站 TLS 或业务认证。DoH/DoT 与 DNSSEC 可以配合,而不是互相替代。RFC 4033 §3、§4
怎样区分名字问题与连接问题?
| 证据 | 可以继续缩小的范围 |
|---|---|
| 不同解析器给出不同地址 | 比较缓存 TTL、内外网区域与权威数据,差异不一定是故障 |
| 返回 NXDOMAIN | 核对拼写、查询名字和负缓存 |
| 返回 SERVFAIL | 核对上游可达、权威状态与验证失败等原因 |
| A 查询成功,但浏览器连接失败 | 检查 AAAA、实际选中地址、端口、TLS 与应用 |
直接把域名改成 IP 并访问 HTTPS,可能因主机名、SNI 或证书匹配条件改变而失败,不能把这个对照简单当作 DNS 根因证据。具体诊断命令留到排障章,那里会保留请求的主机身份来控制变量。
面试时怎样回答?
30—60 秒参考回答
应用通过解析机制向递归解析器请求 DNS 答案。没有可用缓存时,递归解析器通常沿根、顶级域和被委派权威的转介继续查询,再把最终记录交给客户端;这包含客户端的递归请求和解析器的迭代查询。有缓存时不必每次经过根。A 对应 IPv4,AAAA 对应 IPv6,CNAME 是名字别名。TTL 控制缓存时间,既有缓存不会因权威修改立即消失。DNS 支持 UDP 和 TCP,EDNS 可扩大 UDP 消息能力,截断时常回退 TCP。DoT/DoH 保护传输,DNSSEC 验证数据,它们职责不同。
四个追问及解析
- 根服务器会返回所有网站的 IP 吗? 通常返回相关顶级域的转介信息;最终答案由对应权威提供,缓存可省略部分查询。
- 把 TTL 改为 30 秒,30 秒后所有人都用新地址吗? 不能保证。已有旧 TTL 缓存、独立客户端缓存和连接复用都需要考虑。
- CNAME 和 HTTP 301 有什么区别? 前者在 DNS 解析中关联名字,后者是应用响应中的重定向指示;二者不会产生相同的地址栏与请求语义。
- 使用 DoH 就能确认权威记录没有被篡改吗? 加密到所选服务不等于对权威数据做 DNSSEC 验证,服务身份、信任与数据验证要分别判断。
两个易错说法
- “DNS 只用 UDP,超过 512 字节才改 TCP。”EDNS 改变 UDP 消息大小能力,TCP 本身也可直接承担普通查询。
- “DNS 成功就证明网站正常。”名字解析只是获得候选连接信息,后面仍有传输、TLS 和应用交互。
现在有了目标地址,主机却还需决定把收到的数据交给哪个应用。下一章从端口、连接和 Socket 继续追踪这条路径。
资料与核验日期
核验于 2026-10-08。域名、地址、时间与响应均为教学设定,没有声称执行真实 dig 查询。基础 RFC 的后续扩展按本章主题补充,DNS 不以 1987 年两份文档作为全部现行行为。