关于DNS TCP和UDP那些事

关于DNS你需要了解的不只是搭建权威DNS、域名层次级别、递归查询,你还需要了解报文格式和TCP/UDP协议。

背景资料:购买了两台云服务器配合内网负载均衡搭建了一套高可用的权威DNS架构(其实如果是DNS的话本来可以使用主备模式,不需要再使用负载均衡进行高可用)。

  • 权威DNS使用的是bind来构建,只解析自己的域名,其他的域名还是通过云厂商的DNS服务器进行递归查询。

  • 使用的是四层轮询负载模式,开启了健康检查,监听了UDP53号端口。

经过的排查:
  • 直接绕过负载均衡直接使用权威DNS进行解析。 可以通

  • 解析其他外网域名例如baidu.com。 可以通

  • 查看后端监听是否有UDP53,健康检查状态是否正常 正常

  • 解析 **单独唯一一个报错(某第三方公司提供的服务) ** 不能通

解决问题最好的办法就是抓包:
image
  • 其实看到这个问题的时候很奇怪DNS使用UDP报文为什么会出现S 标志位?这不是TCP协议的吗?

现在进行大胆猜想

数据到达了传输层,而且目测是正常的。得到了包但是还是报错。我猜测是应用层的问题(DNS配置或者DNS BUG)。

现在进行小心求证

我们根据它的架构模式来搭建简单的DNS,涉及产品CLB,CVM,VPC

  • 网络通讯架构模式

    • 内网Client(无hosts指定)访问CLB,CLB四层转发到DNS2,DNS2去DNS1,DNS经过NAT网关访问指定的腾讯云提供的DNS服务。
    
    graph LR
    
    A[Client] --> B[CLB]
    
    B-->D[DNS2]
    
    D-->E
    
    B-->E[DNS1]
    
    E-->F[NAT GETWAY]
    
    F-->G[CloudSerDo]
    
    
  • 购买机器、基本配置CLB、NAT、安装配置DNS就不再进行赘述了。

  • 通过搭建DNS、添加域名A记录 dns2.lqhtest.com,来看一下DNS报文不超过512个字节的响应情况

  • 通过上图我们可以对DNS协议分析得到以下结论:

    • 正常的响应包使用的UDP进行传输。

    • Flags标签位中的Truncated截断位表示并未被截断。

    • 相应包返回的解析IP地址只有一个为10.2.1.13

  • 我们再来看看DNS报文大小超过512字节时的特殊响应情况。

image
  • 根据上图我们可以得到的信息有:

    • DNS块报文大小超过了512字节。

    • Flags标志位中信息截断位为1被截断。

    • 在应用层DNS收到这个被截断的报文后,主动与DNS服务器重新使用TCP建立会话,进行通讯。

    • 来看看这个由TCP和UDP维护的DNS请求报文内容。

image
  • 对比下响应报文。
image
分析和总结

当名字解释器发出一个查询请求,并且返回响应中的TC(删减标志)比特被设置为1时,它就意味着响应的长度超过了512个字节,而仅返回前512个字节。在遇到这种情况时,名字解释器通常使用TCP重发原来的查询请求,它将允许返回的响应超过512个字节。-------引用自TCP/IP协议一卷 翻译版14章DNS域名系统。

  • 那么可以得出响应的总结了:

    • 如果DNS报文内容大于512个字节,那么DNS在收到这个报文内容时,发现Flags标志位中的信息截断被标识为1,那么客户端会再次会主动的向DNS服务器发起TCP连接会话请求,在成功建立起TCP会话请求后并再次向服务器发送域名解析请求,DNS服务器在接收到后并同样返回使用TCP封装的DNS报文。
自问自答
  • UDP数据包理论能够承载多少数据报?

    • 理论上支持的公式为:IP数据报最大长度(排除IP选项部分) - IP首部 - UDP首部 = UDP数据报数据最大长度推算则为:65535-20-8=65507(字节),UDP理论支持的数据最大为:65507字节。
  • 为什么DNS只能接收512个字节的UDP数据报文?

    来自TCP/IP协议详解卷一(第一版)-第十一章
    我们在3.2节中提过,要求主机必须能够接收最短为576字节的IP数据报。在许多UDP应用程序的设计中,其应用程序数据被限制成512字节或更小,因此比这个限制值小。例如,我们在10.4节中看到,路径信息协议总是发送每份数据报小于512字节的数据。我们还会在其他 UDP应用程序如DNS(第14章)、TFTP(第15章)、BOOTP(第16章)以及SNMP(第25章)中遇到这个限制。

    来自TCP/IP协议详解卷一(第二版)-第五章Internet协议-IP头部字段126页
    尽管可发送一个65535字节的IP数据报,但大多数据链路层(例如以太网)不能携带这么大的数据,除非将它拆分成更小的片。另外,主机必需要接收大于576字节的IPv4数据报。(在IPv6中,主机需要能处理所在链路MTU大小的数据报,而最小链路为1280字节。)很多使用UDP协议传输数据(如DNS、DHCP等)的应用程序,限制为使用512字节大小的数据,以避免576字节的IPv4限制。
    (不推荐大家读这一版。这版本翻译有问题,读起来奇奇怪怪的。)

来自RFC-791 https://tools.ietf.org/html/rfc791
Total Length: 16 bits
Total Length is the length of the datagram, measured in octets,including internet header and data. This field allows the length ofa datagram to be up to 65,535 octets. Such long datagrams are impractical for most hosts and networks. All hosts must be prepared to accept datagrams of up to 576 octets (whether they arrive whole or in fragments). It is recommended that hosts only send datagrams larger than 576 octets if they have assurance that the destination is prepared to accept the larger datagrams. The number 576 is selected to allow a reasonable sized data block to be transmitted in addition to the required header information. For example, this size allows a data block of 512 octets plus 64 header,octets to fit in a datagram. The maximal internet header is 60 octets, and a typical internet header is 20 octets, allowing a margin for headers of higher level protocols.

总长度(Total Length):16位
总长度是数据报的总长度,以字节(octets)为单位计量,包含internet头部和数据.这个头部允许一个数据报的长度最长到65535个字节.如此长的数据报对大部分主机和网络来说是不现实的. 所有主机必须能够接收长达576个字节的数据报(不管他们是以整个数据报到达还是以分片到达).推荐主机在确认目的地址能够接收大数据报的情况下才发送大于576字节的数据报.
选择576这个数字是为了允许传送一个合理大小的数据块,除了要求的头部信息之外.比如,这个大小允许512个字节的数据块加上64个字节的头部填充于一个数据报.最大的internet头部是60个字节,通常internet头部是20个字节,允许高层协议流出一个头部富余量.

  • 因为这是DNS自己来进行限制的。与此需要注意的还有TFTP、BOOTP、SNMP。都是在应用端进行了限制。
解决方法
  • 知道原理后就知道如何进行解决了,居然是客户端在解析报文得到被截断标志位后会重新改为TCP进行传输,那么只需要在负载均衡上面设置转发后端TCP53端口即可。

你可能感兴趣的:(关于DNS TCP和UDP那些事)