我们知道, 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 查询记录:
1 | #dig aaaaaaaaaa.test.chinatesters.com TXT @ns1.he.net |
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 协议的知识。