DNS为什么使用UDP,又与TCP有什么关系

Posted by JimWang on 2021-02-19

DNS为什么使用UDP,又与TCP有什么关系

为什么用UDP

DNS请求数据时,整个数据包除了DNS协议相关的内容之外,还包含以太网、IP和UDP的协议头。虽然包含了这么多信息,但是一个DNS请求只有几十个字节。是非常小的数据包。

UDP 和 TCP 的通信机制非常不同,作为可靠的传输协议,TCP 协议需要通信的双方通过 三次握手 建立 TCP 连接后才可以通信,但是在 30 年前的 DNS 查询的场景中我们其实并不需要稳定的连接(或者以为不需要),每一次 DNS 查询都会直接向命名服务器发送 UDP 数据报,与此同时常见 DNS 查询的数据包都非常小,TCP 建立连接会带来以下的额外开销:

TCP 建立连接需要进行三次网络通信;
TCP 建立连接需要传输 ~130 字节的数据;
TCP 销毁连接需要进行四次网络通信;
TCP 销毁连接需要传输 ~160 字节的数据;

跟TCP的关系

今天的网络状况其实没有几十年前设计的那么简单,我们不仅遇到了 IPv4 即将无法分配的状况,而且还需要引入 DNSSEC 等机制来保证 DNS 查询和请求的完整性以及传输安全,总而言之,DNS 协议需要处理的数据包越来越大、数据也越来越多,但是『为什么当需要传输的数据较多时我们就必须使用 TCP 协议呢?』

从理论上来说,一个 UDP 数据包的大小最多可以达到 64KB,这对于一个常见的 DNS 查询其实是一个非常大的数值;但是在实际生产中,一旦数据包中的数据超过了传送链路的最大传输单元(MTU,也就是单个数据包大小的上限,一般为 1500 字节),当前数据包就可能会被分片传输、丢弃,部分的网络设备甚至会直接拒绝处理包含 EDNS(0) 选项的请求,这就会导致使用 UDP 协议的 DNS 不稳定。

TCP 作为可靠的传输协议,可以非常好的解决这个问题,通过序列号、重传等机制能够保证消息的不重不漏,消息接受方的 TCP 栈会对分片的数据重新进行拼装,DNS 等应用层协议可以直接使用处理好的完整数据。同时,当数据包足够大的时候,TCP 三次握手带来的额外开销比例就会越来越小,与整个包的大小相比就会趋近于 0。

总结

DNS 查询选择 UDP 或者 TCP 两种不同协议时的主要原因:

  • UDP 协议
    • DNS 查询的数据包较小、机制简单;
    • UDP 协议的额外开销小、有着更好的性能表现;
  • TCP 协议
    • DNS 查询由于 DNSSEC 和 IPv6 的引入迅速膨胀,导致 DNS 响应经常超过 MTU 造成数据的分片和丢失,我们需要依靠更加可靠的 TCP 协议完成数据的传输;
    • 随着 DNS 查询中包含的数据不断增加,TCP 协议头以及三次握手带来的额外开销比例逐渐降低,不再是占据总传输数据大小的主要部分;

无论是选择 UDP 还是 TCP,最核心的矛盾就在于需要传输的数据包大小,如果数据包小到一定程度,UDP 协议绝对最佳的选择,但是当数据包逐渐增大直到突破 512 字节以及 MTU 1500 字节的限制时,我们也只能选择使用更可靠的 TCP 协议来传输 DNS 查询和相应。

转载自:https://draveness.me/whys-the-design-dns-udp-tcp/