前述
根据国际惯例,在编写 Linux 基础教程或书籍时,DNS 章节通常会选择介绍 Bind。然而,为了使《Rocky Linux 9 从入门到精通》系列教程更贴近实际工作需求,木子将对某些章节进行适当调整,以参考当前主流技术进行讲解。对于前期的一些基础理论,在本章节中会用到的,我们仍会进行简要介绍,但不会过于详细,因为每个章节的基础理论内容都足以单独成书。此章节大概完成了 80%,所以会逐步发布更新。因为微信公众号的发布不可修改,所以对于可能存在的错误,我们会在 RockyLinux 中文社区官方第一时间修正。
为什么需要 DNS?
当前网络通信大部分采用的是 TCP/IP 协议,而该协议的基础是 IP 地址。因此,计算机在网络中进行通信时只能识别由纯数字构成的 IP 地址,包括:IPv4 和 IPv6,例如:202.98.12.12
或 2001:4860:4801:53::48
。试想一下,如果让您通过 https://2001:4860:4801:53::48
访问网站会有多困难。首先,输入这样的 IP 地址非常麻烦,其次,记住这一串数字也很不容易。然而,如果使用 https://www.rockylinux.cn 这样的域名访问,是不是简单很多?这样您可以记住的域名也会更多。
这正是 DNS 存在的最基本意义,将域名转换成 IP 地址。我们可以将 DNS 服务器比作一个电话簿,里面存有对应的域名和 IP 地址。当我们访问某个域名时,DNS 服务器会查询对应的 IP 地址并返回给用户,然后用户根据获取到的 IP 地址访问对应的服务器。当然,DNS 还有很多其他用途,例如:通过 DNS 轮询实现服务高可用性等。
DNS 服务器类型
DNS(Domain Name System,域名系统)是互联网的重要组成部分,是用于实现域名和 IP 地址相互映射的一个分布式数据库,它将人类易读的域名(如: www.rockylinux.cn )翻译成计算机能够识别的 IP 地址(如:192.168.1.1),使用户可以更快速便捷地访问互联。互联网连通的是全球资源,单一的域名服务器不足以支撑全部的地址转换操作,因此全球有多套域名服务器相互配合使用。早在 1983 年互联网就开始采用层次树状结构的命名方法,并使用分布式的域名系统进行解析操作。这样既提升了域名解析的效率,同时也保障了域名解析的稳定性,如果系统中单个域名服务器出现故障,不会对整个 DNS 系统的正常运行造成太大影响。
在这个过程中,不同类型的 DNS 服务器各司其职,确保查询过程顺利进行。以下是 DNS 服务器的四种主要类型:
-
根域名服务器(Root Name Server):
- 根域名服务器是 DNS 层次结构的最顶层。全球共有 13 组根服务器,由多个组织分布在不同地点进行管理。它们保存着顶级域(TLD)服务器的列表。
- 当递归域名服务器无法直接回答查询请求时,它会首先向根域名服务器请求顶级域的信息。
-
顶级域名服务器(TLD Server):
- 顶级域名服务器管理特定顶级域(如:
.com
、.org
、.net
等)。这些服务器保存着次级域名(如:rockylinux.cn
)的权威域名服务器的列表。 - 当递归域名服务器从根域名服务器获取到 TLD 服务器的信息后,会向 TLD 服务器请求次级域名的信息。
- 顶级域名服务器管理特定顶级域(如:
-
权威域名服务器(Authoritative Name Server):
- 权威域名服务器保存着特定域名及其对应的 IP 地址信息(如:
192.168.1.1 rockylinux.cn
),是最终提供域名解析结果的服务器。 - 当递归域名服务器向权威域名服务器请求特定域名的信息时,权威域名服务器会返回相应的 IP 地址。
- 权威域名服务器保存着特定域名及其对应的 IP 地址信息(如:
-
递归域名服务器(Recursive Resolver):
- 递归域名服务器负责接受客户端的 DNS 查询请求,并按照层次结构逐步查询根域名服务器、TLD 服务器和权威域名服务器,直到获取最终的 IP 地址。
- 它们通常由 ISP(互联网服务提供商)或公共 DNS 服务(如:Google DNS、Cloudflare DNS 等)运行,当然也可以自建(如:Bind、SmartDNS、CoreDNS 等)。
除了上述四种主要类型的 DNS 服务器,还有其它类型的 DNS 服务器和相关技术,例如:
-
缓存 DNS 服务器(Caching DNS Server):
- 递归域名服务器在查询过程中会缓存查询结果,以便在未来的查询中更快速地提供响应。这种缓存机制也可以单独实现,通过专门的缓存 DNS 服务器来减少查询延迟。
-
转发 DNS 服务器(Forwarding DNS Server):
- 转发 DNS 服务器并不直接进行递归查询,而是将查询请求转发给其它递归 DNS 服务器处理。这种配置可以用于优化网络流量或集中管理 DNS 查询。
-
动态 DNS 服务器(Dynamic DNS Server):
- 动态 DNS 服务器允许用户将动态变化的 IP 地址与固定的域名关联起来,常用于家庭网络或小型企业网络中。
这些服务机制共同协作,确保 DNS 查询过程高效、可靠地进行。
全球 DNS 根服务器
全球域名的最高管理机构是 ICANN(Internet Corporation for Assigned Names and Numbers),即互联网名称与数字地址分配机构。ICANN 是一个总部位于美国加利福尼亚州的非营利组织,负责管理全球域名系统的运行。它的主要职责是规划和管理顶级域名(Top-Level Domain,缩写为 TLD)。ICANN 不会直接管理所有顶级域名,因为数量庞大且复杂。目前,全球顶级域名已超过 1000
个,每个顶级域名下还有许多服务提供商和零售注册商。为了简化管理,ICANN 将每个顶级域名的具体管理任务委托给专门的注册局(Registry),这些注册局负责各自顶级域名的所有事务。例如:.cn
域名由中国互联网络信息中心(CNNIC)负责管理,CNNIC 制定 .cn
域名的相关政策。而 .com
域名则由 VeriSign 威瑞信 公司管理。通过这种方式,ICANN 只需与各个注册局合作,有效地管理全球域名系统。
IANA(Internet Assigned Numbers Authority) ,即互联网数字分配机构。本质 IANA 是 ICANN 的一个部门,它负责实施和管理 ICANN 的一些技术职能,包括:IP 地址、系统端口号、以及顶级域名(TLD)和国家顶级域名(ccTLD)的管理。IANA 负责全球 IP 地址和 AS(自治系统)号的分配,以及 DNS 根区的管理。在域名系统中,IANA 维护了一个中央的数据库,记录了所有的顶级域名和其对应的权威 DNS 服务器。每次新的顶级域名被创建或者顶级域名的权威服务器发生变化时,IANA 都会更新这个数据库。
在全球只有 13
组 DNS 根服务器,其中 10
组在美国,欧洲 2
组位于英国和瑞典,亚洲 1
组位于日本。详见下表:
13
台,而是由 13
个公网 IPv4 和公网 IPv6 组成的 DNS 根服务器集群,每组集群由全球分布的多个物理服务器组成,通过任播(Anycast)技术提供服务。截止2024年07月16日全球总共有 1845
个节点组成 DNS 根服务器。另外中国并不是没有根服务器,通过任播技术,目前在我国北京、上海、杭州、武汉、长沙、贵州、广州、香港、台北、高雄等地分布着多个根节点集群。详见参考:https://root-servers.org主机名 | IP 地址 IPv4 / IPv6 | 组织 |
---|---|---|
a.root-servers.net | 198.41.0.4, 2001:503:ba3e::2:30 | Verisign 公司(美国,弗吉尼亚州) |
b.root-servers.net | 170.247.170.2, 2801:1b8:10::b | 南加州大学 (ISI)(美国,加利福尼亚州) |
c.root-servers.net | 192.33.4.12, 2001:500:2::c | Cogent 通讯(美国,弗吉尼亚州) |
d.root-servers.net | 199.7.91.13, 2001:500:2d::d | 马里兰大学(美国,马里兰州) |
e.root-servers.net | 192.203.230.10, 2001:500:a8::e | 美国国家航空航天局(NASA)(美国,加利弗尼亚州) |
f.root-servers.net | 192.5.5.241, 2001:500:2f::f | 互联网系统联盟(ISC)(美国,加利弗尼亚州) |
g.root-servers.net | 192.112.36.4, 2001:500:12::d0d | 美国国防部 (NIC)(美国,弗吉尼亚州) |
h.root-servers.net | 198.97.190.53, 2001:500:1::53 | 美国陆军研究实验室(美国,马里兰州) |
i.root-servers.net | 192.36.148.17, 2001:7fe::53 | Autonomica 公司(瑞典,斯德哥尔摩) |
j.root-servers.net | 192.58.128.30, 2001:503:c27::2:30 | Verisign 公司(美国,弗吉尼亚州) |
k.root-servers.net | 193.0.14.129, 2001:7fd::1 | RIPE NCC(英国,伦敦) |
l.root-servers.net | 199.7.83.42, 2001:500:9f::42 | ICANN(美国,弗吉尼亚州) |
m.root-servers.net | 202.12.27.33, 2001:dc3::35 | WIDE Project(日本,东京) |
参考链接:Root Servers,或通过 dig +bufsize=1200 +norec NS . @a.root-servers.net
可以获取所有根服务器信息。
[root@coredns-001 ~]# dig +bufsize=1200 +norec NS . @a.root-servers.net
; <<>> DiG 9.16.23-RH \<<>> +bufsize +norec NS . @a.root-servers.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER <<- \opcode: QUERY, status: NOERROR, id: 6268
;; flags: qr aa; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1472
;; QUESTION SECTION:
;. IN NS
# 所有根服务器信息
;; ANSWER SECTION:
. 518400 IN NS a.root-servers.net.
. 518400 IN NS b.root-servers.net.
. 518400 IN NS c.root-servers.net.
. 518400 IN NS d.root-servers.net.
. 518400 IN NS e.root-servers.net.
. 518400 IN NS f.root-servers.net.
. 518400 IN NS g.root-servers.net.
. 518400 IN NS h.root-servers.net.
. 518400 IN NS i.root-servers.net.
. 518400 IN NS j.root-servers.net.
. 518400 IN NS k.root-servers.net.
. 518400 IN NS l.root-servers.net.
. 518400 IN NS m.root-servers.net.
# 对应根服务器 A 与 AAAA 记录信息
;; ADDITIONAL SECTION:
a.root-servers.net. 518400 IN A 198.41.0.4
b.root-servers.net. 518400 IN A 170.247.170.2
c.root-servers.net. 518400 IN A 192.33.4.12
d.root-servers.net. 518400 IN A 199.7.91.13
e.root-servers.net. 518400 IN A 192.203.230.10
f.root-servers.net. 518400 IN A 192.5.5.241
g.root-servers.net. 518400 IN A 192.112.36.4
h.root-servers.net. 518400 IN A 198.97.190.53
i.root-servers.net. 518400 IN A 192.36.148.17
j.root-servers.net. 518400 IN A 192.58.128.30
k.root-servers.net. 518400 IN A 193.0.14.129
l.root-servers.net. 518400 IN A 199.7.83.42
m.root-servers.net. 518400 IN A 202.12.27.33
a.root-servers.net. 518400 IN AAAA 2001:503:ba3e::2:30
b.root-servers.net. 518400 IN AAAA 2801:1b8:10::b
c.root-servers.net. 518400 IN AAAA 2001:500:2::c
d.root-servers.net. 518400 IN AAAA 2001:500:2d::d
e.root-servers.net. 518400 IN AAAA 2001:500:a8::e
f.root-servers.net. 518400 IN AAAA 2001:500:2f::f
g.root-servers.net. 518400 IN AAAA 2001:500:12::d0d
h.root-servers.net. 518400 IN AAAA 2001:500:1::53
i.root-servers.Net. 518400 IN AAAA 2001:7fe::53
j.root-servers.Net. 518400 IN AAAA 2001:503:c27::2:30
k.root-servers.net. 518400 IN AAAA 2001:7fd::1
l.root-servers.net. 518400 IN AAAA 2001:500:9f::42
m.root-servers.net. 518400 IN AAAA 2001:dc3::35
;; Query time: 4 msec
;; SERVER: 198.41.0.4#53(198.41.0.4)
;; WHEN: Tue Jul 02 11:47:59 CST 2024
;; MSG SIZE rcvd: 811
# 单独查询某个根服务器对应 IP 信息
[root@coredns-001 ~]# dig +short a.root-servers.net.
198.41.0.4
[root@coredns-001 ~]# dig +short b.root-servers.net.
170.247.170.2
[root@coredns-001 ~]# dig +short AAAA a.root-servers.net.
2001:503:ba3e::2:30
[root@coredns-001 ~]# dig +short AAAA b.root-servers.net.
2801:1b8:10::b
一般来说根服务器很少发生变更,但也有例外,在 2023 年 05 月16 日 USC/ISI 发布公告,变更 b.root-servers.net
IPv4 地址为:170.247.170.2
, IPv6 地址将为:2801:1b8:10::b
。详见:New addresses for b.root-servers.net,变更公告:LACNIC asigna recursos de numeración al servidor raíz de USC/ISI。
为什么只有 13 组 DNS 根服务器?
为什么只有 13 组 DNS 根服务器集群?是否可以有更多的 DNS 根服务器集群?
要回答这个问题,首先需要对 DNS 报文进行详细分析。如果您对此部分不感兴趣,可以直接跳到【结论】部分。
Priming Queries
DNS 查询都从根服务器开始,那么客户端如何知道当前的根服务器列表呢?原则上,客户端的代码中会硬编码这些信息。然而,实际上根服务器并非永久不变(前面提到 b.root-servers.net
就变更过 IP),新加入的服务器如何被识别呢?这就涉及到了“Priming Queries”。简单来讲,每个 DNS 解析客户端都会附带一个包含所有当前根服务器信息(包括域名、IP 地址等)的列表文件,称为 Root Hints,可以从 IANA 官网下载。但鉴于根服务器列表可能发生变化,客户端需定期从已知的根服务器查询最新的服务器列表,这种请求被称为 Priming Queries。
客户端首先从 Root Hints 中选出一台根服务器,然后查询最新的根服务器列表,并在本机进行一段时间的缓存,直至缓存过期。Priming Queries 使用的是 DNS 协议,通过 UDP 传输。由于互联网早期 IP 网络的最大传输单元长度(MTU)只有五百多字节,因此 DNS 回复信息的最大长度也不能过长,即不得超过 512
字节。这就构成了添加根服务器的技术难题。理论上,可以要求客户端使用 TCP 连接传输 Priming 查询结果。但由于所有 DNS 查询都采用 UDP 协议,简单且统一。虽然 DNS 也支持使用 TCP,但如果让 Priming Queries 单独使用 TCP,将会使系统变得复杂。因此,社区最终决定采取域名压缩查询的方法,来解决 DNS 报文可能超过 512
字节的问题。
512 字节
前面提到 DNS 报文不能够超过 512
字节,下面我们来简单了解一下它的来龙去脉。
DNS 协议最初的定义可以追溯到 20 世纪 80 年代末,它使用了两种通讯协议:UDP
和 TCP
。通常情况下,UDP 用于查询和响应,而 TCP 用于主 DNS 服务器与辅助 DNS 服务器之间的区域传送。然而,UDP 有一个限制,它只能处理最大 512
字节的数据包。这个限制对于需要在每个包中包含数字签名的一些新的 DNS 特性(如 DNSSEC)来说,显得有些小。这个 512
字节的限制也影响了 DNS 根服务器的数量和名称。为了使所有的根服务器数据能够在一个 512
字节的 UDP 包中进行传输,根服务器的数量只能限制在 13
个,并且每个服务器都被单个字母命名。
在以太网中,数据的长度必须在 46-1500
字节之间,这是由以太网的物理特性决定的。实际上,这个 1500
字节就是网络层 IP 数据包的长度限制。理论上,IP 数据包的最大长度可以达到 65535
(2^16 – 1) 字节。但是,除去 20
字节的 IP 首部和 8
个字节的 UDP 首部,UDP 数据包中的数据最大长度为 65507
字节。在互联网数据传输中,UDP 数据的长度通常控制在 576
字节(互联网标准 MTU 值)。而在很多 UDP 应用程序设计中,数据包的大小被限制为 512
字节或更小,以防止数据包的丢失。
当解析器首次发送 UDP 查询时,如果收到的响应被截断,它会使用 TCP 重新发送该查询。虽然这个过程可以绕过 512
字节的限制,但效率并不高,TCP 连接的开销要大得多。一个 UDP 名称服务器交换只需要两个包:一个查询包和一个响应包。而一个 TCP 交换至少需要 7
个包:三次握手初始化 TCP 会话、一个查询包、一个响应包以及最后一次握手来关闭连接。
DNS 报文拆解
一个典型的DNS报文由以下几个部分组成,每个部分包含的字节数如下:
- 报文头部(Header):12 字节。
- 问题(Question):可变长度,保存查询问题。
- 回答(Answer):可变长度,保存查询结果。
- 权威(Authority):可变长度,保存权威信息。
- 附加(Additional):可变长度,保存附加信息。
报文头部(Header)
报文头部总共占用 12 字节(96 位),其具体结构如下:
- 标识(ID):2 字节(16 位),用于标识查询和响应的匹配。
- 标志字段(Flags):2 字节(16 位)
- QR:1 位,查询报文(查询请求
0
)或响应报文(查询应答1
) - Opcode:4 位,标识查询类型(标准查询
0
、反向查询1
或服务器状态请求2
) - AA:1 位,权威应答(Authoritative Answer),表示当前查询结果是由域名的权威服务器回应。
- TC:1 位,截断标志(Truncated),使用 UDP 时,如果应答超过
512
字节,只返回前512
个字节。 - RD:1 位,期望递归(Recursion Desired),在请求中设置,并在应答中返回。该位为
1
时,服务器必须处理这个请求,如果服务器没有授权回答,它必须替客户端请求其他 DNS 服务器,这也是所谓的 递归查询 。该位为0
时,如果服务器没有授权回答,它就返回一个能够处理该查询的服务器列表给客户端,由客户端自己进行 迭代查询 。 - RA:1 位,递归可用(Recursion Available),如果服务器支持递归查询,就会在应答中设置该位,以告知客户端。
- Z:3 位,保留字段,必须为
0
,目前 3 位未用,留给未来扩展使用。 - RCODE:4 位 – 返回码(Response Code),表示请求结果,常见的值包括:
0
表示没有差错,3
表示域名差错,该差错由权威服务器返回,表示查询的域名不存在。
- QR:1 位,查询报文(查询请求
- 问题数(QDCOUNT):2 字节(16 位),问题的条目数。
- 回答数(ANCOUNT):2 字节(16 位),回答的资源记录数。
- 权威记录数(NSCOUNT):2 字节(16 位),权威的资源记录数。
- 附加记录数(ARCOUNT):2 字节(16 位),附加的资源记录数。
问题(Question)
问题部分包含一个或多个查询,每个查询的结构如下:
- 查询名(QNAME):可变长度,查询的域名,以点分十进制格式表示,每个标签长度前有一个字节表示该标签的长度。
- 查询类型(QTYPE):2 字节(16 位),指定查询的类型,例如 A 记录、MX 记录等。
- 查询类(QCLASS):2 字节(16 位),指定查询的类(网络类型),通常为 IN(Internet 类)。
如下图所示,QNAME
字段的长度是可变的,用于储存查询的域名。以域名 A.ROOT-SERVERS.NET.
为例,它会被分解为三个部分:A
、ROOT-SERVERS
和 NET
。这些部分被称为标签(Label),而在 QNAME
字段中,只保存标签,不保存 .
。每个标签的第一个字节用于记录当前标签的长度,后面则跟着标签的内容,在末尾使用一个零长度的标签来表示结束,因此总长度为 20
个字节。特别需要注意的是,对于根域名 .
,其编码为 0
,但总长度为 1
个字节。
查询部分包含 a.root-servers.net
:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1| a|12| r| o| o| t| -| s| e| r| v| e| r| s| 3| n| e| t| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
具体字节占用如下:
1 a
:表示标签a
,占 2 个字节。12 root-servers
:表示标签root-servers
,占 13 个字节。3 net
:表示标签net
,占 4 个字节。0
:表示域名结束,占 1 个字节。
总共长度为 2 + 13 + 4 + 1 = 20
字节。
回答(Answer)
回答包含一个或多个资源记录(RR,全称:Resource Record),每个资源记录的结构如下:
- 名称(NAME):可变长度,资源记录的域名。
- 类型(TYPE):2 字节(16 位),资源记录的类型。
- 类(CLASS):2 字节(16 位),资源记录的类,通常为 IN(Internet 类)。
- 生存时间(TTL):4 字节(32 位),资源记录的生存时间(缓存时间)。
- 数据长度(RDLENGTH):2 字节(16 位), 资源数据的长度。
- 资源数据(RDATA):可变长度,资源记录的数据。
相比问题(Question),RR 多了 TTL
、RDLENGTH
和 RDATA
三个字段。其中,TTL
代表有效时长,RDLENGTH
代表后续 RDATA
的长度,而 RDATA
则储存实际的响应数据。根据 TYPE
和 CLASS
的不同,RDATA
的内容也会有所变化。在 Priming 查询中,RDATA
用于储存各个根服务器的域名,其编码方式与 Question 中的 QNAME
相同。
根据上面的逻辑,当 DNS 服务器返回如下一条 RR 记录:
. 518400 IN NS a.root-servers.net.
那么对应的 RR 总长度是 1(Name) + 2(Type) + 2(Class) + 4(TLL) + 2(RDLength) + 20(RDATA) = 31
字节。
权威(Authority)和附加(Additional)
权威(Authority)和附加(Additional)这两个部分的资源记录结构与回答(Question)的资源记录结构相同,均由一条或多条资源记录组成,记录数目保存在头部中的对应字段,这里不再赘述。
结论
上述一系列的 DNS 报文拆解,最终 Priming 查询响应的返回值有多大呢?我们可以进行以下计算:
- Header 固定为
12
字节。 - 第一个域名 NS 记录占用
31
字节。 - 其余 12 个压缩后的域名 NS 记录,占用
180
字节(12 * 15
字节)。15 = 1(Name) + 2(Type) + 2(Class) + 4(TLL) + 2(RDLength) + 2(指针) + 2(偏移量) - 13 个 A 记录,占用
208
字节(13 * 16
字节)。16 = 2(指针) + 2(Type) + 2(Class) + 4(TLL) + 2(RDLength) + 4(RDATA),RDATA 即返回的 IPv4 地址。 - Question 中的 QTYPE 和 QCLASS 字段占用
4
字节。 - Question 中的 QNAME 字段占用
1
字节。
这样总共占用的字节为 436
字节(12+31+180+208+4+1
)。由于 DNS 消息的大小限制为 512
字节,因此还剩下 76
字节(512-436
)的可用空间。一组新的根服务器需要额外占用 31
字节(15+16
)。理论上,还可以添加两台根服务器,也就是最多 15
台。然而,早期的根服务器还充当 .com
、.net
、 .org
区域权威服务器功能。客户端可以向根服务器发起针对特定 .com
域名的 Priming 查询。由于响应结果需要包含查询域名 QNAME
,所以在上述的 76
字节中,至少需要保留 64
字节用于 QNAME
。这样就只剩 12
字节(512-436-64=500),因此不能再添加新的根服务器。如果您有任何疑问,可以参考官方文档说明: RSSAC FAQ
域名压缩
域名压缩本质就是为了解决超 512
字节的问题,举一个简单例子:
查询域名 a.root-servers.net.
和 b.root-servers.net.
的 A
记录,没有进行域名压缩之前,需要将这两个字符串完整传给 DNS 服务器进行解析,但使用域名压缩后,只需要传 a.root-servers.net.
和 b
就可以了,这就是域名压缩带来的好处。
而在域名压缩中有一个关键点,就是偏移量问题,那么这个偏移量怎么计算了?在计算偏移量之前,首先需要了解 ASCII 码,然后在后面的案例中才能够明白其中的意思。在 DNS 中,域名中的字母是不区分大小写的,并且存储时也是采用小写字母,这就意味着在解析过程中,a
和 A
被视为相同。以下是域名常用字符集:
- 小写字母
a-z
- 数字
0-9
- 连字符
-
对应 ASCII 码如下。
小写字母 a-z
字符 | ASCII 码 | 十六进制 |
---|---|---|
a | 97 | 0x61 |
b | 98 | 0x62 |
c | 99 | 0x63 |
d | 100 | 0x64 |
e | 101 | 0x65 |
f | 102 | 0x66 |
g | 103 | 0x67 |
h | 104 | 0x68 |
i | 105 | 0x69 |
j | 106 | 0x6A |
k | 107 | 0x6B |
l | 108 | 0x6C |
m | 109 | 0x6D |
n | 110 | 0x6E |
o | 111 | 0x6F |
p | 112 | 0x70 |
q | 113 | 0x71 |
r | 114 | 0x72 |
s | 115 | 0x73 |
t | 116 | 0x74 |
u | 117 | 0x75 |
v | 118 | 0x76 |
w | 119 | 0x77 |
x | 120 | 0x78 |
y | 121 | 0x79 |
z | 122 | 0x7A |
数字 0-9
字符 | ASCII 码 | 十六进制 |
---|---|---|
0 | 48 | 0x30 |
1 | 49 | 0x31 |
2 | 50 | 0x32 |
3 | 51 | 0x33 |
4 | 52 | 0x34 |
5 | 53 | 0x35 |
6 | 54 | 0x36 |
7 | 55 | 0x37 |
8 | 56 | 0x38 |
9 | 57 | 0x39 |
连字符 –
字符 | ASCII 码 | 十六进制 |
---|---|---|
– | 45 | 0x2D |
域名压缩规则
- 在 DNS 报文中,域名可以通过指针进行压缩,指针的格式是两个字节。 DNS 规定域名的长度不能超过
63
字节。NAME
字段中的第一个字节表示长度,最大值为63
(32+16+8+4+2+1=63) ,二进制表示为00111111
,可见高两位是零。因此,约定当高两位设为11
(即c0
)时,后面的14
位表示从报文头开始的偏移量。 - 偏移量是从 DNS 报文的开始位置(即第一个字节)计算的。
案例分析
为了让大家更方便地了解域名压缩的逻辑,我们将采用抓包逐步拆解的方法进行讲解。这里以查询 a.root-servers.net
为例进行演示。
# 客户端 DNS 查询
❯ dig @192.168.1.1 a.root-servers.net.
; <<>> DiG 9.10.6 <<>> @192.168.1.1 a.root-servers.net.
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- \opcode: QUERY, status: NOERROR, id: 62875
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a.root-servers.net. IN A
;; ANSWER SECTION:
a.root-servers.net. 2640 IN A 198.41.0.4
;; Query time: 7 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Tue Jul 16 19:23:05 CST 2024
;; MSG SIZE rcvd: 81
# DNS 服务器端抓包
[root@coredns-001 ~]# tcpdump -nnvvXS -i any port 53 -vvv
tcpdump: data link type LINUX_SLL2
dropped privs to tcpdump
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
19:23:05.461306 enp6s0f0 In IP (tos 0x0, ttl 63, id 18162, offset 0, flags [none], proto UDP (17), length 75)
192.168.3.1.63893 > 192.168.1.1.53: [udp sum ok] 62875+ [1au] A? a.root-servers.net. ar: . OPT UDPsize=4096 (47)
0x0000: 4500 004b 46f2 0000 3f11 c0f2 ac10 1082 E..KF...?.......
0x0010: ac10 0b1b f995 0035 0037 dfff f59b 0120 .......5.7......
0x0020: 0001 0000 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: 0000 2910 0000 0000 0000 00 ..)........
19:23:05.461693 enp6s0f0 Out IP (tos 0x0, ttl 64, id 35132, offset 0, flags [DF], proto UDP (17), length 75)
192.168.1.1.57323 > 223.6.6.6.53: [bad udp cksum 0x9c80 -> 0x90e6!] 13797+ [1au] A? a.root-servers.net. ar: . OPT UDPsize=4096 (47)
0x0000: 4500 004b 893c 4000 4011 152e ac10 0b1b E..K.<@.@.......
0x0010: df06 0606 dfeb 0035 0037 9c80 35e5 0120 .......5.7..5...
0x0020: 0001 0000 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: 0000 2910 0000 0000 0000 00 ..)........
19:23:05.468441 enp6s0f0 In IP (tos 0x0, ttl 116, id 35132, offset 0, flags [DF], proto UDP (17), length 91)
223.6.6.6.53 > 192.168.1.1.57323: [no cksum] 13797 q: A? a.root-servers.net. 1/0/1 a.root-servers.net. [44m] A 198.41.0.4 ar: . OPT UDPsize=1408 (63)
0x0000: 4500 005b 893c 4000 7411 e11d df06 0606 E..[.<@.t.......
0x0010: ac10 0b1b 0035 dfeb 0047 0000 35e5 8180 .....5...G..5...
0x0020: 0001 0001 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: c00c 0001 0001 0000 0a50 0004 c629 0004 .........P...)..
0x0050: 0000 2905 8000 0000 0000 00 ..)........
19:23:05.468652 enp6s0f0 Out IP (tos 0x0, ttl 64, id 43342, offset 0, flags [DF], proto UDP (17), length 109)
192.168.1.1.53 > 192.168.3.1.63893: [bad udp cksum 0x7428 -> 0xfcae!] 62875 q: A? a.root-servers.net. 1/0/1 a.root-servers.net. [44m] A 198.41.0.4 ar: . OPT UDPsize=4096 (81)
0x0000: 4500 006d a94e 4000 4011 1d74 ac10 0b1b E..m.N@[email protected]....
0x0010: ac10 1082 0035 f995 0059 7428 f59b 8180 .....5...Yt(....
0x0020: 0001 0001 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: 0161 0c72 6f6f 742d 7365 7276 6572 7303 .a.root-servers.
0x0050: 6e65 7400 0001 0001 0000 0a50 0004 c629 net........P...)
0x0060: 0004 0000 2910 0000 0000 0000 00 ....)........
4 packets captured
6 packets received by filter
0 packets dropped by kernel
第一个请求包
19:23:05.461306 enp6s0f0 In IP (tos 0x0, ttl 63, id 18162, offset 0, flags [none], proto UDP (17), length 75)
192.168.3.1.63893 > 192.168.1.1.53: [udp sum ok] 62875+ [1au] A? a.root-servers.net. ar: . OPT UDPsize=4096 (47)
0x0000: 4500 004b 46f2 0000 3f11 c0f2 ac10 1082 E..KF...?.......
0x0010: ac10 0b1b f995 0035 0037 dfff f59b 0120 .......5.7......
0x0020: 0001 0000 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: 0000 2910 0000 0000 0000 00 ..)........
第一个响应包
19:23:05.468441 enp6s0f0 In IP (tos 0x0, ttl 116, id 35132, offset 0, flags [DF], proto UDP (17), length 91)
223.6.6.6.53 > 192.168.1.1.57323: [no cksum] 13797 q: A? a.root-servers.net. 1/0/1 a.root-servers.net. [44m] A 198.41.0.4 ar: . OPT UDPsize=1408 (63)
0x0000: 4500 005b 893c 4000 7411 e11d df06 0606 E..[.<@.t.......
0x0010: ac10 0b1b 0035 dfeb 0047 0000 35e5 8180 .....5...G..5...
0x0020: 0001 0001 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: c00c 0001 0001 0000 0a50 0004 c629 0004 .........P...)..
0x0050: 0000 2905 8000 0000 0000 00 ..)........
请求包分析
在第一个请求包中,我们看到查询的是 a.root-servers.net
,并且未使用域名压缩。这部分数据从 0x0020
到 0x0040
解析如下:
0x0020: 0001 0000 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
0x0040: 0000 2910 0000 0000 0000 00 ..)........
以下的拆包基于上面的 ASCII 码进行分析,并且每两个字符对一个 ASCII 码。
0161
:01
表示标签长度为1
,61
表示内容为a
。0c72 6f6f 742d 7365 7276 6572 73
:0c
表示标签长度为12
,内容为root-servers
。03 6e65 74
:03
表示标签长度为3
,内容为net
。00
: 结束符,表示域名结束。
响应包分析
在第一个响应包中,我们可以看到从 0x0040
开始有 c00c
。这表示使用了域名压缩。
0x0040: c00c 0001 0001 0000 0a50 0004 c629 0004 .........P...)..
c0
: 前两位11
表示这是一个指针。0c
: 偏移量 12(十进制的 12)。
偏移量 12 对应的查询部分
在请求包中,从第 12 个字节开始的部分是:
0x0020: 0001 0000 0000 0001 0161 0c72 6f6f 742d .........a.root-
0x0030: 7365 7276 6572 7303 6e65 7400 0001 0001 servers.net.....
从第 12 字节开始的内容是:
0x002c: 0161 0c72 6f6f 742d 7365 7276 6572 7303 .a.root-servers
0x0030: 6e65 7400 .net.
这段内容解析为:
0161
: 标签长度为1
,内容为a
。0c72 6f6f 742d 7365 7276 6572 73
: 标签长度为12
,内容为root-servers
。03 6e65 74
: 标签长度为3
,内容为net
。00
: 结束符,表示域名结束。
响应包的域名压缩解析
在响应包中,c00c
指向了请求包中的域名部分,具体解析如下:
0x0040: c00c 0001 0001 0000 0a50 0004 c629 0004 .........P...)..
c00c
: 指向偏移量12,即a.root-servers.net
部分。0001
: 类型 A 记录。0001
: 类 IN(Internet)。0000 0a50
: TTL 为 2640 秒。0004
: 数据长度为 4 个字节。c629 0004
: 对应的 IPv4 地址为198.41.0.4
。
从这里可能看到 QNAME 未压缩使用了 20
个字节,而 RNAME 压缩后使用了 2
个字节,在响应包中减少了 18
个字节。通过使用 DNS 域名压缩技术,在处理包含重复域名的 DNS 响应时尤其有效,可以显著减少报文的大小,提高网络传输效率。
域名组成结构
说到 DNS,就不得不说域名,域名通常由多个部分组成,这些部分从右到左依次是:
-
根域名(Root Domain):
- 域名系统的顶层,通常表示为一个点(
.
)。在实际使用中,根域名通常是隐式的,并不直接出现在域名中。
- 域名系统的顶层,通常表示为一个点(
-
顶级域名(Top-Level Domain, TLD):
- 域名的最高级别部分,位于根域名的左边。它分成两种:通用顶级域名(gTLD) 和 国别顶级域名(ccTLD),常见的通用顶级域名包括:
.com
、.org
、.net
等,国别顶级域名包括:.cn
(中国)、.uk
(英国)等。顶级域名由国际域名管理机构 ICANN 控制(我们每注册一个域名需要向 ICANN 支付一笔费用的,虽然很少。),委托商业公司管理 gTLD,委托各国管理自己的国别域名。全球顶级域名信息参考:Root Zone Database - 示例:在
rockylinux.cn
中,.cn
是国别顶级域名。
- 域名的最高级别部分,位于根域名的左边。它分成两种:通用顶级域名(gTLD) 和 国别顶级域名(ccTLD),常见的通用顶级域名包括:
-
次级域名(Second-Level Domain, SLD):
- 位于顶级域名左边的部分,通常是域名的核心部分。次级域名加上顶级域名通常被称为“一级域名”。
- 示例:在
rockylinux.cn
中,rockylinux
是次级域名。
-
主机名(Hostname)或子域名(Subdomain):
- 位于次级域名左边的部分,用于标识特定的主机或服务。可以有多个级别的子域名。
- 示例:在
www.rockylinux.cn
中,www
是主机名(或称子域名)。
域名组成结构,可以参考下图:
这里以 web.blog.rockylinux.cn
为例,解析其组成部分:
- 根域名(Root Domain):
.
(通常隐式存在) - 顶级域名(TLD):
cn
- 次级域名(SLD):
rockylinux
- 子域名(Subdomain):
blog
- 主机名(Hostname):
web
在这种结构中:
rockylinux.cn
是一级域名。blog.rockylinux.cn
是二级域名。web.blog.rockylinux.cn
是三级域名。
总结:
- 一级域名:由次级域名和顶级域名组成。例如:
rockylinux.cn
是一级域名。 - 二级域名:在一级域名的基础上,加上一个子域名。例如:
blog.rockylinux.cn
是二级域名。 - 三级域名:在二级域名的基础上,再加上一个子域名。例如:
web.blog.rockylinux.cn
是三级域名。
域名系统通过这种多级分层,实现了对互联网资源的有序、结构化的组织和管理。
DNS 正向解析&反向解析
在 DNS 服务中,有两个重要的概念:正向解析、反向解析。
正向解析(Forward Resolution)
正向解析:是将域名转换为 IP 地址的过程。
作用:当用户在浏览器中输入一个域名(如: www.rockylinux.cn )时,DNS 服务器会将该域名解析为对应的 IP 地址,以便用户的计算机可以与该域名对应的服务器通信。
常见记录类型:
- A 记录:将域名解析为 IPv4 地址。
rockylinux.cn. 3600 IN A 192.168.1.1
- AAAA 记录:将域名解析为 IPv6 地址。
rockylinux.cn. 3600 IN AAAA 2001:0db8:85a3:0000:0000:8a2e:0370:7334
反向解析(Reverse Resolution)
反向解析:是将 IP 地址转换为域名的过程。
作用:反向解析通常用于网络调试、日志分析和邮件服务器的反垃圾邮件机制。它有助于确定某个 IP 地址对应的主机名。
常见记录类型:
- PTR 记录(Pointer Record):用于反向解析,将 IP 地址映射到域名。例如:IP 地址
192.168.1.1
的反向解析记录是1.1.168.192.in-addr.arpa
。1.1.168.192.in-addr.arpa. 3600 IN PTR rockylinux.cn.
DNS 记录类型
DNS 解析有多种记录类型,每种类型都有其特定的用途。以下是 DNS 解析中所有常见的记录类型及其作用:
- A(Address)记录:
- 作用:将域名映射到一个 IPv4 地址。
- 示例:
rockylinux.cn. IN A 192.168.1.1
- AAAA(IPv6 Address)记录:
- 作用:将域名映射到一个 IPv6 地址。
- 示例:
rockylinux.cn. IN AAAA 2001:0db8:85a3:0000:0000:8a2e:0370:7334
- CNAME(Canonical Name)记录:
- 作用:将一个域名别名映射到另一个域名。
- 示例:
www.rockylinux.cn. IN CNAME rockylinux.cn.
- MX(Mail Exchange)记录:
- 作用:指定负责接收邮件的邮件服务器。
- 示例:
rockylinux.cn. IN MX 10 mail.rockylinux.cn.
- NS(Name Server)记录:
- 作用:指定域名的权威 DNS 服务器。
- 示例:
rockylinux.cn. IN NS ns1.rockylinux.cn.
- PTR(Pointer)记录:
- 作用:用于反向 DNS 查找,将 IP 地址映射到域名。
- 示例:
1.1.168.192.in-addr.arpa. IN PTR rockylinux.cn.
- SOA(Start of Authority)记录:
- 作用:提供关于 DNS 区域的信息,包括主 DNS 服务器、区域管理员的电子邮件、序列号及刷新间隔等。
- 示例:
rockylinux.cn. IN SOA ns1.rockylinux.cn. admin.rockylinux.cn. 2021010101 3600 1800 1209600 86400
- TXT(Text)记录:
- 作用:存储任意文本数据,常用于验证域名所有权和存储与邮件相关的 SPF 记录等。
- 示例:
rockylinux.cn. IN TXT "v=spf1 include:_spf.google.com ~all"
- SRV(Service)记录:
- 作用:定义某个服务在某个域名上的位置(主机和端口)。
- 示例:
_sip._tcp.rockylinux.cn. 86400 IN SRV 10 60 5060 sipserver.rockylinux.cn.
- CAA(Certification Authority Authorization)记录:
- 作用:指定哪些证书颁发机构(CA)被授权为该域名颁发 SSL/TLS 证书。
- 示例:
rockylinux.cn. 86400 IN CAA 0 issue "letsencrypt.org"
- NAPTR(Name Authority Pointer)记录:
- 作用:支持正则表达式的 DNS 记录,用于实现复杂的名称转换和服务寻址。
- 示例:
rockylinux.cn. IN NAPTR 100 10 "u" "E2U+sip" "!^.*$!sip:[email protected]!" .
- DNAME(Delegation Name)记录:
- 作用:将一个域名及其子域名重定向到另一个域名。
- 示例:
rockylinux.cn. IN DNAME rockylinux.org.
- HINFO(Host Information)记录:
- 作用:提供主机的硬件和操作系统类型信息。
- 示例:
rockylinux.cn. IN HINFO "Intel" "Linux"
- RP(Responsible Person)记录:
- 作用:提供域名管理员的联系信息。
- 示例:
rockylinux.cn. IN RP admin.rockylinux.cn. hostmaster.rockylinux.cn.
- SSHFP(SSH Fingerprint)记录:
- 作用:存储 SSH 公钥指纹,用于验证 SSH 连接的真实性。
- 示例:
rockylinux.cn. IN SSHFP 1 1 123456789abcdef67890123456789abcdef67890
- TLSA(Transport Layer Security Authentication)记录:
- 作用:用于存储 TLS 服务器的证书信息,用于 DANE(DNS-Based Authentication of Named Entities)协议,以增强 TLS 连接的安全性。
- 示例:
_443._tcp.rockylinux.cn. IN TLSA 3 1 1 4a5c...
- SPF(Sender Policy Framework)记录:
- 作用:用于定义哪些邮件服务器被授权代表该域名发送邮件,以防止电子邮件欺诈。虽然 SPF 记录可以作为 TXT 记录的一部分,但它也可以单独存在。
- 示例:
rockylinux.cn. IN SPF "v=spf1 ip4:192.0.2.0/24 -all"
- URI(Uniform Resource Identifier)记录:
- 作用:提供 URI 映射,用于在某些应用程序中将域名映射到 URI。
- 示例:
_http._tcp.rockylinux.cn. IN URI 10 1 "https://rockylinux.cn/resource"
- AFSDB(Andrew File System Database)记录:
- 作用:指定与域名关联的 Andrew 文件系统数据库服务器的位置。
- 示例:
rockylinux.cn. IN AFSDB 1 afsdb.rockylinux.cn.
- LOC(Location)记录:
- 作用:存储地理位置信息(经度、纬度和高度),通常用于地理服务。
- 示例:
rockylinux.cn. IN LOC 37 24 29.1 N 122 05 42.5 W 18m
- CERT(Certificate)记录:
- 作用:存储证书或公钥,用于安全通信。
- 示例:
rockylinux.cn. IN CERT PGP 0 MIIBIjANBgkqh...
- HIP (Host Identity Protocol) 记录:
- 作用:用于存储 Host Identity Tag (HIT) 和主机标识。
- 示例:
rockylinux.cn. IN HIP 1 2001:0db8::1 a3d3d7e3a1...
- APL(Address Prefix List)记录:
- 作用:存储地址前缀列表,用于指定一组网络地址。
- 示例:
rockylinux.cn. IN APL 1:192.0.2.0/24 2:2001:db8::/32
- DHCID(DHCP Identifier)记录:
- 作用:用于在 DNS 与 DHCP 之间共享动态更新信息。
- 示例:
rockylinux.cn. IN DHCID AAIBG2...
- IPSECKEY(IPsec Key)记录:
- 作用:用于存储 IPsec 公钥,以支持 IPsec 安全通信。
- 示例:
rockylinux.cn. IN IPSECKEY 10 1 2 192.168.1.1 AQPSK...
- NSEC(Next Secure)记录:
- 作用:在 DNSSEC 中使用,用于证明某个域名不存在。
- 示例:
rockylinux.cn. IN NSEC next.rockylinux.cn. A NS
- NSEC3(Next Secure v3)记录:
- 作用:改进版的 NSEC,用于提供更安全的不存在证明。
- 示例:
rockylinux.cn. IN NSEC3 1 0 1 D399EAAB A NS
- NSEC3PARAM(NSEC3 Parameters)记录:
- 作用:存储 NSEC3 记录的参数,用于 DNSSEC(DNS Security Extensions)。
- 示例:
rockylinux.cn. IN NSEC3PARAM 1 0 1 D399EAAB
- DNSKEY(DNS Key)记录:
- 作用:存储 DNSSEC 的公钥,用于验证 DNSSEC 签名。
- 示例:
rockylinux.cn. IN DNSKEY 256 3 8 AwEAAb...
- RRSIG(Resource Record Signature)记录:
- 作用:存储 DNSSEC 签名,用于验证 DNS 记录的真实性和完整性。
- 示例:
rockylinux.cn. IN RRSIG A 5 3 3600 20210101000000 20201201000000 12345 rockylinux.cn. AwEAAb...
- DS(Delegation Signer)记录:
- 作用:存储父区域中的子区域的 DNSSEC 签名信息,用于链条的信任传递。
- 示例:
rockylinux.cn. IN DS 12345 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118
- CDS(Child DS)记录:
- 作用:子区域向父区域提交的 DS 记录,用于 DNSSEC。
- 示例:
rockylinux.cn. IN CDS 12345 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118
- CDNSKEY(Child DNS Key)记录:
- 作用:子区域向父区域提交的 DNSKEY 记录,用于 DNSSEC。
- 示例:
rockylinux.cn. IN CDNSKEY 256 3 8 AwEAA...
- TA(Trust Anchor)记录:
- 作用:用于指定 DNSSEC 的信任锚点。
- 示例:
rockylinux.cn. IN TA 256 3 8 AwEAA...
- DLV(DNSSEC Lookaside Validation)记录:
- 作用:用于 DNSSEC 的旁路验证,但已逐渐被淘汰。
- 示例:
rockylinux.cn. IN DLV 12345 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118
- EUI48(Extended Unique Identifier 48)记录:
- 作用:存储 48 位扩展唯一标识符(通常为 MAC 地址)。
- 示例:
rockylinux.cn. IN EUI48 00-1C-42-7B-65-0A
- EUI64(Extended Unique Identifier 64)记录:
- 作用:存储 64 位扩展唯一标识符(通常为 IPv6 接口标识符)。
- 示例:
rockylinux.cn. IN EUI64 00-1C-42-FF-FE-7B-65-0A
- OPENPGPKEY(OpenPGP Key)记录:
- 作用:存储 OpenPGP 公钥,用于加密电子邮件和验证签名。
- 示例:
rockylinux.cn. IN OPENPGPKEY mQENBF...
- SMIMEA(S/MIME Certificate Association)记录:
- 作用:存储 S/MIME 证书,用于加密和签名电子邮件。
- 示例:
_smimecert.rockylinux.cn. IN SMIMEA 3 1 1 4a5c...
- AVC(Application Visibility and Control)记录:
- 作用:用于存储与应用程序可视性和控制相关的数据。
- 示例:
rockylinux.cn. IN AVC ...
- CSYNC(Child-to-Parent Synchronization)记录:
- 作用:用于自动同步子区域和父区域的 DNS 数据。
- 示例:
rockylinux.cn. IN CSYNC 12345 A NS
- HIP(Host Identity Protocol)记录:
- 作用:存储 Host Identity Tag (HIT) 和主机标识。
- 示例:
rockylinux.cn. IN HIP 1 2001:0db8::1 a3d3d7e3a1...
- TKEY(Transaction Key)记录:
- 作用:用于 DNS 安全扩展(DNSSEC)的会话密钥协商。
- 示例:
rockylinux.cn. IN TKEY ...
- TSIG(Transaction Signature)记录:
- 作用:用于 DNS 请求和响应的消息完整性和身份验证。
- 示例:
rockylinux.cn. IN TSIG hmac-md5.sig-alg.reg.int. 1234567890 300 16 1234567890abcdef1234567890abcdef
- NID(Node Identifier)记录:
- 作用:为节点标识符(NID)提供 DNS 支持。
- 示例:
rockylinux.cn. IN NID 1 192.168.1.1
- L32(Locator 32)记录:
- 作用:存储 IPv4 网络的 32 位定位器。
- 示例:
rockylinux.cn. IN L32 192.168.1.1
- L64(Locator 64)记录:
- 作用:存储 IPv6 网络的 64 位定位器。
- 示例:
rockylinux.cn. IN L64 2001:0db8::1
- LP(Locator Pointer)记录:
- 作用:提供与 L32 和 L64 记录相关的定位器指针。
- 示例:
rockylinux.cn. IN LP 10 2001:0db8::1
- SVCB(Service Binding)记录:
- 作用:用于指定访问服务所需的参数,为新的协议和服务提供更灵活的配置。
- 示例:
_rockylinux._https IN SVCB 1 svc4.rockylinux.org. port=8443 alpn=h2
- HTTPS 记录:
- 作用:HTTPS 记录是 SVCB 记录的一个特例,专门为 HTTPS 服务设计,用于优化浏览器对 HTTPS 服务的连接过程。
- 示例:
_rockylinux._https IN HTTPS 1 svc4.rockylinux.org. port=8443 alpn=h2
- ZONEMD(Zone Message Digest)记录:
- 作用:提供整个 DNS 区域的消息摘要,用于区域完整性验证。
- 示例:
rockylinux.cn. IN ZONEMD 2021010101 1 1 ( 1234567890abcdef1234567890abcdef )
- OPT(Option)记录:
- 作用:用于扩展 DNS 协议,存储 EDNS(扩展 DNS)选项数据。
- 示例:
rockylinux.cn. IN OPT ...
在实际生产当中常用的包括:A
、MX
、CNAME
、URI
、TXT
等,当然不同的 DNS 服务提供商还有一些自定义的类型,比如:Cloudflare 提供了一种 Worker
类型的解析,主要用于为自家的 Workers 和 Pages 产品提供解析服务。
域名解析全过程
为了让大家能够更好的理解域名解析的全过程,这里以用户访问 https://www.rockylinux.cn 域名解析全过程为例进行讲解。
DNS 解析是互联网中将域名转换为 IP 地址的关键过程。以下是 DNS 解析的 10 个详细步骤,其中前两个步骤在本地电脑内完成,后八个步骤涉及域名解析服务器:
- 浏览器缓存检查:本地电脑首先检查浏览器缓存中是否存在该域名对应的 IP 地址。如果缓存中有,这个解析过程就结束。浏览器缓存域名的时间有限制,通常几分钟到几小时不等,由域名的 TTL(生存时间)属性控制。缓存时间太长或太短都不合理,太长会导致 IP 地址变更时无法及时更新,太短则增加解析请求频率。
- 操作系统 Host 检查:如果浏览器缓存中没有数据,浏览器会查找操作系统缓存中是否有该域名对应的 DNS 解析结果。在 Linux 系统中通过
/etc/hosts
文件设置。在 Windows 系统中通过C:\Windows\System32\drivers\etc\hosts
文件设置。用户可以将域名解析到特定 IP 地址,用于开发测试或运维交互验证等。 - 本地 DNS 服务器查询:如果前两个步骤都未能解析域名,操作系统会将请求发送给配置的本地 DNS 服务器。通常,内网环境(如学校或公司)都会配置本地 DNS 服务器,这些服务器也会缓存解析结果。大约 80% 的解析请求在此结束。如果您配置的是比如阿里或腾讯的 DNS 服务器地址(比如:223.6.6.6),缓存机制是由对方控制的,而本地配置的 DNS 服务器缓存等是由自身控制的。Windows 系统中 DNS 服务器地址配置路径:控制面板 -> 网络和共享中心 -> 更改适配器设置 -> 选中目标适配器右键选择属性 -> Internet 协议版本 4 (TCP/IPv4) -> 配置 DNS 地址。Linux 系统中配置文件路径:
/etc/resolv.conf
,当然不同 Linux 系统类型配置方法有所不同。 - 根 DNS 服务器查询:如果本地 DNS 服务器无法解析域名,它会向根 DNS 服务器发送请求。全球有 13 个根 DNS 服务器,这些服务器保存顶级域名服务器的地址,比如:
.com
、.cn
、.org
等。 - 顶级域名服务器地址返回:根 DNS 服务器返回顶级域名服务器(如
.com
、.cn
、.org
等)的地址。 - 顶级域名服务器查询:本地 DNS 服务器向获得的顶级域名服务器发送解析请求。
- Name Server 地址返回:顶级域名服务器返回该域名对应的 Name Server 域名服务器地址。Name Server 是由域名提供商管理的服务器,负责该域名的解析任务。例如,访问 www.rockylinux.cn 时,实际我们走了两层 DNS 解析,一层位于腾讯云 DNSpod,另一层位于 Cloudflare,用于实现根据不同地址位置解析。这超出了我们本文的范畴,暂不详述。
- Name Server 查询:Name Server 查询存储的域名和 IP 地址映射关系表,将查询结果和 TTL 值返回给本地 DNS 服务器。
- 缓存解析结果:本地 DNS 服务器缓存该域名和 IP 地址的对应关系,缓存时间由 TTL 值控制。
- 返回解析结果:本地 DNS 服务器将解析结果返回给本地电脑,本地电脑根据 TTL 值将其缓存到系统缓存中,至此域名解析过程结束。
在实际的 DNS 解析过程中,可能还会有更多步骤。例如:Name Server 可能有多级结构,或者有一个全局流量管理(GTM)系统来进行负载均衡控制,这些都会影响域名解析过程。
下面使用 dig
命令对域名解析各阶段进行说明:
[root@coredns-001 ~]# dig www.rockylinux.cn
# 查询参数与统计信息
; <<>> DiG 9.16.23-RH <<>> www.rockylinux.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33915
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
# 查询内容,这里查询的是 www.rockylinux.cn 的 A 记录
;; QUESTION SECTION:
;www.rockylinux.cn. IN A
# DNS 服务器的响应结果,返回 9 条 A 记录信息,其中 TTL 为 600 秒,表示 DNS 查询缓存时间。
;; ANSWER SECTION:
www.rockylinux.cn. 600 IN CNAME www.rockylinux.cn.cdn.dnsv1.com.
www.rockylinux.cn.cdn.dnsv1.com. 600 IN CNAME 4mm2a9bp.slt.sched.tdnsv8.com.
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 183.255.118.118
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 111.29.14.58
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 183.255.118.94
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 111.29.14.124
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 183.255.104.113
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 36.159.79.135
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 120.226.2.65
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 183.255.118.215
4mm2a9bp.slt.sched.tdnsv8.com. 60 IN A 183.253.58.241
# DNS 服务器传输信息
;; Query time: 43 msec # 查询耗时 43 毫秒
;; SERVER: 192.168.1.1#53(192.168.1.1) # DNS 服务器IP、端口
;; WHEN: Tue Jul 02 10:49:13 CST 2024
;; MSG SIZE rcvd: 145 # 返回字节长度 145
# 如果只想查询返回结果,可以使用 +short 参数
[root@coredns-001 ~]# dig +short www.rockylinux.cn
www.rockylinux.cn.cdn.dnsv1.com.
4mm2a9bp.slt.sched.tdnsv8.com.
111.29.14.124
111.29.14.58
183.255.118.94
36.159.79.135
183.255.118.118
183.255.104.113
120.226.2.65
183.255.118.215
183.253.58.241
另外可以通过 dig
命令的 +trace
参数显示 DNS 解析的整个分级查询过程,这更有利于我们理解上面的域名解析流程图。
[root@coredns-001 ~]# dig +trace www.rockylinux.cn
# 第一阶段:返回所有根服务器信息
; <<>> DiG 9.16.23-RH <<>> +trace www.rockylinux.cn
;; global options: +cmd
. 3346 IN NS d.root-servers.net.
. 3346 IN NS b.root-servers.net.
. 3346 IN NS j.root-servers.net.
. 3346 IN NS m.root-servers.net.
. 3346 IN NS c.root-servers.net.
. 3346 IN NS k.root-servers.net.
. 3346 IN NS h.root-servers.net.
. 3346 IN NS g.root-servers.net.
. 3346 IN NS a.root-servers.net.
. 3346 IN NS e.root-servers.net.
. 3346 IN NS l.root-servers.net.
. 3346 IN NS i.root-servers.net.
. 3346 IN NS f.root-servers.net.
;; Received 431 bytes from 192.168.1.1#53(192.168.1.1) in 14 ms
# 第二阶段:查看后缀 cn 的顶级域名服务器信息
cn. 172800 IN NS d.dns.cn.
cn. 172800 IN NS a.dns.cn.
cn. 172800 IN NS ns.cernet.net.
cn. 172800 IN NS b.dns.cn.
cn. 172800 IN NS c.dns.cn.
cn. 172800 IN NS e.dns.cn.
cn. 86400 IN DS 57724 8 2 5D0423633EB24A499BE78AA22D1C0C9BA36218FF49FD95A4CDF1A4AD 97C67044
cn. 86400 IN RRSIG DS 8 1 86400 20240714220000 20240701210000 20038 . GBzlIo7JeoI9lC0i+Ft9N/GAs5fzWpNbOuKniuynXOd8yP8Dvsw1nmEu PiSbac2k2khjsf7AMLHNYct1KTnd+l+1GAG6ZI3Sxubp2xoLs/cLUXmU mQQ5ZPXvletMOCbMXgqyHVetjwcKFHtvHdKMdCDUbzBnhl2uOw7v0qXL pMcN8kUmy/CnzGqvbPhVhZ1JMzP1rTx6ez4cKUiN8sKBqUboIJQ3A8aK Dqy6rIKQS9u5msdKWaghPv7hxgyrjccQ4STWWFxolDbxdf/oZP8+NLpT 5bME6XQsjqtFYQlWMfSbIk3fbCPVY3U/mvheVcW8SHb/vIw3SXbesC9S S1+ldw==
;; Received 760 bytes from 170.247.170.2#53(b.root-servers.net) in 74 ms
# 第三阶段:查看次级域名(一级域名)服务器信息
rockylinux.cn. 86400 IN NS ethel.dnspod.net.
rockylinux.cn. 86400 IN NS teresa.dnspod.net.
3QDAQA092EE5BELP64A74EBNB8J53D7E.cn. 21600 IN NSEC3 1 1 10 AEF123AB 3QHKTF6LTFG8AAFUUAJSR8RVAJP99SFU NS SOA RRSIG DNSKEY NSEC3PARAM
3QDAQA092EE5BELP64A74EBNB8J53D7E.cn. 21600 IN RRSIG NSEC3 8 2 21600 20240724080919 20240624075551 38388 cn. S6oKZea6MMhhQFNL/QKyEX9pJyPNQrAv+WGd7oupl2ma1+HGm13QfELh 2MZWmvNUsl0qWuDCJ4KtO8BQtygLtoiwvgbr45fiVGxZn0uZLIsG+Kon 9JE9ybX/mjGD4zLAAZWTAVDibOSqLlSbW8hm5fHC+6man2hEFbLHbjEz 1vE=
DF3OCIJI71MFDJ9KMCL8VEQJIRL6S4NF.cn. 21600 IN NSEC3 1 1 10 AEF123AB DH1DUDAN3PJV060FC51M37GDJOR3NL8R NS DS RRSIG
DF3OCIJI71MFDJ9KMCL8VEQJIRL6S4NF.cn. 21600 IN RRSIG NSEC3 8 2 21600 20240721021126 20240621013431 38388 cn. kld7vw7CDhZhAqCjTpK6l64n3yP+OHEzDw889U9pIApjXWkxGDeT1PHq E0S/wHJSw+lRkUMbZyIoKm09fszWaOK4OvXEfXVjgi7pHZvm3VfZzRMv qHeO+akUwvfM0PgyMYJsnNFd2uUFDpZGtRaVuuqeKa/2zfg6bn2BuDqg PuM=
;; Received 616 bytes from 103.137.60.44#53(ns.cernet.net) in 45 ms
# 第四阶段:通过一级域名服务器获取对应域名的 A 记录,因为木子配置了 CDN,所以看到的是 CNAME 记录信息。
www.rockylinux.cn. 600 IN CNAME www.rockylinux.cn.cdn.dnsv1.com.
rockylinux.cn. 86400 IN NS ethel.dnspod.net.
rockylinux.cn. 86400 IN NS teresa.dnspod.net.
;; Received 152 bytes from 1.12.0.4#53(teresa.dnspod.net) in 39 ms
# 当然还可以手动一级一级查询
[root@coredns-001 ~]# dig +short ns cn
a.dns.cn.
e.dns.cn.
b.dns.cn.
d.dns.cn.
c.dns.cn.
ns.cernet.net.
[root@coredns-001 ~]# dig +short ns rockylinux.cn
ethel.dnspod.net.
teresa.dnspod.net.
[root@coredns-001 ~]# dig +short CNAME www.rockylinux.cn
www.rockylinux.cn.cdn.dnsv1.com.
参考文献
[1] RSSAC FAQ
[2] Root Servers
[3] New addresses for b.root-servers.net
[4] Root Server Technical Operations Association
[5] LACNIC asigna recursos de numeración al servidor raíz de USC/ISI
![](https://www.rockylinux.cn/images/1669431564-wechat-pay.png)