我们知道, DNS 是同时占用 UDP 和 TCP 的 53 端口传输数据的,这种单个应用协议同时使用两种传输协议的情况,在 TCP/IP 栈中也算是个异类。
当我们在使用 tcpdump 、 WireShark 等抓包工具分析时,会发现几乎所有的 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
我们来做个测试:
将 chinatesters.com 配置一个子域名 test , NS 指向 He.net 的域名服务器。如图所示:
将 test.chinatesters.com 添加到 He.net 的域名控制面板,并添加一条 TXT 记录,值为11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111(长度: 768 )。如下图:
配置生效后,使用 tcpdump 跟踪本地网卡的 53 端口,同时新开窗口用 dig 命令直接向 ns1.he.net 请求查询该 TXT 记录。
DNS 查询记录:
123456789101112131415161718192021#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 网卡跟踪记录:
查询记录结果的第一句便提示了 Truncated, retrying in TCP mode. ,表示启用了 TCP 协议查询。
网卡抓包也展示了 seq 、 ack 等 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 协议的知识。
参考资料
《计算机网络(第五版)》.谢希仁
RFC 1034
RFC 1035