在Internet上,DNS可以使用UDP,也可以使用TCP,在两种情况下,DNS服务器使用的公认端口是53。
DNS报文封装在UDP数据报或TCP数据段中,然后封装在IP数据报中,最后封装成数据链路层中的帧通过物理层传输。
DNS报文结构有哪些类型
DNS报文可以分为查询和应答,他们的总体结构是相同的。DNS的顶层格式分成5个部分:
1、首部(Header)
2、问题(Question)
3、回答(Answer)
4、权威(Authority)
5、附加(Additional)
大体DNS报文格式就是这样。这里截屏没有权威和附加的资源记录。可以通过标红框上的信息看出
每一类DNS报文都有一个首部部分。首部包括一些字段,用于规定其余部分是否存在,也是规定是查询还是响应,是标准查询还是其他类型的 *** 作。
首部后面是其他部分的名称来自它们在标准查询中的使用。问题部分包括的字段用于描述发送给服务器的问题(查询请求)。这些字段时查询类型、查询类和查询域名。
回答部分包括问题的资源记录。权威部分包括指向权威DNS服务器的资源记录。
DNS报文的首部格式说明
查询报文和应答报文都具有相同的首部格式,查询报文主要是将某些字段设置为0,首部长度为12字节。
上图中显示了 DNS 的报文格式。其中,事务 ID、标志、问题计数、回答资源记录数、权威名称服务器计数、附加资源记录数这 6 个字段是DNS的报文首部,共 12 个字节。
标志字段中每个字段的含义如下:
Response:查询请求/响应的标志信息。查询请求时,值为 0;响应时,值为 1。
Opcode: *** 作码。其中,0 表示标准查询;1 表示反向查询;2 表示服务器状态请求。
Authoritative:授权应答,该字段在响应报文中有效。值为 1 时,表示名称服务器是权威服务器;值为 0 时,表示不是权威服务器。
Truncated:表示是否被截断。值为 1 时,表示响应已超过 512 字节并已被截断,只返回前 512 个字节。
Recursion Desired:期望递归。该字段能在一个查询中设置,并在响应中返回。该标志告诉名称服务器必须处理这个查询,这种方式被称为一个递归查询。如果该位为 0,且被请求的名称服务器没有一个授权回答,它将返回一个能解答该查询的其他名称服务器列表。这种方式被称为迭代查询。
Recursion Available:可用递归。该字段只出现在响应报文中。当值为 1 时,表示服务器支持递归查询。
Z:保留字段,在所有的请求和应答报文中,它的值必须为 0。
问题部分格式说明
问题部分用在大多数查询报文中表达具体的查询问题,即定义要查什么。
查询域名:是可变长字段。查询名称由标签序列构成,每个标签前有一个八位位组指出该标签的长度。因为每个域名以空标签结束,因此每个域名的最后一个八位位组的值为0.。
查询类型:两个八位位组代码,长度16位,它指定查询的类型。这个类型的值包括所有适用于资源记录类型。记录类型如下(信息参考:https://www.cnblogs.com/bonelee/p/7611941.html):
查询类:两个八位位组代码,指定查询的类。例如:对于Internet,查询类字段值为1,其符号表示为IN。
资源记录格式说明
回答部分、权威部分和附加部分都是共享相同格式,就是可变数目的资源记录,其中记录的数目在首部相应计数字段中规定。只有应答报文才提供资源记录。
Name:可变长字段,指该资源记录匹配的域名。它实际上就是查询报文问题部分查询名称的副本,但由于在域名重复出现的地方DNS使用压缩,这个字段就是到查询报文问题部分中的相应域名的指针偏移。
Type:两个八位位组代码,长度16位,指定资源记录的类型,说明RDATA字段中数据意义。该字段与问题部分的查询类型字段相同。
Class:两个八位位组,指定RDATA字段中数据的类,与问题部分的查询类字段相同。
TTL:生成时间,32位无正负号整数,指定资源记录可以被缓存时间,单位是秒。值为0表示资源记录仅能用于正在进行的业务,不能被缓存。
Data length:资源数据长度,无符号16位整数,指定RDATA字段长度,以八位位组为字节。
资源数据:可变长字段,是资源记录的具体内容。其格式取决于资源记录的TYPE和CLASS字段。
资源数据格式种类包含如下:
- 数字:八位位组表示数,例如,IPv4地址是4个八位组整数,而IPv6地址是一个16个八位组整数。
- 域名:可用标签序列来表示。每一个标签前面有1个字节长度字段,它定义标签中的字段数。长度字段的两个高位永远是0,标签的长度不能超过63字节。
- 偏移指针:域名可以用偏移指针来替换。偏移指针是2字节字段,它的两个高位置为1
- 字符串:用1字节的长度字段后面跟着长度字段数。长度字段并不像域名长度字段那样受限。字符串可以多达256个字符。
DNS报文传输
- 使用UDP进行传输
使用UDP用户服务器端口53发送消息。由UDP携带的DNS报文长度被限制在512字节之内,其中不包括IP首部或UDP首部。较长的DNS报文被截断,TCP字段在首部中被设置为1。
UDP是DNS的Internet标准查询的推荐方式,但不包括区域传输。使用UDP发送的查询可能丢失,因此需要考虑传策略。查询或查询的应答可能由网络重新排序,或者经DNS服务器处理过,因此解析程序不能依赖按顺序返回的应答。
- 使用TCP进行传输
通过TCP传输的DNS报文使用两个字节长度字段做前缀。这个长度字段给出报文长度,计算长度不包括这个长度字段。该长度字段使得在开始解析报文之前,底层处理能够组装好完整的报文。
DNS协议解析
int main(int argc, char *argv[]) { char errbuf[100]; pcap_t *desc = 0; char *filename = argv[1]; if (argc != 2) { printf("usage: ./dissect_pppoe [pcap file]n"); return -1; } printf("ProcessFile: process file: %sn", filename); if ((desc = pcap_open_offline(filename, errbuf)) == NULL) { printf("pcap_open_offline: %s error!n", filename); return -1; } pcap_loop(desc, -1, got_packet, NULL); pcap_close(desc); return 0; }
总结
在分析DNS报文时,可以使用nslookup工具来测试DNS解析,要获取DNS报文的详细数据信息,需要使用Wrieshark捕获DNS流量进行分析。
欢迎关注微信公众号【程序猿编码】,需要DNS完整源码和报文的添加本人微信号(c17865354792)
参考:RFC 973、RFC 1886
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)