3732 字
19 分钟
浅谈DNS消息格式

🖋️作者: 千石🌟
🌐个人网站:cnqs.moe🚀
🤝支持方式:👍点赞、💖收藏、💬评论
💬欢迎各位在评论区🗣️交流,期待你的灵感碰撞🌈

前言#

前段时间在朋友的推荐下阅读了 《DNS与Bind》 这本书,里面有涉及到 DNS消息格式 的内容,我对这部分比较感兴趣,遂做一下记录。

什么是DNS#

DNS,(即Domain Name System,翻译为域名系统)是互联网的基础服务之一,它的主要职责是将人类可读的域名(如 example.com)转换为机器可识别的IP地址(如 192.0.2.1)。它使得我们可以通过易于记忆的名称来访问网站,而无需记住复杂的数字序列。

《DNS与Bind》这本书的第一章的1.3小节(第五版第4页)有这样一段描述:

域名系统是一个分布式数据库。这种结构充许对整体数据库的各个部分进行本地控制,并且在各个部分中的数据通过客户端/服务器(client/server)模式变得对整个网络都可用。通过复制和缓存等机制,DNS拥有了健壮性和充足的性能。

……

域名被当做DNS数据库的索引来使用。可以把域名同DNS中的数据对应起来。在文件系统中,目录包含文件和子目录。同样,域也包含主机和子域。域中所包含的主机和子域的域名,就位于该域所属的命名空间的子树中。

简单来说,DNS是一个分布式数据库,由分散在世界各地的DNS服务器组成,它通过索引域名来高效地管理和定位网络中的主机和子域。

(图片来自于《DNS与Bind》图2.5,主机在此处通过域名来表示)

关于DNS更详细的内容可以阅读《DNS与Bind》《计算机网络:自顶向下方法》这两本书,写的非常详细,这里不再赘述。

DNS报文概述#

DNS消息格式,作为网络通信的核心组成部分,对于理解域名解析至关重要。它的结构精细且功能全面,保证了每次DNS查询的精确处理和有效响应。那么,这一格式是如何组织的,以确保高效的信息交换呢?

DNS消息的组成#

DNS消息由五个主要部分构成:Header、Question、Answer、Authority和Additional。每部分都具有特定的功能,共同完成DNS查询的整个过程。这里的关键是理解每个部分的作用及其在整体消息流中的重要性。

Header部分:消息的导航仪#

在DNS消息格式中,Header部分是整个消息处理的关键。这个部分虽然在整个消息中占据的字节较少,但其重要性不容小觑。

结构和组成

Header部分通常包括12个字节,由多个字段组成,包括事务ID、标志、问题数、回答数、权限记录数和额外记录数。事务ID是一个16位的数字,用于标识特定的DNS查询,确保请求和响应之间的一致性。接下来的标志字段则包含了多个控制位,如QR(查询/响应标识)、AA(授权回答标识)等。

截取自rfc1035,下同
                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

事务ID

事务ID的主要作用是区分不同的DNS查询。当一个DNS客户端向服务器发送查询时,它会生成一个随机的事务ID,并在收到响应时检查此ID以验证响应的有效性。这种机制增加了DNS查询的安全性,防止了响应的伪造。

标志字段

标志字段是Header部分中最复杂的元素。它包括多个不同的位,每个位都有其特定的意义。例如,QR位表示消息是查询(0)还是响应(1),AA位表示是否是权威回答,TC位表示消息是否被截断,RD位和RA位分别表示递归查询和递归回答的可用性。这些标志的正确设置对于DNS消息的正确处理至关重要。

计数字段

Header部分还包含了四个计数字段,分别表示问题、回答、授权记录和额外记录的数量。这些字段对于解析DNS消息的结构非常重要,因为它们指示了随后每个部分的记录数。

总之,Header部分在DNS消息中充当控制中心的角色,通过事务ID和标志字段等信息确保查询的一致性、安全性和正确处理。

Question部分:查询的焦点#

DNS消息格式中的Question部分是整个查询过程的出发点,它定义了DNS查询的具体目标和类型。

结构和组成

Question部分通常包括查询的域名(QNAME)、查询类型(QTYPE)和查询类(QCLASS)。域名字段指明了需要解析的具体域名,如“example.com”。查询类型字段则指定了查询的种类,例如A记录(IP地址)、MX记录(邮件交换服务器)等。查询类字段通常指的是IN(Internet),表示Internet类的查询。

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                     QNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QTYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QCLASS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

查询类型

在DNS查询中,不同的查询类型扮演着不同的角色。A记录查询用于获取域名对应的IP地址,MX记录查询用于查找处理电子邮件的服务器地址,CNAME记录则用于查找一个域名的规范名称。

域名字段

Question部分中的域名字段是整个DNS查询的核心。DNS客户端通过这个字段向服务器提出“我需要这个域名的哪些信息?”的问题。这个字段的正确格式化和解析对于整个查询过程的成功至关重要。

查询类

查询类(QCLASS)在大多数情况下都是IN。简单来说,当在DNS查询中指定查询类为IN时,这意味着查询是针对互联网(Internet)的资源记录。例如,当查询一个域名的A记录(用于寻找与域名关联的IPv4地址)或者AAAA记录(用于寻找与域名关联的IPv6地址)时,这些都是Internet类的查询。

虽然DNS协议理论上支持不同种类的网络(如CHAOS或Hesiod),但在实际应用中,绝大多数DNS查询都是针对互联网的,因此IN类是最常见和最广泛使用的类别。

总之,Question部分是DNS查询的明确指向,它通过域名、查询类型和查询类,告诉DNS服务器具体需要哪种类型的信息。

在DNS消息格式中,Answer、Authority和Additional部分共同构成了对Question部分查询的完整回应。它们不仅提供了查询请求的直接答案,还给出了权威源信息和额外的辅助数据。在以下内容中,我们将详细探讨这三个部分的作用和重要性。

Answer、Authority和Additional部分:构成DNS响应的核心元素#

结构和组成

Answer、Authority和Additional包含相同的字段,如下:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                                               /
    /                      NAME                     /
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     CLASS                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TTL                      |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   RDLENGTH                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
    /                     RDATA                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Answer部分:直接响应

Answer部分是对Question部分提出的查询的直接回答。例如,如果Question部分查询了某个域名的A记录,那么Answer部分将包含该域名的IP地址。这部分可以包含多个资源记录(RR),每个资源记录包含了名称、类型、类别、生存时间(TTL)、数据长度和数据本身。这些信息共同提供了关于查询结果的全面细节,如IP地址、主机名或其他相关信息。

Authority部分:权威引导

Authority部分包含权威名称服务器的信息,这些服务器是对查询域名具有权威的。在一些情况下,如果DNS服务器本身不包含请求的答案,它会提供权威名称服务器的信息,指导查询者到正确的服务器寻找答案。

Additional部分:辅助信息

Additional部分提供与查询相关的额外信息,这些信息虽不直接回答查询请求,却对完成整个查询过程大有帮助。例如,它可能包含权威服务器的地址记录,从而避免了对这些服务器再次进行DNS查询。

Bind中的DNS报文处理#

BIND(Berkeley Internet Name Domain)是一个开源的DNS服务软件,被许多企业和教育机构用于DNS查询和域名解析。它支持广泛的DNS协议标准,包括递归和迭代查询,以及各种类型的DNS记录处理。

DNS报文处理流程图如下:

(插个题外话,做计网DNS实验的时候,老师让我们用古早版本的OpenSUSE,出了各种幺蛾子,一个实验做了一下午,后来换了OpenCloudOS重新做实验,说多了都是泪qwq)

DNS报文处理的初始阶段

当BIND接收到一个DNS查询报文时,首先会解析Header部分,确定事务ID和标志字段。这一阶段是确定报文类型(如查询或响应)和提取基本操作信息的关键步骤。接下来,BIND会检查Question部分,了解查询的具体目标和类型。

查询类型的处理

BIND根据Question部分中指定的查询类型,决定如何处理该查询。对于常见的A记录查询,BIND会查找其本地缓存,如果有可用的答案,则直接返回。若无,BIND会根据配置决定是进行递归查询还是返回迭代查询的引导。

递归查询处理

在进行递归查询时,BIND会向上游的根服务器或顶级域名服务器发送查询请求,并逐步获取信息直到找到最终答案。这一过程中,BIND会充分利用其缓存机制,以提高效率和响应速度。递归查询的结果会被缓存以应对未来的相同请求。

迭代查询的引导

对于迭代查询,BIND会提供指向更具体名称服务器的引导信息。这通常涉及Authority和Additional部分的信息,如名称服务器的记录和对应的IP地址。

缓存和超时机制

BIND的一个关键特点是其强大的缓存机制。它会存储先前查询的结果,包括所有相关的记录信息,以加速未来的查询处理。同时,为保证信息的最新性,BIND实施了生存时间(TTL)的超时机制,确保过时的记录被及时更新或删除。

安全性考虑

考虑到DNS攻击的可能性,如缓存投毒和DNS放大攻击,BIND在处理DNS报文时采取了一系列安全措施。这包括验证响应的合法性,确保事务ID和请求匹配,以及限制对特定类型查询的响应,从而增强了整体的DNS服务安全性。

DNS查询机制#

在DNS查询过程中,递归查询和迭代查询是两种基本的解析机制。

递归查询:一站式解析#

在递归查询中,当一个DNS客户端(如计算机)向其配置的DNS服务器(通常是本地ISP的服务器)请求解析一个域名时,这个服务器将负责处理整个查询过程,直至获得最终答案。如果此服务器没有缓存该域名的解析结果,它会作为客户端向其他服务器进行查询,直到找到答案或到达查询链的末端。

在这个过程中,DNS消息格式的每一部分都被充分利用。例如,Header部分在每次请求和响应中保持一致性;Question部分指定了查询的具体域名和类型;Answer部分在最终响应中给出了所需的记录;而Authority和Additional部分在必要时提供进一步的指导和信息。

迭代查询:逐步寻址#

迭代查询则有所不同。在这种模式下,客户端的DNS服务器向根服务器发起查询。根服务器不会直接回答查询,而是提供一个指向更具体名称服务器的引导(如顶级域名服务器)。然后,客户端的DNS服务器继续向这些服务器进行查询,逐步逼近最终答案。

在迭代查询中,DNS消息格式同样发挥着关键作用。Header部分在每一步的请求和响应中维护着事务的一致性;Question部分在整个查询过程中保持不变,确保查询的目标明确;Authority部分在每一步提供了更接近答案的名称服务器信息;Additional部分有时也会提供辅助信息,如名称服务器的IP地址,以加速查询过程。

一个例子🌰#

让我们回顾之前的例子:假设一个设备要解析“example.com”。在递归查询中,本地DNS服务器执行所有查询步骤,最终将解析结果返回给设备。而在迭代查询中,本地服务器将逐步与根服务器、顶级域名服务器和权威名称服务器交互,每一步都使用DNS消息格式来保证查询的正确执行。

最后#

通过撰写这篇文章文章,我发现自己对这些概念的理解还有提升的空间。原以为自己已经能够清晰较为地阐述这些复杂的技术细节,但在真正写作的过程中,我意识到在某些部分上我的表达还不够流畅。

我深刻认识到,理论知识和实际应用能力之间还有一段距离。因此,我更加坚信了踏实学习的重要性,同时也意识到不能抱有侥幸心理。对我而言,这不仅是一次学习的机会,也是一个自我提升的过程。共勉。

8. 参考资料#

浅谈DNS消息格式
https://cnqs.moe/posts/talk-dns-format/
作者
千石
发布于
2024-02-07
许可协议
CC BY-NC-SA 4.0