如何突破DNS报文的512字节限制

DNS协议大家都应该很熟悉,最近有同学问到如何获得UDP承载的超过512字节的DNS报文,借此机会,我们一起了解下DNS协议与报文长度有关的一些细节。


本文将讨论的是DNS协议在UDP承载时超过512字节的这一细节。
在之前的文章里,对DNS协议进行了介绍:

使用Wireshark进行DNS协议解析

Windows下的DNS命令用法


看完这两篇文章,大家应该对DNS协议有一些初步的了解。对DNS协议而言,在IETF网站上,能够很容易地获取到相关的RFC文档及扩展信息。


在大部分讲解DNS协议的文章里,都会这样描述DNS协议的特性:

当封装的DNS响应的长度超过512字节时,协议应采用TCP传输,而不是UDP。


根据协议标准文档RFC1035,这当然是对的,实际使用DNS协议的过程中,抓取的报文也确实是这样的,但是,不要忘记这份RFC文档产生于三十年前,这么多年,随着网络环境的变化,协议是会发展的,大家想想,网络上是不是到处都是超过512字节的UDP数据呀,那超过512字节的UDP DNS又有何不可?


RFC 6891这份标准文档,对DNS进行了扩展,描述了超过512字节的DNS的情况,即EDNS0。


本文将首先描述DNS协议的长度限制情况,然后对EDNS0进行说明,接着用示例说明DNS工具在超过512字节时的通常情况,最后将介绍如何方便地产生超过512字节的UDP承载的DNS报文。大家可以根据需要,跳到对应章节查阅。



01

DNS的512字节限制


根据协议标准,DNS协议同时占用UDP和TCP的53端口,这是为什么呢?


翻阅DNS资料,可以发现,DNS协议默认按UDP传输,为优化传输性能,DNS协议有一个512字节的限制,当数据长度超过了512字节时,DNS协议会改用TCP进行传输。


DNS协议从UDP切换到TCP的过程如下:

1、客户端向服务器发起UDP DNS请求;

2、如果服务器发现DNS响应数据超过512字节,则返回UDP DNS响应中置truncated位,告知客户端改用TCP进行重新请求;

3、客户端向服务器发起TCP DNS请求;

4、服务器返回TCP DNS响应。


那为什么限制是512字节呢?


一个说法是:IPV4标准规定了各个主机必须能够重组576字节或更少字节的数据包。具有512字节内容的DNS报文加上IP头和UDP头,将小于576字节。


02

EDNS0


EDNS0:即Extension Mechanisms for DNS (EDNS(0)),详细情况可参考RFC 6891这份文档。


EDNS0是随着网络的发展,在DNS消息格式和它支持的消息内容已不足以满足一些DNS服务器的需求的情况下被提出的,它用于传递包大小,扩展了DNS协议。


EDNS0是在遵循已有的DNS消息格式的基础上增加一些字段,来支持更多的DNS请求业务。当然,具备向后兼容性,未支持EDNS0的旧的DNS服务器仍然能够很好地处理EDNS0。


EDNS0特征如下:

扩展DNS使用UDP传输时的最大报文限制,可以超过512字节 

扩展RCODE,由4为增加到12位 

建议利用域名标签类型的剩余两个


我们在这里关注的是ENDS0突破DNS 512字节限制的能力。


DNS协议在发起请求时,通过在Additional部分增加OPT RR字段,告知服务器能处理的最大UDP报文长度,当服务器准备进行回应时,如果响应数据大于该值,则在DNS协议中置truncated位,否则,可发送小于该值大小的报文。这相当于突破了512字节的长度限制。


在ENDS0标准文档中,很容易找到OPT RR字段的格式:

640?wx_fmt=png


各字段如下:

NAME:目前为空

TYPE:OPT RR的类型编号,41

CLASS:最大UDP报文长度

TTL:扩展的DNS消息头部

RDLEN:紧接着的RDATA的长度

RDATA:可变部分数据。


RDATA格式如下:

640?wx_fmt=png

说明如下:

OPTION-CODE:由IANA分配

OPTION-LENGTH:OPTION-DATA的长度

OPTION-DATA:具体内容


而TTL则是用来存储扩展消息头部中的RCODE和flags,格式如下:

640?wx_fmt=png

说明如下:

EXTENDED-RCODE:扩展RCODE(返回状态码),这8个bit加上DNS头部的4bit总共有12bit(8bit在高位),这样就可以表示更多的返回类型

VERSOION:EDNS的版本

DO:DNSSEC OK,见相关RFC文档定义

Z:一般被发送者设置为0,接收方可以忽略它


因此,只要在进行DNS请求时,设置了OPT RR的CLASS值,则当响应超过了512字节,但未超过该值时,会仍然使用UDP进行传输。


03


DNS超过512字节时常规交互


在进行示例之前,我们首先要找到能够产生超过512字节DNS报文的域名及DNS服务器。这是由于大部分的DNS响应都不会很长,而同时,不同的DNS服务器缓存的DNS数据是有差异的。


经过搜集,我们选取了微软的DNS服务器之一:208.84.2.53,同时,选取了进行示例的域名:outlook.com。


常规的DNS请求,不会设置OPT RR的CLASS值,因此会默认在DNS报文大于512字节时,换用TCP传输。


常规DNS交互的实力,选择使用windows自带的nslookup服务进行,命令如下:

nslookup -qt=ANY outlook.com 208.84.2.53


使用Wireshark抓包可看到报文如下:

640?wx_fmt=png


可以看到,DNS在UDP传输之后自动进行了TCP DNS请求,响应体长度达到1010字节。


自动进行的关键是UDP的DNS响应报文里给truncated进行了置位:

640?wx_fmt=png


因此,我们只需要找到超过512字节DNS响应的域名及DNS服务器,就能很容易获取到DNS TCP的报文。


04


DNS突破UDP 512字节限制


对于超过512字节的DNS UDP报文,就不是那么容易获得的。一个简单的办法是,到骨干网络上去抓包,抓取DNS服务器之间的DNS同步报文。当然,对很多分析DNS协议的朋友,这不现实。


这里,将介绍一种在PC上产生超过512字节的UDP DNS报文的办法。


使用的仍然是前一节的DNS域名和服务器。


这里,需要找到设置DNS协议的OPT RR的CLASS值的方法,很幸运,有这样的工具存在,即dig这个小工具,一款Linux下用于查看域名详情的小工具,类似于nslookup,但功能更强大。dig也存在Windows版,它包含在BIND工具包中,BIND工具包可以在BIND官网下载,地址如下:https://www.isc.org/downloads/


在页面下方即可找到BIND各个版本的下载按钮。


下载好bind包,解压后,直接命令行进入解压目录,即可使用dig进行DNS请求,为构造UDP的DNS大包,设置了参数+notcp以及+bufsize=1400

dig.exe @208.84.2.53 outlook.com ANY IN +notcp +bufsize=1400


wireshark获取到报文如下:

640?wx_fmt=png

没有从UDP跳转为TCP进行DNS请求,而是直接在UDP中返回了完整的DNS数据。


其中请求如下:

640?wx_fmt=png


在OPT RR中,设置了UDP的payload size 1400。


响应如下:

640?wx_fmt=png

响应体达1031字节。


很容易地,就设置了DNS协议的OPT RR的CLASS值。从而获得了超过512字节的UDP承载的DNS协议报文。


05


总结


只要找到合适的方法,就能很方便地突破DNS协议的UDP 512字节限制。如果有什么疑问,可以随时联系我。

640?wx_fmt=jpeg

长按进行关注。





原文地址:https://www.cnblogs.com/protosec/p/11673326.html