DNS是如何一步步查到IP的
本文讲解了DNS是如何通过递归查询,一步步查到IP的

书接上回
在我开发部署网站的过程中,对相关知识又有了新的收获,所以打算把用浏览器打开网页过程中涉及到的各种技术原理写一写。
之前有网友提醒,我写的不是打开网页的过程,而是根据域名找到网页的过程,这个确实是我没有交代清楚。我原计划是要把 DNS、HTTP、CDN、网页加载、渲染等,也就是打开网页的整个过程都写一写的,所以才说是打开网页,只是目前刚写到 DNS。
不过我以前没做过专职的前端,对于偏向渲染侧的技术了解也不是太多,还不确定能写到什么程度,至少写到那之前,我自己也得研究下。
上周介绍了在本地网络中与 DNS 相关的流程。也就是请求一个域名后,会依次检查浏览器 DNS 缓存、系统 DNS 缓存、hosts文件、路由器DNS缓存等,如果能匹配到域名,就直接返回结果,如果没有有效缓存,才会把这个查询请求发送给运营商提供的 DNS 服务器。
这周就继续说说,请求到了运营商提供的 DNS 服务后,又是如何查询到 WEB 服务器的 IP 的。
域名
我们先来看一下域名的结构。之前提过域名就是以句点分割的字符串,不过在 DNS 规范中,域名是必须以句点结尾的:
最后这个句点表示“根”,由根向左,每一段被句点分割的字符串依次称为顶级域名、一级域名、二级域名……
虽然所有域名都是以句点结尾的,但在用户的角度,一个始终存在的东西并没有太大的意义,于是在用户可见的地方,这个根往往会被省略掉,所以我们平时看到的域名一般是没有这个根句点的。
四种服务器类型
DNS 服务器的设计,也与域名分级相对应:
| 服务器类型 | 说明 |
|---|---|
| 根域名服务器 | 存储了顶级域名服务器的地址 |
| 顶级域名服务器 | 存储了权威域名服务器的地址 |
| 权威域名服务器 | 存储了域名的解析记录 |
| 递归解析器 | 代客户端查询,缓存解析记录 |
递归解析器
咱们自底向上说。递归解析器(Recursive Resolver),之前已经提到了,在家庭宽带中,路由器联网后会获取到由运营商提供的 DNS 服务器地址,这个 DNS 服务器就是递归解析器,比如国内常用的 114.114.114.114。
除了运营商提供的,还有一些大公司提供的知名 DNS,例如谷歌的 8.8.8.8,Cloudflare 的 1.1.1.1 等。我们可以在自己的电脑或者路由器上手动进行设置,来使用指定的 DNS 服务器。
有特殊需求的,也可以使用商业或开源软件自己搭建 DNS 服务器。比如公司内部使用的网站,基于安全等原因,没必要把解析记录提交到公网,在内网自建的 DNS 上配置解析记录,把域名关联到内网地址就可以了。这样终端设备联网时获取到自建 DNS 地址,域名解析的过程在局域网就可以完成了。
权威域名服务器
权威域名服务器(Authoritative Name Server),保存了我们最终想要查询的域名的解析记录。也就是说我们最终查询的域名对应的 IP 都来自于权威域名服务器。
这里顺便介绍下解析记录常见的几种类型:
- A,最常用的类型,域名最终指向的 IP(IPv4)。
- AAAA:与 A 相似,不同的是指向的是 IPv6 地址。
- CNAME,别名,也就是把待查询的域名映射到了另一个域名上。
- NS,用来指向其它的域名服务器,也就是告诉你要到另一台域名服务器上去查解析记录。
如果查到 A 或 AAAA 记录,那也就是查到了最终的 IP,返回到浏览器后,就可以直接访问 WEB 服务器了。如果查到了 CNAME 记录,就要接着查询返回的新域名。如果返回了 NS 记录,则需要去指定的域名服务器上继续查询。
顶级域名服务器
顶级域名服务器(Top-Level Domain Server,TLD),保存了一个或多个顶级域名下的权威域名服务器的地址。
例如 .com 顶级域名服务器共有13个地址,依字母表顺序,从 a.gtld-servers.net 到 m.gtld-servers.net。在这些服务器中,就存储着我的域名 laidbackgeek.com 的权威域名服务器的地址。
根域名服务器
根域名服务器(Root Name Server),保存了所有顶级域名服务器(如 .com、.org、.cn 等)的地址。与顶级域服务器类似,根域名服务器的地址也有13个,依字母表顺序,从 a.root-servers.net 到 m.root-servers.net。
递归查询
知道了四个 DNS 服务器的类型,我们再从查询的角度再自顶向下,看看递归解析器是如何一步一步查到最终的 IP 地址的。我们先假定当前请求中,涉及的所有环节都还没有缓存,来看看一次查询都需要经过哪些步骤。
还以我的网站 www.laidbackgeek.com 为例,由递归解析器来发起查询请求,
- 首先是查询根域名服务器,根域名服务器会返回 .com 的 NS 记录,也就是 .com 顶级域名服务器的地址
- 然后按照一定的策略从中挑选一个地址继续发起查询请求,也就是查询 .com 顶级域名服务器,顶级域名服务器会返回 laidbackgeek.com 的 NS 记录,也就是权威域名服务器的地址
- 然后按照一定的策略从中挑选一个地址继续发起查询请求,也就是查询 laidbackgeek.com 权威域名服务器,权威域名服务器会返回 www.laidbackgeek.com 的 A 记录,也就是部署了我网站的 WEB 服务器地址
查询成功后,每个环节都会缓存查询结果,以便后续查询复用。
这就是递归解析器的查询过程,先检查本地缓存,如果没有就自顶向下,从根域名服务器查起,根据返回的地址逐级查询下一级别的域名服务器,直到最终找到对应的 IP。
两个小问题
这里面还有一些细节,你或许也应该知道。
根域名服务器地址从哪来
递归解析器首先查的是根域名服务器,那它怎么知道根域名服务器的地址呢?因为根域名服务器只有13个地址,极少变动,所以递归解析器都是内置了这13个地址,确保它一启动就能访问根域名服务器。能正常工作后,再通过更新程序定期校验和刷新。
前面提到,根域名服务器的地址是13个域名,也就是说,在访问根域名服务器之前还需要经过一次域名解析,也就是说想解析任何一个域名,都要先解析一个根域名服务器的域名,这不就形成死循环了吗?
所以递归解析器中内置的除了13个根域名服务器的域名外,也内置它们对应的 IP,这样才能确保正常发起第一次请求。因为根域名的信息是很少会变化的,所以这种提前内置的信息也并不容易过时。
多级域名如何查询
向权威域名服务器发起请求后,并不一定都能查到对应的 IP,返回的也可能只是 NS 记录,也就是另一个权威域名服务器的地址,这也就说明你要查的域名是被另一个权威域名服务器管理的,需要去另一个域名服务器查。
在同一个一级域名下,可以为多级域名配置不同的权威域名服务器,那么解析时就会出现上面说的这种情况。
实例
上面流程只写了三步,是我故意简化了,实际解析时也可能遇到比较复杂的情况,我就碰巧找到了一个特别复杂的查询过程,就是大家每年都会用的12306的域名,12306.cn,咱们实际操作一下,来看看它的域名解析过程。
我们还是假设查询前没有任何缓存。我是 Mac 系统,使用的 dig 命令进行的域名解析查询,如果你是 Windows 可以使用 nslookup。
我们先直接查询一下:
dig 12306.cn
; <<>> DiG 9.10.6 <<>> 12306.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32320
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 5, ADDITIONAL: 8
;; QUESTION SECTION:
;12306.cn. IN A
;; ANSWER SECTION:
12306.cn. 2830 IN CNAME 12306.cn.wsglb0.com.
12306.cn.wsglb0.com. 300 IN A 42.81.147.213
12306.cn.wsglb0.com. 300 IN A 103.254.191.156
12306.cn.wsglb0.com. 300 IN A 43.243.235.24
;; AUTHORITY SECTION:
wsglb0.com. 36250 IN NS dns2.wsglb0.info.
wsglb0.com. 36250 IN NS dns1.wsglb0.org.
wsglb0.com. 36250 IN NS dns4.wsglb0.info.
wsglb0.com. 36250 IN NS dns5.cdn30.org.
wsglb0.com. 36250 IN NS dns3.wsglb0.org.
;; ADDITIONAL SECTION:
dns1.wsglb0.org. 5636 IN A 27.148.151.246
dns1.wsglb0.org. 5636 IN A 117.27.241.168
dns5.cdn30.org. 2807 IN A 27.155.71.57
dns2.wsglb0.info. 2077 IN A 117.27.241.168
dns3.wsglb0.org. 2998 IN A 123.103.125.112
dns3.wsglb0.org. 2998 IN A 183.134.12.233
dns4.wsglb0.info. 2082 IN A 125.77.129.21
dns5.cdn30.org. 2807 IN AAAA 2408:8719:5300::193
;; Query time: 7 msec
;; SERVER: fe80::9e56:36ff:fedc:9e50%18#53(fe80::9e56:36ff:fedc:9e50%18)
;; WHEN: Thu Oct 30 10:22:03 CST 2025
;; MSG SIZE rcvd: 382
主要看 ANSWER SECTION 部分,12306.cn 先是有一条 CNAME 记录,然后是三条 A 记录,也就是最终绑定了三个 IP。因为 DNS 查询是递归的,所以一个命令就能查到最终结果,但为了演示查询过程,我们会指定 DNS 服务器,逐级查询。
首先,递归解析器内置了根域名服务器的域名和 IP,我们先随便挑选一个,作为首次查询的 DNS 服务器。例如挑选 a.root-servers.net 198.41.0.4。以下展示的查询结果中,我会略去不太重要的部分。
1. 去根域名服务器查
dig @198.41.0.4 12306.cn
......
;; AUTHORITY SECTION:
cn. 172800 IN NS a.dns.cn.
cn. 172800 IN NS b.dns.cn.
......
;; ADDITIONAL SECTION:
a.dns.cn. 172800 IN A 203.119.25.1
b.dns.cn. 172800 IN A 203.119.26.1
......
从根域名服务器中可以查到6条 NS 记录,也就是找到了6个 .cn 顶级域名服务器的地址,同时也会给出这这6个域名的 A 记录,这样就可以直接查询顶级域名服务器了,不然再对顶级域名服务器的域名做解析,还得先查根域名服务器,这就陷入死循环了。这与递归解析器内置了根域名服务器的 IP 的道理类似。
2. 去.cn顶级域名服务器查
dig @203.119.25.1 12306.cn
......
;; AUTHORITY SECTION:
12306.cn. 86400 IN NS cns1.zdnscloud.net.
12306.cn. 86400 IN NS dns1.zdnscloud.info.
12306.cn. 86400 IN NS ins1.zdnscloud.com.
12306.cn. 86400 IN NS vns1.zdnscloud.biz.
......
随便挑了一个顶级域名的 IP 进行查询,返回了4条 NS 记录,也就是查到了4个 12306.cn 的权威域名服务器地址。因为这四个地址的顶级域名都不是 .cn,所以 .cn 顶级域名服务器不知道它们的 IP 是什么,还需要我们继续进行域名解析查询。
我们随便挑一个 cns1.zdnscloud.net 来查询。
3. 查权威域名服务器 cns1.zdnscloud.net 的 IP
3.1 去根域名服务器查
dig @198.41.0.4 cns1.zdnscloud.net
......
;; AUTHORITY SECTION:
net. 172800 IN NS a.gtld-servers.net.
net. 172800 IN NS b.gtld-servers.net.
......
;; ADDITIONAL SECTION:
a.gtld-servers.net. 172800 IN A 192.5.6.30
b.gtld-servers.net. 172800 IN A 192.33.14.30
......
可以查到13条 NS 记录,也就是找到了13个 .net 的顶级域名服务器地址和对应的 IP。随便挑一个,继续查询。
3.2 去 .net 顶级域名服务器查
dig @192.5.6.30 cns1.zdnscloud.net
......
;; AUTHORITY SECTION:
zdnscloud.net. 172800 IN NS cns1.zdnscloud.net.
zdnscloud.net. 172800 IN NS ins1.zdnscloud.com.
zdnscloud.net. 172800 IN NS dns1.zdnscloud.info.
zdnscloud.net. 172800 IN NS vns1.zdnscloud.biz.
zdnscloud.net. 172800 IN NS fns1.zdnscloud.cn.
;; ADDITIONAL SECTION:
cns1.zdnscloud.net. 172800 IN AAAA 2408:8719:2500:0:a::1
cns1.zdnscloud.net. 172800 IN A 42.62.2.24
cns1.zdnscloud.net. 172800 IN A 42.62.2.29
......
查到了5条 NS 记录,也就是5个 zdnscloud.net 权威域名服务器地址。其中一个地址就是我们要查的 cns1.zdnscloud.net,也就是说它自己就是自己一级域名的权威域名服务器。为了避免死循环所以查询结果中也包括了它对应的 IP。
上面查根域名服务器时也有这种情况,当查到的权威域名服务器位于待查域名之下(比如 zdnscloud.net 的权威域名服务器是 cns1.zdnscloud.net,而它又是 zdnscloud.net 的子域名)时,解析器若不知道权威域名服务器的 IP,就必须先解析它的域名。
可解析它又需要找到 zdnscloud.net 的权威域名查询,就形成了死循环。这种情况下,域名服务器就会通过粘合记录(glue records)的方式,在 ADDITIONAL SECTION 中返回此域名的 A 记录,来避免循环。
4. 去 12306.cn 权威域名服务器查
在 3.2 中已经查到了 12306.cn 权威域名服务器 cns1.zdnscloud.net 的 IP 是 42.62.2.24,继续查询。
dig @42.62.2.24 12306.cn
......
;; ANSWER SECTION:
12306.cn. 3600 IN CNAME 12306.cn.wsglb0.com.
......
查到了一条 CNAME 记录,也就是想知道最终的 IP,就需要继续查 12306.cn.wsglb0.com。这是给网站配置 CDN 常用的一种方法,域名 wsglb0.com 是网宿公司的域名,也就是说 12306 网站使用的是网宿的 CDN 服务。
5. 查 12306.cn.wsglb0.com 的 IP
这个域名的顶级域名是 .com 前面的查询中没有涉及到,所以没有缓存,还要从根域名服务器查起。
5.1 去根域名服务器查
dig @198.41.0.4 12306.cn.wsglb0.com
......
;; AUTHORITY SECTION:
com. 172800 IN NS a.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
......
;; ADDITIONAL SECTION:
a.gtld-servers.net. 172800 IN A 192.5.6.30
b.gtld-servers.net. 172800 IN A 192.33.14.30
......
可以查到13条 NS 记录,也就是找到了13个 .com 顶级域名服务器的地址和对应的 IP。随便挑一个,继续查询。
5.2 去 .com 顶级域名服务器查
dig @192.5.6.30 12306.cn.wsglb0.com
......
;; AUTHORITY SECTION:
wsglb0.com. 172800 IN NS dns5.cdn30.org.
wsglb0.com. 172800 IN NS dns1.wsglb0.org.
wsglb0.com. 172800 IN NS dns3.wsglb0.org.
wsglb0.com. 172800 IN NS dns2.wsglb0.info.
wsglb0.com. 172800 IN NS dns4.wsglb0.info.
......
查到了5条 NS 记录,也就是5个 wsglb0.com 权威域名服务器的地址,因为这5个地址的顶级域名都不是 .com,所以这台 .com 顶级域名服务器并不知道它们对应的 IP,还需要继续查询。我们随便挑一个 dns5.cdn30.org 来查。
5.3 查 dns5.cdn30.org 的 IP
5.3.1 去根域名服务器查
dig @198.41.0.4 dns5.cdn30.org
......
;; AUTHORITY SECTION:
org. 172800 IN NS a0.org.afilias-nst.info.
org. 172800 IN NS a2.org.afilias-nst.info.
;; ADDITIONAL SECTION:
a0.org.afilias-nst.info. 172800 IN A 199.19.56.1
a2.org.afilias-nst.info. 172800 IN A 199.249.112.1
......
可以查到6条 NS 记录,也就是找到了6个 .org 顶级域名服务器的地址和对应的 IP。随便挑一个,继续查询。
5.3.2 去 .org 顶级域名服务器查
dig @199.19.56.1 dns5.cdn30.org
......
;; AUTHORITY SECTION:
cdn30.org. 3600 IN NS ns3.cdn30.org.
cdn30.org. 3600 IN NS ns4.cdn30.org.
......
;; ADDITIONAL SECTION:
ns1.cdn30.org. 3600 IN A 125.77.129.21
ns2.cdn30.org. 3600 IN A 163.171.208.43
......
可以查到5条 NS 记录,也就是找到了5个 cdn30.org 权威域名服务器的地址,因为同是 .org 顶级域名下的,所以也就同时查到了其对应的 IP。
5.3.3 去 cdn30.org 权威域名服务器查
dig @125.77.129.21 dns5.cdn30.org
......
;; ANSWER SECTION:
dns5.cdn30.org. 3600 IN A 27.155.71.57
......
查到了一条 A 记录,也就是 wsglb0.com 的权威域名服务器 dns5.cdn30.org 对应的 IP。
5.4 去 wsglb0.com 权威域名服务器查
dig @27.155.71.57 12306.cn.wsglb0.com
......
;; ANSWER SECTION:
12306.cn.wsglb0.com. 60 IN A 42.81.147.213
12306.cn.wsglb0.com. 60 IN A 103.254.191.156
12306.cn.wsglb0.com. 60 IN A 43.243.235.24
......
查到了3条 A 记录,也就是 12306.cn.wsglb0.com 绑定的三个 IP,也就是请求 12306.cn 最终解析到的三个 IP。
对比下一开始直接执行 dig 12306.cn的结果,三个 A 记录是一样的,就是域名 12306.cn 解析后最终的结果。
6. 总结
如果你还没绕过来,也许这张图能帮你理解一下。

所以在我这解析一个 12306.cn,一共发起了11次查询请求。不过这是在全无缓存的前提下,第一次查询才会如此复杂。
而在实际使用中,当你想要访问 12306.cn 时,大概率递归解析器中就已经有缓存了,一次查询都不需要,直接就可以返回 IP 了。就算 12306.cn 的缓存过期了,那中间过程中的顶级域名服务器、权威域名服务器的缓存大概率也是有的,查询过程也会大大简化。
所以分层与缓存两种架构风格在 DNS 系统中起到了重要作用。原本计划写的 DNS 的五种架构风格,因为这篇内容已经比较多了,就放到下周再写吧。
智能解析
如果你感兴趣,也可以找一个域名,按照我上面的方式,使用 dig 或者 nslookup 命令来看看域名解析的查询过程。不过就算你也解析 12306.cn,得到的结果可能也跟我不同。这是因为配置域名解析时,可以按照不同的地域和运营商来配置不同的 IP。
这个能力按照不同的实现方式叫法有所不同,国内很多云厂商会叫“智能解析”,也有叫全局服务器负载均衡(GSLB)的。不过最终的目的都是希望,不同地方的人,访问同一个域名时,都可以解析到更快更好的节点。
比如,我在天津,我上面解析到的三个 IP,一个在上海,两个在北京。我找杭州的同学,解析出来的两个 IP 都在温州。我找武汉的同学,同样是 CNAME 到网宿的域名,但是网宿的域名又 CNAME 到了另一个家公司的域名,最终解析出了一个 IP,是在郑州。
智能解析当然不止这一种用法,例如还可以用来做 CDN 供应商的备份。举个例子,我要为自己网站配置 CDN 服务,技术层面的操作就是类似 12306.cn 那样,将自己的域名 CNAME 到 CDN 厂商提供的域名上。
但是,如果 CDN 厂商的服务出现故障,那我的网站就不可用了。如果我想提高我网站的可用性,那我可以对接两个 CDN 厂商,一个出现故障就换成另一个,就是改个 CNAME 的事。或者电信用一个,非电信的用一个,这样一家厂商出故障,只会影响一部分用户。
不过,如果两家 CDN 厂商的价格不同,那我还是更希望用便宜的那家,它故障了再换成贵的那家。可如果总不用贵的那家,万一他家的链路出现了问题我也发现不了,等用的时候才发现那就更麻烦了。
于是,我可以找一个城市,或者一个城市的一个运营商,配置成贵的那家,其他地方都用便宜的那家。这样贵的那家万一有问题了,可以及时发现,总成本也能保持一个低水平。这就是智能解析带来的能力。
写在最后
DNS 对普通用户完全透明,所以大部分人都不太了解。就算是我们搞开发的,如果平时不做运维工作,大部分人也是只了解个大概,就像当年刚刚接触 CDN 的我。
但如果你是在做一个面向全国甚至全球的高可用性云服务,那么理解 DNS,理解 CDN 都会对你的工作有很大帮助。
我本是打算写科普的,但是具体介绍 DNS 的话又免不了涉及一些专业知识。所以在易懂与专业间如何平衡,我似乎做得还不是很好,大不了以后再重写吧。
今天这篇写得比预想的多了,关于之前说的架构风格的就放到下周再写吧。