多张图带你彻底搞懂 DNS 域名解析过程
Category(分类): Other Status: 优
原文作者:林小鹿
本文保留原文关于 DNS 层级、递归查询、迭代查询和高速缓存的结构,并根据 RFC 1034、RFC 1035、EDNS、DNS over TCP、DoT 和 DoH 等规范修订容易误解的内容。原文截图已下载到本文同目录的
images/文件夹。
1、什么是 DNS
DNS(Domain Name System)是 域名系统的英文缩写。它是一套分布式、层次化的命名系统和资源记录数据库,最常见的用途是把主机名解析为 IPv4 地址(A 记录)或 IPv6 地址(AAAA 记录),也可以提供别名、邮件服务器、权威服务器、文本信息和服务发现等记录。
DNS 并不只服务于 Web。邮件投递依赖 MX 记录,服务发现可以使用 SRV 或 HTTPS/SVCB 记录,反向地址查询使用 PTR 记录,DNSSEC 则利用 DNS 记录提供数据来源和完整性验证。
2、DNS 的作用
通常我们有两种方式识别网络服务:通过主机名或者 IP 地址。人们更喜欢容易记忆、具有层次结构的主机名,而网络通信最终需要使用 IP 地址或其他协议地址。DNS 就像一个分布式目录系统,让应用可以通过主机名查找资源记录。
因此,不使用域名也可以通过 IP 地址访问某些服务,但直接写 IP 会带来几个问题:
- IP 地址难以记忆,且可能会变化;
- 一个 IP 可以承载多个虚拟主机,HTTP Host 和 TLS SNI 仍然需要域名;
- CDN、负载均衡和故障切换可能需要根据时间、线路或地域返回不同地址;
- IPv4 和 IPv6 可能同时存在,客户端需要根据网络能力选择。
当用户在浏览器地址栏输入 Web 域名时,浏览器通常会先查询自身缓存或连接信息,再通过操作系统的 stub resolver 向配置的递归 DNS 解析器发起查询。注意:浏览器、操作系统、hosts 文件、Service Worker 和本地网络设备都可能影响最终请求,DNS 只是访问流程中的一个阶段。

如果本地没有可用结果,stub resolver 会向递归解析器请求记录。递归解析器可能直接命中自己的缓存,也可能代表客户端继续向根、顶级域和权威 DNS 查询。

得到 A 或 AAAA 等结果后,客户端才能向目标地址建立 TCP/TLS、QUIC 或其他协议连接,再由 HTTP 客户端访问 Web 服务。DNS 返回 IP 并不代表网页已经加载完成。

DNS 返回的不一定只有一个 IP
DNS 的映射不是“一个域名永久对应一个 IP”:
- 一个名称可以拥有多个 A 或 AAAA 记录;
- 多个域名可以指向同一个 IP;
- CNAME 可以把一个别名指向另一个规范主机名;
- CDN 或负载均衡系统可能根据解析位置、时间和健康状态返回不同结果;
- 记录受 TTL 和各级缓存影响,修改后不会立即在所有网络中同时生效。
3、域名的层级关系
层级关系特点
- Internet 使用树状的域名空间;
- 域名由多个 label(标签)组成,展示时使用点号分隔;
- 级别较低、较具体的标签通常写在左侧,根域名在最右侧,完整域名可以用最后的点表示根,例如
www.example.com.; - 一个 label 最多 63 个八位组(octets),DNS wire format 中一个完整域名的长度上限通常是 255 个八位组;
- DNS 比较域名时通常不区分 ASCII 大小写,但应尽量保持注册和展示时的大小写;
- 常见主机名通常使用字母、数字和连字符,但国际化域名可以通过 IDNA/Punycode 表示,不能简单断言每一级只能由英文字母和数字组成;
- DNS 规范不规定每一级域名必须代表公司、地区或服务器,也不规定域名一定有固定数量的下级域名;
- 区域(zone)的管理边界由 DNS 管理者划分,不一定与“二级域名”边界完全相同。
原文说“最高的顶级域名由 ICANN 管理”过于概括。IANA/ICANN 负责根区相关协调和授权体系的一部分,顶级域注册管理机构、注册商、各组织和区域运营者分别承担不同管理职责;DNS 技术本身并不把所有管理工作归给一个机构。
Internet 的域名空间

从概念上可以看到:
根域名(.)
└── 顶级域(com.)
└── 组织或注册域(example.com.)
└── 主机名(www.example.com.)
图中的“根域名服务器、顶级域名服务器和权威域名服务器”属于不同层次的权威服务:
- 根服务器:权威回答根区内容,通常告诉递归解析器负责某个顶级域的 NS 记录和必要的 glue 地址,并不保存全世界每个主机名的最终 IP;
- 顶级域名服务器(TLD server):权威回答某个顶级域下的委派信息,例如
com.区域可以告诉解析器example.com.由哪些权威服务器负责; - 权威 DNS 服务器:对一个或多个 zone 的正式数据负责,可以直接返回 A、AAAA、CNAME、MX、TXT、SOA 等记录,或返回 NXDOMAIN/NODATA;
- 递归解析器(recursive resolver):为客户端执行递归服务,维护缓存并根据权威服务器返回的 referral 继续查询。它通常不属于根到 TLD 的权威层级,而是站在客户端一侧的缓存和查询代理。
原文称“因特网上共有 13 个不同 IP 地址的根域名服务器”。更准确的说法是:根区配置了 13 个根服务器标识(A 到 M),每个标识有公布的 IPv4/IPv6 地址;这些标识背后由不同运营者在世界各地部署了大量实例,通常使用 Anycast,绝不是只有 13 台物理服务器。
根服务器地址通常通过 root hints 提供给递归解析器,用于启动迭代解析流程。客户端一般不会直接查询根服务器。
4、DNS 域名解析过程
DNS 查询中有两个容易混淆的维度:
- **递归(recursive)**描述请求方是否要求服务器替自己完成后续查询;
- **迭代(iterative)**描述服务器只返回当前掌握的信息或下一步应查询的服务器,由请求方继续查询。
递归查询
如果客户端向递归解析器发起递归查询,并在请求中设置了 RD(Recursion Desired)标志,解析器会尽力替客户端完成查询,然后返回最终答案、错误或超时结果。
典型流程是:
- 客户端的 stub resolver 向本地递归解析器发起递归查询;
- 如果递归解析器缓存中没有结果,它作为 DNS 客户端向根服务器发起查询;
- 根服务器通常返回
.com等顶级域的 NS referral,而不是继续替递归解析器查询 TLD; - 递归解析器根据 referral 查询 TLD 服务器;
- TLD 服务器返回
abc.com.的权威 NS referral; - 递归解析器查询
abc.com.的权威服务器; - 权威服务器返回
y.abc.com.的 A、AAAA、CNAME 或错误结果; - 递归解析器缓存允许缓存的记录,再把结果返回给客户端。
假设主机希望解析 y.abc.com:
stub resolver --递归请求--> recursive resolver
recursive resolver --迭代请求--> root server
recursive resolver <--.com NS referral-- root server
recursive resolver --迭代请求--> .com TLD server
recursive resolver <--abc.com NS referral-- .com TLD server
recursive resolver --迭代请求--> abc.com authoritative server
recursive resolver <--A/AAAA/CNAME/NXDOMAIN-- abc.com authoritative server
stub resolver <--最终结果-- recursive resolver
原文把根域名服务器、顶级域名服务器和权威 DNS 服务器都描述成“收到递归委托后继续向下查询”,这是不准确的。实际部署中,根和 TLD 权威服务器通常提供迭代 referral;递归解析器负责沿着 referral 继续查找。

查询结果会经过递归解析器返回给客户端。若答案是 CNAME,解析器还需要继续解析 CNAME 目标,最终得到请求类型对应的记录或错误。

迭代查询
在迭代查询中,服务器返回自己能够提供的最佳信息:
- 如果它是目标 zone 的权威服务器,可以返回最终答案;
- 如果它只知道下一层委派信息,就返回 NS referral 和可用的 glue;
- 如果域名不存在,权威服务器可能返回 NXDOMAIN;
- 如果名称存在但没有请求类型,可能返回 NODATA(通常表现为 NOERROR 但 Answer 为空)。
典型的迭代过程如下:
- 主机向递归解析器发起递归请求;
- 递归解析器向根服务器发起迭代查询;
- 根服务器返回顶级域服务器的 NS 和相关地址;
- 递归解析器向顶级域服务器发起迭代查询;
- 顶级域服务器返回目标 zone 的权威服务器 NS 和相关地址;
- 递归解析器向权威服务器发起迭代查询;
- 权威服务器返回最终记录或错误;
- 递归解析器把结果返回主机。

“从主机到本地域名服务器递归、其余部分迭代”是常见的教学模型。现实中,解析器之间也可能使用转发(forwarding)、服务商私有调度、DNS over TLS/HTTPS 或其他部署方式;具体行为取决于服务器配置。
递归、权威和缓存的标志位
DNS 报文中常见的相关标志包括:
RD(Recursion Desired):客户端请求服务器提供递归服务;RA(Recursion Available):服务器表示自己是否提供递归服务;AA(Authoritative Answer):响应是否由对该名称负责的权威服务器给出;TC(Truncated):响应在当前传输中被截断,客户端通常需要改用 TCP 重试;RCODE:表示成功、格式错误、服务器失败、NXDOMAIN 等结果。
递归服务器不应对 Internet 任意来源开放递归,否则可能被用于 DNS 放大和反射攻击。公开递归服务需要访问控制、速率限制和运营安全策略。
5、高速缓存
为了减少重复查询、降低权威服务器负载并改善响应时间,DNS 系统广泛使用缓存。缓存可以存在于:
- 浏览器或应用内部;
- 操作系统的 stub resolver 或本地缓存服务;
- 家庭路由器、企业 DNS 或运营商递归解析器;
- 公共递归解析器;
- 其他 DNS 转发和代理层。
每条资源记录都有 TTL,表示缓存可以在多长时间内把它视为新鲜数据。缓存并不是永久保存,TTL 到期后解析器通常需要重新验证或重新查询。
原文举例“每个项目只存放两天”,这不是 DNS 的统一规则。TTL 由 zone 数据的管理者设置,可能是数秒、数分钟、数小时或更久;递归解析器还可能受到最小/最大 TTL、负缓存和服务商策略影响。

如果递归解析器刚查询过 y.abc.com,并且相应记录仍在 TTL 有效期内,它就可以直接把缓存中的答案返回给客户端,而不用再次访问根、TLD 和权威服务器。
缓存并不是下载整个 DNS 数据库
原文称“许多用户主机在启动时从本地域名服务器下载域名和 IP 地址的全部数据库”,这是错误的。客户端通常只缓存自己最近查询过的记录,不会在启动时下载整个 DNS 数据库;递归解析器也只缓存实际查询到的记录和必要的委派信息。
DNS 记录可能因为以下原因变化:
- 域名管理员修改 A/AAAA/CNAME 等记录;
- CDN 或负载均衡根据调度策略返回不同地址;
- 记录 TTL 到期;
- 权威服务器更新 zone 或发生故障切换。
修改记录后,旧答案在各级缓存的 TTL 到期前仍可能继续被使用,所以 DNS 变更通常不是实时全球同步。需要提前变更时,可以在变更前降低 TTL,但已经缓存的旧 TTL 不会被事后强行缩短。
负缓存
解析器也可能缓存“域名不存在”(NXDOMAIN)或“该名称没有这种记录类型”(NODATA)的结果。负缓存通常与权威响应中的 SOA 信息有关,因此刚创建一个此前不存在的域名后,部分用户仍可能在一段时间内得到旧的 NXDOMAIN。
排查 DNS 变更时,应同时查看:
dig example.com A
dig example.com AAAA
dig example.com CNAME
dig example.com +trace
+trace 会从根开始展示一条迭代查询路径,但它只代表执行命令的这台机器看到的路径,不等于所有用户的解析结果。
6、DNS 使用的传输协议
DNS 为什么常用 UDP?
更准确的答案是:DNS 同时使用 UDP 和 TCP,现代部署还可能使用 DoT、DoH 或 DoQ。
传统 DNS 查询常通过 UDP 53 端口传输,因为报文小、无须建立连接,适合低延迟的请求-响应模式。早期 DNS over UDP 的消息大小上限通常描述为 512 字节,但 EDNS(0) 允许请求方声明更大的 UDP 载荷能力,现代 DNSSEC、IPv6 和其他记录也经常需要超过 512 字节的响应。
如果 UDP 响应超过当前传输能力,服务器可能设置 TC(Truncated)标志,解析器随后通过 TCP 重试。根据 RFC 7766,通用 DNS 实现应支持 UDP 和 TCP;TCP 不是已经过时的备用协议。
TCP 的使用场景
DNS 使用 TCP 的场景包括:
- UDP 响应被截断后重试;
- AXFR 全量区域传送和常见的 IXFR 增量区域传送;
- 需要可靠传输的大型消息;
- DNS over TLS 的底层连接。
原文说“TCP 允许的报文长度更长”方向基本正确,但更重要的是 DNS over TCP 使用长度字段和可靠、有序的字节流。TCP 连接也有额外的建立和资源开销,因此正常小查询通常仍会优先使用 UDP 或由实现选择更合适的传输。
EDNS(0) 和 512 字节限制
EDNS(0) 扩展了 DNS 报文能力,允许请求方在 OPT 伪记录中声明可接收的 UDP 载荷大小,并提供 DNSSEC 等扩展所需的字段。512 字节是未使用 EDNS 时的历史限制,不是所有现代 DNS UDP 响应的固定最大值。
更大的 UDP 报文可能受到路径 MTU、分片和防火墙影响,因此解析器不能只把 EDNS 载荷设置得越大越好。出现大响应、分片丢失或中间设备异常时,TCP fallback 和连接管理都很重要。
DNS over TLS 和 DNS over HTTPS
传统 UDP/TCP DNS 的查询内容可能被路径上的网络设备观察或篡改。现代客户端还可以使用加密传输:
- DoT(DNS over TLS):通常在 TCP 853 端口上使用 TLS 加密 DNS 查询,主要保护 stub 到递归解析器的链路;
- DoH(DNS over HTTPS):把 DNS 查询封装在 HTTPS 请求中,通常使用 443 端口;
- DoQ(DNS over QUIC):使用 QUIC 传输 DNS,适用于支持该协议的客户端和解析器。
DoT/DoH 保护的是客户端到所选解析器之间的传输隐私,并不自动证明 DNS 答案来自权威来源,也不意味着解析器看不到查询内容。DNSSEC 解决数据来源认证和完整性问题,DoT/DoH 解决传输保密性和抗路径篡改问题,两者可以同时使用。
7、常见 DNS 记录类型
理解查询过程时,至少应认识下面这些记录:
- A:把名称映射到 IPv4 地址;
- AAAA:把名称映射到 IPv6 地址;
- CNAME:把别名指向规范主机名;
- NS:声明某个 zone 的权威名称服务器;
- SOA:记录 zone 的起始授权信息、序列号和刷新参数;
- MX:声明邮件交换服务器及优先级;
- TXT:保存文本信息,常用于 SPF、DKIM、域名验证等;
- PTR:用于反向 DNS,把地址空间映射回名称;
- SRV:描述某类服务的主机和端口;
- HTTPS/SVCB:提供服务端点、协议和连接参数等信息,现代客户端可能用它辅助 HTTPS/HTTP3 连接。
CNAME 和 A/AAAA 的关系尤其容易混淆:CNAME 记录的目标是另一个域名,解析器再根据目标名称查询 A/AAAA;CNAME 不是把域名直接写成 IP,也不是 HTTP 层面的重定向。
8、DNS 相关面试问题
1. DNS 为什么用 UDP?
更完整的回答是:DNS 同时支持 UDP 和 TCP。UDP 适合低延迟的小型查询;EDNS、DNSSEC 或响应过大时可能需要 TCP;区域传送通常使用 TCP。现代实现还可能使用 DoT、DoH 或 DoQ。
2. 递归查询和迭代查询有什么区别?
可以把它理解成“是否把后续查询外包出去”:
- 递归查询:请求方要求被查询的服务器替自己完成后续查询,最后返回最终答案或错误。典型是 stub resolver 到递归解析器;
- 迭代查询:服务器返回自己知道的答案、权威信息或下一步 referral,由请求方继续查询。典型是递归解析器依次查询根、TLD 和权威服务器。
递归和迭代是查询行为,不是简单的“某一种服务器永远只递归、另一种服务器永远只迭代”。具体取决于请求中的 RD、服务器是否提供递归服务以及服务器配置。
3. 使用域名访问 Web 服务器的过程
可以把流程简化为:
浏览器/应用缓存
-> hosts 文件和系统解析器
-> 本地递归 DNS 缓存
-> 根/TLD/权威查询(缓存未命中时)
-> 得到 A/AAAA/CNAME 等结果
-> TCP + TLS 或 QUIC
-> HTTP/1.1、HTTP/2 或 HTTP/3 请求
-> 服务器返回响应
DNS 解析只是地址发现阶段。即使 DNS 很快,TLS 握手、连接建立、服务器处理、CDN 缓存和资源下载仍然会影响页面加载速度。
4. 讲讲 DNS 解析过程
可以按照下面的顺序回答:
- 浏览器或应用检查自己的缓存;
- 操作系统解析器检查 hosts、系统缓存和配置的上游解析器;
- stub resolver 向递归解析器发送查询;
- 递归解析器命中缓存则直接返回,否则从根开始进行迭代查询;
- 根服务器返回 TLD referral,TLD 服务器返回目标 zone 的权威 NS;
- 权威服务器返回 A、AAAA、CNAME 或错误结果;
- 递归解析器按 TTL 缓存结果,再返回客户端;
- 客户端使用地址建立后续的 TCP/TLS 或 QUIC 连接。
9、DNS 排查常用工具
dig
dig 是 Unix/Linux/macOS 上常用的 DNS 查询工具:
# 查询 A 记录
dig example.com A
# 只打印最终地址
dig +short example.com A
dig +short example.com AAAA
# 查看 CNAME 链
dig +short www.example.com CNAME
# 从根开始展示迭代过程
dig +trace www.example.com
# 指定某个递归解析器查询
dig @1.1.1.1 example.com A
nslookup、host 和系统缓存
Windows 常用:
nslookup example.com
ipconfig /displaydns
ipconfig /flushdns
Linux systemd-resolved 环境可以使用:
resolvectl status
resolvectl query example.com
resolvectl flush-caches
清理缓存只能影响当前设备或当前解析服务,不能强制全球其他递归解析器立即丢弃旧记录。
总结
DNS 是一个分布式、层次化并带缓存的资源记录系统。理解它时可以抓住以下重点:
- 根、TLD 和权威服务器负责不同 zone 的权威数据,递归解析器负责为客户端缓存和完成查询;
- 递归查询是请求服务器代为完成后续查询,迭代查询是服务器返回 referral 让请求方继续;
- 根服务器不是 13 台物理机器,而是 13 个根服务器标识背后的全球实例网络;
- DNS 不只是“域名转 IP”,还包括 CNAME、NS、SOA、MX、TXT、PTR、HTTPS/SVCB 等记录;
- 512 字节是未扩展 UDP DNS 的历史限制,现代 DNS 需要 EDNS(0)、TCP 和更大响应处理;
- DoT、DoH、DoQ 与 DNSSEC 解决的问题不同,不能互相简单替代;
- TTL、正缓存和负缓存都会影响 DNS 变更的生效时间;
- DNS 解析完成后还要经过 TCP/TLS、QUIC、HTTP 和服务端处理,不能把所有访问延迟都归因于 DNS。