为什么 DNS 使用 UDP 协议
The following article is from 真没什么逻辑 Author Draveness
概述
RFC1034 · Domain Names - Concepts and Facilities Internet Standard, 1987-11 DNS 查询可以通过 UDP 数据包或者 TCP 连接进行传输; 由于 DNS 区域传输的功能对于数据的准确有着较强的需求,所以我们必须使用 TCP 或者其他的可靠协议来处理 AXFR 类型的请求; RFC1035 · Domain Names - Implementation and Specification 互联网支持命名服务器通过 TCP 或者 UDP 协议进行访问; UDP 协议携带的消息不应该超过 512 字节,超过的消息会被截断并设置 DNS 协议的 TC
位,UDP 协议对于区域传输功能是不可接受的,不过是互联网上标准查询的推荐协议。通过 UDP 协议发送的查询可能会丢失,所以需要重传策略解决这个问题;RFC1123 · Requirements for Internet Hosts -- Application and Support Internet Standard, 1989-10 未来定义的新 DNS 记录类型可能会包含超过 512 字节的信息,所以我们应该使用 TCP 协议来传输 DNS 记录;因此解析器和命名服务需要使用 TCP 协议作为 UDP 无法满足需求时的备份; DNS 解析器和递归服务器必须支持 UDP 协议,并且应该支持使用 TCP 协议发送非区域传输的查询;也就是说,DNS 解析器或者服务器在发送非区域传输查询时,必须先发送一个 UDP 查询,如果该查询的响应被截断,它应该尝试使用 TCP 协议重新请求; RFC3596 · DNS Extensions to Support IP Version 6 Internet Standard, 2003-10 通过 DNS 扩展支持 IPv6 协议,每个 IPv6 占 16 个字节是 IPv4 的四倍; RFC5011 · Automated Updates of DNS Security (DNSSEC) Trust Anchors Independent, 2007-10 新增多种资源记录为 DNS 客户端的 DNS 数据来源进行认证,记录包含的数据往往较大; RFC6376 · DomainKeys Identified Mail (DKIM) Signatures Internet Standard, 2011-09 选择合适的键大小进行加密是需要在成本、性能和风险之间的权衡,然而大的键(4096-bit)可能没有办法直接放到 DNS UDP 响应包中直接返回; RFC6891 · Extension Mechanisms for DNS (EDNS(0)) Internet Standard, 2013-04 使用 UDP 进行传输的 DNS 查询和响应最大不能超过 512 字节,不能支持大量 IPv6 地址或者 DNS 安全签名等记录的传输; EDNS 为 DNS 提供了扩展功能,让 DNS 通过 UDP 协议携带最多 4096 字节的数据; RFC7766 · DNS Transport over TCP - Implementation Requirements Proposed 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 查询中可以互相替代,而不是作为重试机制; Specification for DNS over Transport Layer Security (TLS) Proposed Standard, 2016-05 在 DNS 协议中引入 TLS 来为用户提供隐私,减少对 DNS 查询的窃听和篡改,但是 TLS 协议的引入会带来一些性能方面的额外开销; RFC8484 · DNS Queries over HTTPS (DoH) Proposed Standard, 2018-10 定义了一种通过 HTTPS 发送 DNS 查询和获取 DNS 响应的协议;
设计
UDP
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.....
0000 38 f9 d3 ce 10 a6 b0 6e bf 6a 4c 40 08 00 45 00 8......n.jL@..E.
0010 00 76 00 00 00 00 96 11 4c 7d 72 72 72 72 c0 a8 .v......L}rrrr..
0020 32 6d 00 35 f3 27 00 62 5b c2 0c 5a 81 80 00 01 2m.5.'.b[..Z....
0030 00 03 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 c0 0c 00 05 00 01 00 .com............
0050 00 02 cb 00 0f 03 77 77 77 01 61 06 73 68 69 66 ......www.a.shif
0060 65 6e c0 16 c0 2b 00 01 00 01 00 00 01 18 00 04 en...+..........
0070 3d 87 a9 7d c0 2b 00 01 00 01 00 00 01 18 00 04 =..}.+..........
0080 3d 87 a9 79 =..y
TCP 建立连接需要进行三次网络通信; TCP 建立连接需要传输 ~130 字节的数据; TCP 销毁连接需要进行四次网络通信; TCP 销毁连接需要传输 ~160 字节的数据;
使用 TCP 协(共 330 字节) 三次握手 — 14x3(Ethernet) + 20x3(IP) + 44 + 44 + 32 字节 查询协议头 — 14(Ethernet) + 20(IP) + 20(TCP) 字节 响应协议头 — 14(Ethernet) + 20(IP) + 20(TCP) 字节 使用 UDP 协议(共 84 字节) 查询协议头 — 14(Ethernet) + 20(IP) + 8(UDP) 字节 响应协议头 — 14(Ethernet) + 20(IP) + 8(UDP) 字节
需要注意的是,我们在这里计算结果的前提是 DNS 解析器只需要与一个命名服务器或者权威服务器进行通信就可以获得 DNS 响应,但是在实际场景中,DNS 解析器可能会递归地与多个命名服务器进行通信,这也加倍地放大了 TCP 协议在额外开销上的劣势。
TCP
当 DNS 数据包大小为 500 字节时,TCP 协议的额外开销为 ~41.2%; 当 DNS 数据包大小为 1100 字节时,TCP 协议的额外开销为 ~20.7%; 当 DNS 数据包大小为 2300 字节时,TCP 协议的额外开销为 ~10.3%; 当 DNS 数据包大小为 4800 字节时,TCP 协议的额外开销为 ~5.0%;
总结
DNS 在设计之初就在区域传输中引入了 TCP 协议,在查询中使用 UDP 协议; 当 DNS 超过了 512 字节的限制,我们第一次在 DNS 协议中明确了『当 DNS 查询被截断时,应该使用 TCP 协议进行重试』这一规范; 随后引入的 EDNS 机制允许我们使用 UDP 最多传输 4096 字节的数据,但是由于 MTU 的限制导致的数据分片以及丢失,使得这一特性不够可靠; 在最近的几年,我们重新规定了 DNS 应该同时支持 UDP 和 TCP 协议,TCP 协议也不再只是重试时的选择;
UDP 协议 DNS 查询的数据包较小、机制简单; UDP 协议的额外开销小、有着更好的性能表现; TCP 协议 DNS 查询由于 DNSSEC 和 IPv6 的引入迅速膨胀,导致 DNS 响应经常超过 MTU 造成数据的分片和丢失,我们需要依靠更加可靠的 TCP 协议完成数据的传输; 随着 DNS 查询中包含的数据不断增加,TCP 协议头以及三次握手带来的额外开销比例逐渐降低,不再是占据总传输数据大小的主要部分;
如何对使用 TCP 协议的 DNS 进行一些优化,减少一些额外开销? 我们现在已经可以使用 UDP/TCP/TLS/HTTPS 四种方式传输 DNS 数据,这些方式有什么异同?是否还可以通过其他的协议实现 DNS 查询?
Reference
详解 DNS 与 CoreDNS 的实现原理
DNS Transport over TCP - Implementation Requirements · RFC7766
DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION · RFC1035
DNS Stateful Operations · RFC8490
When do DNS queries use TCP instead of UDP?
Domain Name System
DNS zone transfer
Extension Mechanisms for DNS (EDNS(0)) · RFC6891
How much data it cost to set up a TCP connection?
后台回复“加群”,带你进入高手如云交流群
推荐阅读:
10T 技术资源大放送!包括但不限于:云计算、虚拟化、微服务、大数据、网络、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公众号内回复「1024」,即可免费获取!!