0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

DNS报文结构与编码解析

dyquk4xk2p3d 来源:taoshu.in 2023-06-26 10:54 次阅读

网上很多人都说 DNS 根服务器只有 13 台,中国一台也没有。在网络世界,中国被美国卡住了脖子。那 DNS 根服务器真的只有 13 台吗?如果是,那原因又是什么?今天就给大家说道说道。

DNS 基本概念

在回答这个问题之前,我们需要先回顾一些基本概念。DNS 是一种分层结构,这种层级就体现在域名的『点』里。以我的域名为例,TAOSHU.IN它的完整域名其实是TAOSHU.IN.。注意最后有一个点。它分三个层级,结结构为.➜IN➜TAOSHU。

DNS 又是分布式系统,每一层级都有自己的解析服务器。.是第一层级,它的解析服务器就是根服务器。第二层级是对应我们常说的COM/NET等顶级域名 TLD,而我用的IN是印度的国家域名,跟中国的CN一样,它们都是 CCTLD,也就是所谓的国家顶级域名。TAOSHU就是普通的一级域名。每个域名都可以自行设置子域名,不受上级域名限制。

域名解析过程也是分布式的。还是以TAOSHU.IN为例。客户端先找到根服务器的地址,并其查询IN的解析服务器。再向IN的服务器查询TAOSHU.IN的服务器。最后向TAOSHU.IN的服务器查询具体的解析记录,比如 A 记录等。

当前根服务器

从上面的过程可知,所有的 DNS 查询都从根服务器开始。所以根服务器是整个 DNS 系统的核心。如果根服务器出现故障,那所有 DNS 查询都会失败!为了避免出现这种问题,人们设置了多个 DNS 根服务器。发展到现在,互联网社区累计设置了 13 台,它们分别是:

主机名 IP 地址 运营机构 国家
a.root-servers.net 198.41.0.4, 2001ba3e:30 Verisign, Inc. 美国
b.root-servers.net 199.9.14.201, 2001200::b University of Southern California, Information Sciences Institute 美国
c.root-servers.net 192.33.4.12, 20012::c Cogent Communications 美国
d.root-servers.net 199.7.91.13, 20012d::d University of Maryland 美国
e.root-servers.net 192.203.230.10, 2001a8::e NASA (Ames Research Center) 美国
f.root-servers.net 192.5.5.241, 20012f::f Internet Systems Consortium, Inc. 美国
g.root-servers.net 192.112.36.4, 200112::d0d US Department of Defense (NIC) 美国
h.root-servers.net 198.97.190.53, 20011::53 US Army (Research Lab) 美国
i.root-servers.net 192.36.148.17, 2001:53 Netnod 瑞典
j.root-servers.net 192.58.128.30, 2001c27:30 Verisign, Inc. 美国
k.root-servers.net 193.0.14.129, 2001:1 RIPE NCC 荷兰
l.root-servers.net 199.7.83.42, 20019f::42 ICANN 国际
m.root-servers.net 202.12.27.33, 2001:35 WIDE Project 日本

资料来源:IANA1 资料截止时间:2023年06月06日

在 1984 年,Jon Postel 和 Paul Mockapetris 在南加州大学设立了世界上第一台根服务器2。到了 1990 年,根服务器的数量扩展到了 7 台,分属不同的组织给护,但全都在美国。到了 1991 年,KTH 在瑞典设立一台根服务器。这是首次在美国之外部署根服务器。此后一直有旧的根服务器退役,新的服务器入役。到了 1995 年,根服务器已经扩展到 9 台。这个时候就遇到了技术瓶颈,无法添加新的根服务器了。

到底是什么技术瓶颈呢?这就得说说 DNS 的底层实现细节了。

Priming 查询

前面说所有的 DNS 查询都从根服务器开始。那客户端怎么知道当前有哪些根服务器呢?没什么好办法,就是在各自的代码中写死!对,是硬编码。但我们前面也说了,在役的根服务器并非一成不变,写死的话新添加的服务怎么生效呢?

这就用到了所谓的 Priming Queries3。简单来说,所有 DNS 解析客户端都随软件附带一个列表文件,里面有当前所有根服务器的信息,包括域名、IP地址等信息。这个文件叫 Root Hints,可以从 IANA 官网4下载。但考虑到根服务器的列表可能会变,所以客户端需要定期从已知的根服务器查询当前最新的服务器列表,用的也是 DNS 协议,这类请求叫作 Priming 查询。

对于客户端来说,它先从 Root Hints 中根据某种规则5选出一台根服务器,然后向它查询最新的根服务器列表,并本机缓存一段时间,过期之前都以该列表为准。

因为 Priming 查询也是用 DNS 协议,自然也走 UDP 传输。互联网早期 IP 网络的最大传输单元长度(MTU)也就五百多字节,所以 DNS 回复信息的最大长度同样不能太长。所以 DNS 协议规定回复信息不能超过 512 字节。这就是添加根服务器遇到的技术瓶颈。

其实解决这个问题很容易,完全可以要求客户端使用 TCP 连接传输 Priming 查询结果嘛。可惜当时没有采用这种方案。不过,如果是我,也不会选 TCP 方案。因为所有 DNS 查询都走 UDP 协议,简单而统一。虽然 DNS 也支持使用 TCP,但让 Priming 查询单独走 TCP 明显会让系统变得很复杂。

社区最终决定想办法压缩查询结果长度。

报文结构与编码

DNS 报文结构如下,分为五个部分6。

+---------------------+
|Header|
+---------------------+
|Question|thequestionforthenameserver
+---------------------+
|Answer|RRsansweringthequestion
+---------------------+
|Authority|RRspointingtowardanauthority
+---------------------+
|Additional|RRsholdingadditionalinformation
+---------------------+

Header

Header 为报文头信息,长度固定为 12 字节,结构如下:

0123456789012345
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|ID|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|Opcode|AA|TC|RD|RA|Z|RCODE|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QDCOUNT|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|ANCOUNT|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|NSCOUNT|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|ARCOUNT|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Header 中跟本文内内直接相关的就是 QDCOUNT/ANCOUNT/NSCOUNT/ARCOUNT 这四个字段,分别表示后续 Question/Answer/Authority/Additional 段的数量。

Question

Question 段保存查询请求信息,通长只有一个。它分成三个部分。后两个部分表示查询类型和网络类型。含义不重要,重要的是长度固定为 4 字节。

0123456789012345
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
||
/QNAME/
//
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QTYPE|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QCLASS|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

第一部分 QNAME 长度可变,保存查询的域名。但存储的方式有点特别。以域名A.ROOT-SERVERS.NET.为例,它会分成三部分A、ROOT-SERVERS和NET。每一部分称作一个标签(Label), QNAME 字段只保存标签,不保存.。每个标签用第一个字节记录当前标签长度,后面跟着标签内容。最后用一个长度为零的标签表示结尾。所以完整的 QNAME 字段编码为:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20|1|A|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22|12|R|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24|O|O|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26|T|-|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28|S|E|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30|R|V|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
32|E|R|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34|S|3|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
36|N|E|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38|T|0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

长度为 20 字节。特别的,对于根域名.,它的 QNAME 编码是:

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20|0||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

长度为 1 字节。

Answer

Answer 段是服务器返回的响应结果。数量为一条到多条不等。每一条称为一个 RR,全称是 Resource Record。其结构如下:

0123456789012345
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
||
//
/NAME/
||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|TYPE|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|CLASS|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|TTL|
||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|RDLENGTH|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/RDATA/
//
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

RR 跟前面的 Question 相比多了 TTL/RDLENGTH/RDATA 三个字段。TTL 表示有效时长, RDLENGTH 表示后续 RDATA 的长度,RDATA 保存实际的响应数据。根据 TYPE 和 CLASS 的不同,RDATA 内容也各不相同。在 Priming 查询中,RDATA 保存各根服务器的域名,编码跟前 Question 中的 QNAME 一样。

如果服务器返回如下一条 RR 数据:

.518400INNSa.root-servers.net.

那么 RR 的总长度是 1+2+2+4+2+20=31 字节。

Authority

Authority 段用来返回待查询域名的权威服务器信息。比如我们尝试向根服务器直接查询TAOSHU.IN的A记录,根服务器就会在 Authority 段返回IN域名的解析服器。因为根服务器并不保存TAOSHU.IN的域名信息。不过在本文中,Priming 查询的权威服务器就是根服务器,所以此段长度为零。

最后的 Additional 段用来返回一些附加信息。Answer 中只有域名信息。我们希望直接返回 IP 地址,所以需要用到 Additional 段。Additional 中也是一条一条的 PR,计算方式跟 Answer 的一模一样。

因为 Priming 查询会返回所有的根服务器域名及其对应的 IP 地址7,所以根服务器数量越多,返回的数据就越长。但 DNS 协议规定最长只能是 512 字节,这就产生了瓶颈。

到了 1995 年,已经开通了 9 台根服务器,Priming 查询结果快要超过 512 字节了。社区开始着手解决这个问题。方案是标签压缩。

标签压缩

压缩办法也很简单,就是在 NAME 中引入指针结构

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|11|OFFSET|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

DNS 还有一个规定,域名的长度不能超过 63 字节。NAME 中第一个字节表示长度,最大值就是 63,二进制表示为00111111,可见高两位是零。于是大家约定高两位设为11的时候,后面的 14 位就表示从报文 Header 开始的偏移量。这样一来,如果多个 RR 的域名中有相同的部分,就不需要重复传输,减少响应长度。

举个例子,比如要同时返回A.ROOT-SERVERS.NET和B.ROOT-SERVERS.NET两个域名,显然它们有共同的后缀ROOT-SERVERS.NET。假设A.ROOT-SERVERS.NET的偏移量为 20,那么可以表示为:

A.ROOT-SERVERS.NET
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20|1|A|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22|12|R|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24|O|O|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26|T|-|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28|S|E|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30|R|V|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
32|E|R|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34|S|3|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
36|N|E|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38|T|0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
B.ROOT-SERVERS.NET
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40|1|B|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44|11|20|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46|0||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

利用标签压缩技术,域名B.ROOT-SERVERS.NET只需要占用 5 个字节,比A.ROOT-SERVERS.NET节省了 15 个字节。

根服务器更名

要想使用压缩,前提是所有域名有重复的部分。但之前的根服务器域名不相同,这就得改名。到了 1995 年,社区统一的域名为根服务器重新编组并部署标签压缩功能。

旧域名 新域名 运营机构
NS.INTERNIC.NET A.ROOT-SERVERS.NET InterNIC (operated by NSI)
NS1.ISI.EDU B.ROOT-SERVERS.NET Information Sciences Institute, USC
C.PSI.NET C.ROOT-SERVERS.NET PSINet
TERP.UMD.EDU D.ROOT-SERVERS.NET University of Maryland
NS.NASA.GOV E.ROOT-SERVERS.NET NASA Ames Research Center
NS.ISC.ORG F.ROOT-SERVERS.NET Internet Software Consortium
NS.NIC.DDN.MIL G.ROOT-SERVERS.NET GSI (operated by NSI)
AOS.ARL.ARMY .MIL H.ROOT-SERVERS.NET U.S. Army Research Lab
NIC.NORDU.NET I.ROOT-SERVERS.NET NORDUnet

上线之后,为新的根服务器留出了空间。于是在 1997 年,又上线了 J/K/L/M 四台根服务器。

这时候 Priming 查询响应的返回值有多大呢?我们可以算一下:

Header 固定 12 字节

第一个 PR 保存完整域名,31 字节

另外 12 PR 保存压缩后的域名,12*15 = 180 字节

13 个 PR 保存 A 记录,13 * 16 = 208 字节8

Question 段中 QTYPE 和 QCLASS 字段, 4 字节

Question 段中 QNAME 字段,1 字节

总共为 12+31+180+208+4+1=436 字节。剩余可用 512−436=76 字节。一组台服务器需要额外占用 15+16=31 字节。理论上还可以再添加两台根服务器,也就是最多15台。

如果只管根服务器功能,确实还可以添加。但是早期的根服务器同时也是COM/NET/ORG的解析服务器。客户端可以向根服器发起针对特定COM域名的 Priming 查询。因为响应结果需要包含查询域名 QNAME,所以上面说的 76 字节中至少要保留 64 字节给 QNAME。这样就只剩下 12 字节。所以就不能再添加新的根服务器了。

IPv6 与 Anycast

虽然理论上是不能再加新的根服务器了,但后来网络不断发展,UDP 报文早已不需要把长度限制到 512 字节。而且引入 IPv6 网络后,Priming 查询结果中还需要返回 AAAA 记录, 512 个字节肯定不够用。所以社区又设计了 EDNS09 来支持返回超过 512 字节的 DNS 响应。

理论上还是可以继续添加新的根服务器。但为什么不加了呢?那是因为有了更先进的技术 Anycast,中文译作任播。任播,可以简单理解为允许不同网络中的计算机共用一个 IP 地址,同时对外提供 DNS 查询服务。互联网会根据客户端的位置将请求路由到就近的计算机。

Anycast 技术将原来的单台服务器变成了一组多台服务器。到了2002年,J根服务器首次部署 Anycast 功能。到现在为止,前面说的13台根服务器严格来说是 13 个域名并且对应 13 对 IPv4 和 IPv6 地址。每对地址之后都通过 Anycast 部署了很多台实例,总计有超过 1500 台根服务器实例。这些实例又称为根镜像服务器

中国根服务器镜像

虽说中国没有自己的根服务器,但境内还是有不少根镜像服务器:

编号 城市
A 广州
D 香港 台北
E 台北
F 北京 重庆 杭州 高雄 南宁 台北
I 北京 香港 沈阳 台北
J 北京 香港 湖州 上海
K 北京 广州 贵阳 台北
L 北京 长沙 海口 上海 武汉 西宁 新北 郑州
M 高雄

大家不妨通过 Ping 命令测一下,上面的几个根服务器的延迟都在 50ms 左右,一看就是在国内,不然不会这么快。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编码
    +关注

    关注

    6

    文章

    942

    浏览量

    54815
  • DNS
    DNS
    +关注

    关注

    0

    文章

    218

    浏览量

    19828
  • 报文
    +关注

    关注

    0

    文章

    38

    浏览量

    4027
  • 根服务器
    +关注

    关注

    1

    文章

    7

    浏览量

    3210

原文标题:为什么 DNS 全球只有 13 台根服务器,中国却没有自己的?

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    FPGA可以做报文解析吗?有没有相关资料?

    我想在fpga上做一个报文解析的功能,就是将一串01数据发送给FPGA,然后fpga对数据进行报文解析,然后再将解析后的数据发送给电脑,想问
    发表于 11-13 16:04

    如何解决DNS解析错误故障

    DNS解析出现错误,就是把一个域名解析成一个错误的IP地址,或者根本不知道某个域名对应的IP地址是什么时,我们就无法通过域名访问相应的站点了,这就是DNS
    发表于 09-29 15:14

    为什么我的DNS解析为0.0.0.0?

    为什么我的DNS解析为0.0.0.0?它被称为SuxChar*URL=“www. GooGl.com”;IPNS4ADDR ADDR;DNSRES= TCPIPSY-DNSUBION解析(URL
    发表于 01-17 13:36

    使用JavaScript代码在Rapid板子上实现DNS解析域名得到IP地址操作分享!

    ,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。在这里,您将了解到如何使用JavaScript代码在Rapid板子上来实现DNS解析域名得到IP地址。Javascr
    发表于 08-15 04:17

    荣小菜补钙记第43期:报文合成与解析之字的合成与分解

    荣小菜补钙记第43期:报文合成与解析之字的合成与分解 同步更新于 WeChat:荣小菜在补钙欢迎关注 内容更丰富大家好,我是荣小菜,本期将分享一个能够快速合成和分解报文字(字节)的Vi,同时结合
    发表于 08-26 20:33

    CAN报文解析需要知道DBC的哪些信息排序方式

    CAN总线中报文数据读取方法motorola编码格式的CAN报文解析需要知道DBC的哪些信息排序方式读取方式发送方式注motorola编码
    发表于 01-12 07:28

    Win 2000中DNS服务器的设置

    Win 2000中DNS服务器的设置  DNS Domain Name Service是域名解析服务,是一种组织成域层次结构的计算机和网络服务命名系统。
    发表于 02-01 11:51 900次阅读

    什么是DNS

    什么是DNS  英文原义:Domain Name Server 中文释义:域名解析系统 注  解:简单地说,
    发表于 02-23 11:08 724次阅读

    电力101规约(2002版)报文解析

    电力101规约(2002版)报文解析~~~~
    发表于 01-08 14:39 0次下载

    浅谈两种加密DNS协议

    DNS over TLS的标准文档是RFC7858。文档很短,也比较易懂。客户端先和递归服务器进行TLS握手,使用的TCP端口号是853。握手之后,把DNS数据包作为TLS的payload发给DNS递归服务器即可。请求和回答的
    发表于 05-02 15:44 7309次阅读

    教你动手写UDP协议栈—DNS报文解析

    教你动手写UDP协议栈系列文章序号内容1《教你动手写UDP协议栈-UDP协议栈格式》2《教你动手写UDP协议栈-DHCP报文解析》3《教你动手写UDP协议栈-OTA上位机》4《教你动手写UDP协议栈-
    的头像 发表于 12-24 16:16 1423次阅读

    网络协议栈:MQTT的报文格式解析

    在上一篇文章,直接在本地搭建了服务器和客户端,简单的实践了MQTT的用法。而这一篇来解析MQTT的报文格式。MQTT的报文字段很精简。但是解析起来还是有些复杂的。
    的头像 发表于 05-13 14:06 5455次阅读
    网络协议栈:MQTT的<b class='flag-5'>报文</b>格式<b class='flag-5'>解析</b>

    DNS基本概述

    与 HTTP、FTP 和 SMTP 一样,DNS 协议也是一种应用层的协议,DNS 使用客户-服务器模式运行在通信的端系统之间,在通信的端系统之间通过 UDP 运输层协议来传送 DNS 报文
    的头像 发表于 05-25 10:49 3003次阅读

    DNS结构和工作原理

    DNS 代表域名系统或域名服务器。DNS 将IP 地址解析为主机名,反之亦然。
    的头像 发表于 08-05 15:23 518次阅读
    <b class='flag-5'>DNS</b>的<b class='flag-5'>结构</b>和工作原理

    解析的高防DNS是什么?高防DNS有什么作用?

    DNS解析手段在应对攻击时只能采取被动防守的策略,导致线路拥堵、服务器宕机、域名劫持等情况的时有发生。云解析作为一种更智能、更安全的解析技术,其高防
    的头像 发表于 09-26 17:31 291次阅读