在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 additional record_wireshark


大体DNS报文格式就是这样。这里截屏没有权威和附加的资源记录。可以通过标红框上的信息看出

dns additional record_wireshark_02

每一类DNS报文都有一个首部部分。首部包括一些字段,用于规定其余部分是否存在,也是规定是查询还是响应,是标准查询还是其他类型的操作。

dns additional record_网络协议_03

首部后面是其他部分的名称来自它们在标准查询中的使用。问题部分包括的字段用于描述发送给服务器的问题(查询请求)。这些字段时查询类型、查询类和查询域名。

dns additional record_wireshark_04


回答部分包括问题的资源记录。权威部分包括指向权威DNS服务器的资源记录。

DNS报文的首部格式说明

查询报文和应答报文都具有相同的首部格式,查询报文主要是将某些字段设置为0,首部长度为12字节。

dns additional record_DNS_05


上图中显示了 DNS 的报文格式。其中,事务 ID、标志、问题计数、回答资源记录数、权威名称服务器计数、附加资源记录数这 6 个字段是DNS的报文首部,共 12 个字节。

dns additional record_wireshark_06


标志字段中每个字段的含义如下:

Response:查询请求/响应的标志信息。查询请求时,值为 0;响应时,值为 1。

Opcode:操作码。其中,0 表示标准查询;1 表示反向查询;2 表示服务器状态请求。

Authoritative:授权应答,该字段在响应报文中有效。值为 1 时,表示名称服务器是权威服务器;值为 0 时,表示不是权威服务器。

Truncated:表示是否被截断。值为 1 时,表示响应已超过 512 字节并已被截断,只返回前 512 个字节。

Recursion Desired:期望递归。该字段能在一个查询中设置,并在响应中返回。该标志告诉名称服务器必须处理这个查询,这种方式被称为一个递归查询。如果该位为 0,且被请求的名称服务器没有一个授权回答,它将返回一个能解答该查询的其他名称服务器列表。这种方式被称为迭代查询。

Recursion Available:可用递归。该字段只出现在响应报文中。当值为 1 时,表示服务器支持递归查询。

Z:保留字段,在所有的请求和应答报文中,它的值必须为 0。

问题部分格式说明

问题部分用在大多数查询报文中表达具体的查询问题,即定义要查什么。

dns additional record_网络协议_07


查询域名:是可变长字段。查询名称由标签序列构成,每个标签前有一个八位位组指出该标签的长度。因为每个域名以空标签结束,因此每个域名的最后一个八位位组的值为0.。

查询类型:两个八位位组代码,长度16位,它指定查询的类型。这个类型的值包括所有适用于资源记录类型。记录类型如下(信息参考:):

dns additional record_wireshark_08


dns additional record_网络_09


dns additional record_wireshark_10


查询类:两个八位位组代码,指定查询的类。例如:对于Internet,查询类字段值为1,其符号表示为IN。

资源记录格式说明

回答部分、权威部分和附加部分都是共享相同格式,就是可变数目的资源记录,其中记录的数目在首部相应计数字段中规定。只有应答报文才提供资源记录。

dns additional record_DNS_11

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: %s\n", 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 additional record_网络协议_12

dns additional record_网络协议_13

dns additional record_http_14


dns additional record_DNS_15

总结

在分析DNS报文时,可以使用nslookup工具来测试DNS解析,要获取DNS报文的详细数据信息,需要使用Wrieshark捕获DNS流量进行分析。