为什么 DNS 使用 UDP 协议?( 二 )


  • 使用 UDP 进行传输的 DNS 查询和响应最大不能超过 512 字节,不能支持大量 IPv6 地址或者 DNS 安全签名等记录的传输;
  • EDNS 为 DNS 提供了扩展功能,让 DNS 通过 UDP 协议携带最多 4096 字节的数据;
8.RFC7766 · DNS Transport over TCP - Implementation RequirementsProposed Standard, 2016-03
  • 当客户端接收到一个被阶段的 DNS 响应时,应该通过 TC 字段判断是否需要通过 TCP 协议重复发出 DNS 查询请求;
  • DNSSEC 的引入使得截断的 UDP 数据包变得非常常见;
  • 使用 UDP 传输 DNS 的数据包大小超过最大传输单元(MTU)时可能会导致 IP 数据包的分片,RFC1123 文档中预测的未来已经到来了,唯一一个用于增加 UDP 能够携带数据包大小的 EDNS 机制被认为不够可靠;
  • 所有通用 DNS 实现必须要同时支持 UDP 和 TCP 传输协议,其中包括权威服务器、递归服务器以及桩解析器;
  • 桩解析器和递归解析器可以根据情况选择使用 TCP 或者 UDP 查询直接请求目标服务器,以 UDP 协议来开始发起 DNS 请求不再是强制性的,TCP 协议与 UDP 协议在 DNS 查询中可以互相替代,而不是作为重试机制;
9.Specification for DNS over Transport Layer Security (TLS) Proposed Standard, 2016-05
  • 在 DNS 协议中引入 TLS 来为用户提供隐私,减少对 DNS 查询的窃听和篡改,但是 TLS 协议的引入会带来一些性能方面的额外开销;
10.RFC8484 · DNS Queries over HTTPS (DoH) Proposed Standard, 2018-10
  • 定义了一种通过 HTTPS 发送 DNS 查询和获取 DNS 响应的协议;
我们可以简单总结一下 DNS 的发展史,1987 年的 RFC1034 和 RFC1035 定义了最初版本的 DNS 协议,刚被设计出来的 DNS 就会同时使用 UDP 和 TCP 协议,对于绝大多数的 DNS 查询来说都会使用 UDP 数据报进行传输,TCP 协议只会在区域传输的场景中使用,其中 UDP 数据包只会传输最大 512 字节的数据,多余的会被截断;两年后发布的 RFC1123 预测了 DNS 记录中存储的数据会越来越多,同时也第一次显示的指出了发现 UDP 包被截断时应该通过 TCP 协议重试 。
为什么 DNS 使用 UDP 协议?

文章插图
过了将近 20 年的时间,由于互联网的发展,人们发现 IPv4 已经不够分配了,所以引入了更长的 IPv6,DNS 也在 2003 年发布的 RFC3596 中进行了协议上的支持;随后发布的 RFC5011 和 RFC6376 增加了在鉴权和安全方面的支持,但是也带来了巨大的 DNS 记录,UDP 数据包被截断变得非常常见 。
RFC6891 提供的 DNS 扩展机制能够帮助我们在一定程度上解决大数据包被截断的问题,减少了使用 TCP 协议进行重试的需要,但是由于最大传输单元的限制,这并不能解决所有问题 。
DNS 出现之后的 30 多年,RFC7766 才终于提出了使用 TCP 协议作为主要协议来解决 UDP 无法解决的问题,TCP 协议也不再只是一种重试时使用的机制,随后出现的 DNS over TLS 和 DNS over HTTP 也都是对 DNS 协议的一种补充 。
从这段发展时来看,DNS 并不只是使用 UDP 数据包进行通信,在 DNS 的标准中就一直能看到 TCP 协议的身影,我们在今天也是想要站在历史的角度上分析 ——『为什么 DNS 查询选择使用 UDP/TCP 协议』 。
设计在这一节中,我们将根据 DNS 使用协议的不同,分两个部分介绍 UDP 和 TCP 两种不同的协议在支持 DNS 查询和响应时有哪些优点和缺点,在分析的过程中我们也会结合历史上的上下文,还原做出设计决策时的场景 。
UDPUDP 协议在过去的几十年中其实都是 DNS 主要使用的协议,作为互联网的标准,目前的绝大多数 DNS 请求和响应都会使用 UDP 协议进行数据的传输,我们通过抓包工具就能轻松获得以 UDP 协议为载体的 DNS 请求和响应 。
DNS 请求的数据都会以二进制的形式封装成如下的所示的 UDP 数据包中,下面就是一个调用 DNS 服务器获取 www.baidu.com 域名 IP 地址的请求,从第四行的 05 字节开始到最后就是 DNS 请求的内容,整个数据包中除了 DNS 协议相关的内容之外,还包含以太网、IP 和 UDP 的协议头:
0000 b0 6e bf 6a 4c 40 38 f9 d3 ce 10 a6 08 00 45 00 .n.jL@8.......E.
0010 00 3b 97 ae 00 00 40 11 0b 0a c0 a8 32 6d 72 72 .;....@.....2mrr
0020 72 72 f3 27 00 35 00 27 6b ee 0c 5a 01 00 00 01 rr.'.5.'k..Z....
0030 00 00 00 00 00 00 03 77 77 77→05 62 61 69 64 75 .......www.baidu
0040 03 63 6f 6d 00 00 01 00 01 .com.....
虽然每一个 UDP 数据包中都包含了很多以太网、IP、UDP 以及 DNS 协议的相关内容,但是上面的 DNS 请求大小只有 73 个字节,上述 DNS 请求的响应也只有 132 个字节,这对于今天其他的常见请求来讲都是非常小的数据包:


推荐阅读