什么情况下 DNS 会使用 TCP 传输协议?

我们知道, DNS 是同时占用 UDP 和 TCP 的 53 端口传输数据的,这种单个应用协议同时使用两种传输协议的情况,在 TCP/IP 栈中也算是个异类。

当我们在使用 tcpdump 、 WireShark 等抓包工具分析时,会发现几乎所有的 DNS 应用都是在使用 UDP 传输。

DNS查询使用UDP协议传输

那么,为什么 DNS 还要占用 TCP 的端口,到底什么情况下才会用到 TCP 呢?


一点基础知识

TCP 全称 Transmission Control Protocol (传输控制协议), UDP 全称 User Data Protocol (用户数据报协议),它们都是 OSI 七层模型中的传输层协议。灰姑娘大学时是网络工程专业的学渣,虽没学到个啥,但好巧不巧,就记得某些考题逢考必有。比如:

TCP 和 UDP 的区别

特性 TCP UDP
连接性 三次握手 不需要建立连接
可靠性 可靠,丢包会自动重传 不可靠
有序性 会对传输乱序的消息重新排列 可能乱序
传输速度 慢,因为要建立连接并保证可靠和有序
传输及控制 通过字节流传输,无界,有拥塞控制机制(慢开始、拥塞避免、快重传、快恢复) 数据包都是单独的,有界,不作拥塞控制
资源消耗 需要更多资源以传递更多信息,包头比较大(需要 20 字节) 头部只需 8 个字节

通过上述区别,我们不难看出, TCP 主要应用在对可靠性比较高的场合,比如 Telnet 、 FTP 等;而 UDP 主要应用于实时性较高的场合,例如即时聊天。

DNS 查询用的传输协议

前面提到,一般我们看到的绝大多数 DNS 查询是用的 UDP 传输。

域名解析时大多使用 UDP 协议

客户端在请求一个域名的解析结果时,实际上需要经过重重 DNS 查询。(对 DNS 不太了解的童鞋可以先学下这个:转载:从理论到实践,全方位认识DNS(理论篇)

一方面,要保证用户端的快速响应, TCP 的三次握手则过于繁冗;另一方面, DNS 解析查询即使出现异常,网民用户大不了重新申请一次查询,因而对可靠性的要求并没有那么高。

所以日常的域名解析需求使用 UDP 传输即可。

具备特殊要求的域名解析使用 TCP 协议

由于UDP是按照数据包来传输的,整个包最大只能 512 字节。一般正常情况下,用来 DNS 查询是绰绰有余的。但当解析配置过于复杂,或者记录值过长(如: TXT 、 RRSIG 记录)使得 UDP 无法承载的情况下,就有必要转换 TCP 查询。

由于基于 TCP 的域名解析非常少见,大多数域名厂商是不支持的, CloudXNS 也不例外。然而同域名同主机同线路的同类型解析将会封装到一个 UDP 包传输,如果内容过多(超过 512 字节),该数据包可能会承载不下。

这也是为什么 CloudXNS 中即使 A 、 TXT 、 MX 等类型记录尽管不与自身互斥,我们仍然会对同域名下同一主机同一线路限制解析记录条数的原因。

当然,国外的一些域名解析商这方面可能比我们严谨些,还是有一部分厂家是支持当数据过长时转用 TCP 传输的。比如:He.Net

我们来做个测试:

  1. chinatesters.com 配置一个子域名 test , NS 指向 He.net 的域名服务器。如图所示:
    子域 DNS 配置
  2. test.chinatesters.com 添加到 He.net 的域名控制面板,并添加一条 TXT 记录,值为11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111(长度: 768 )。如下图:
    超长 TXT 记录配置
  3. 配置生效后,使用 tcpdump 跟踪本地网卡的 53 端口,同时新开窗口用 dig 命令直接向 ns1.he.net 请求查询该 TXT 记录。

DNS 查询记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#dig aaaaaaaaaa.test.chinatesters.com TXT @ns1.he.net
;; Truncated, retrying in TCP mode.

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.47.rc1.el6 <<>> aaaaaaaaaa.test.chinatesters.com TXT @ns1.he.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56555
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;aaaaaaaaaa.test.chinatesters.com. IN TXT

;; ANSWER SECTION:
aaaaaaaaaa.test.chinatesters.com. 300 IN TXT "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" "011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" "101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" "11"

;; Query time: 221 msec
;; SERVER: 216.218.130.2#53(216.218.130.2)
;; WHEN: Tue Jul 18 13:58:50 2017
;; MSG SIZE rcvd: 833

tcpdump 网卡跟踪记录:

tcpdump 网卡跟踪

查询记录结果的第一句便提示了 Truncated, retrying in TCP mode. ,表示启用了 TCP 协议查询。

网卡抓包也展示了 seqack 等 TCP 协议中的三次握手过程,最后返回了域名 aaaaaaaaaa.test.chinatesters.com. 的 TXT 记录值。

事实上,根据 RFC 1035 章节 4.2 ,DNS 解析查询优先使用 UDP ,当 UDP 完成不了的情况下,则转换 TCP 查询。上述展示的就是这样的实例。

当看完 RFC 的这一章节,我们会发现,基于 TCP 协议的 DNS 应用还有一个更重要的作用。

DNS 区域传送(zone-transfer)

由于 DNS 服务器作为互联网基础设施,一般都会分布式的设置多台冗余备份,各个域名的配置在多个服务器之间的同步过程便被称之为区域传送。我在过去的文章《隔壁粗事了!朝鲜顶级域 .kp 域名 DNS 数据配置可被转移》中提到过“区域传送”的概念,不太了解的童鞋可先查看下。

区域传送时,辅域名服务器将向主服务器拉取数据。该数据同步传送的量往往比较大且不容有失,该操作没有较高的时效性要求只需要隔段时间定时执行一遍即可。所以必须采用可靠性高的 TCP 传输协议

CloudXNS 的 NS 服务器间的区域同步技术是公司自研的一套机制,虽然亦是使用的 TCP 传输,但由于专利技术保密,不便提供示例。下次咱们大概可以在搭建一套开源的 DNS 服务器的折腾过程中再引申下关于区域传送时应用 TCP 协议的知识。

参考资料

  1. 《计算机网络(第五版)》.谢希仁
  2. RFC 1034
  3. RFC 1035

文章目录
  1. 1. 一点基础知识
    1. 1.1. TCP 和 UDP 的区别
  2. 2. DNS 查询用的传输协议
    1. 2.1. 域名解析时大多使用 UDP 协议
    2. 2.2. 具备特殊要求的域名解析使用 TCP 协议
  3. 3. DNS 区域传送(zone-transfer)
  4. 4. 参考资料