抓迅雷的包,发现迅雷整了N多和下载无关的东西,比如kankan,games啥的,启动的时候发了一堆DNS请求来解析这些整合的东西。于是学习了一下DNS报文的结构DNS请求报文的结构是0151631标识ID标志问题数资源记录数授权资源记录数额外资源记录数查询问题回答授权信息额外信息其中,后面四个字段的长度可变,它们各自的字节数也不一定是4的倍数。标识ID:有发出DNS请求的客户端生成,对应的DNS响应报文中也要置同样的ID。16bit的标志字段如下:QR:0表示查询报文,1表示响应报文Opcode:通常值为0(标准查询),其他值为1(反向查询)和2(服务器状态请求)。AA:表示授权回答(authoritativeanswer).TC:表示可截断的(truncated)RD:表示期望递归RA:表示可用递归随后3bit必须为0Rcode:返回码,通常为0(没有差错)和3(名字差错)后面4个16bit字段说明最后4个变长字段中包含的条目数。就我抓包所见,DNS请求报文的标志字段一般为0x0100问题数字段是指这个DNS请求中待解析的域名数目,一般是1,也即0x0001。对应的DNS响应报文的问题数字段也置同样的值资源记录数、授权资源记录数、额外资源记录数在DNS请求报文中都为0,在响应报文中视情况而定。查询问题字段的格式为0151631查询名(长度不定,字节数不一定为4的倍数)查询类型查询类查询名为要查找的名字,它由一个或者多个标示符序列组成。每个标示符已首字节数的计数值来说明该标示符长度,每个名字以0结束,计数字节数必须是0~63之间。该字段无需填充字节。如,表示是从hostaddress解析IP查询类一般为0x0001,表示classIN请求报文和对应的响应报文中的查询问题字段是完全一样的回答字段的格式如下0151631NAME(长度不定,字节数不一定是4的倍数)响应类型响应类生存时间数据长度数据(长度不定,字节数不一定是4的倍数)NAME是该响应报文对应的DNS请求报文要解析的域名,可能是和查询问题字段中的查询名完全一样,但更多的情况下:考虑到响应报文中的查询问题字段和请求报文完全一样,也就包含了查询名,那么也可采用压缩的方式来存放,即用一个16bit的指针来指示NAME的偏移量。比如0xC00C,二进制就是1100000000001100,头两位为11表示这是一个双字节的指针,而不是一个计数字节(上面提到了,查询名里的计数字节为0~63,因此头两位不可能为11),后面的14位则表示这个压缩指针所指的数据离DNS报文(也就是UDP数据报的数据部分,不是指包含DNS报文的UDP数据报的报头)头部的偏移量是12。生存时间以s为单位数据长度是数据的字节数响应类和请求报文的查询问题字段中的查询类对应响应类型我目前见到了两种,一种是0x0001,这种情况下后面的数据是NAME对应的IP,占4字节;一种是0x0005,这种情况下后面的数据是NAME重定向到的域名(比如),这里数据也用查询名中的方式来存放重定向到的域名。下面是实例解析,以查询名()响应类型响应类响应报文标识ID标志字段问题数资源记录数授权资源记录数额外资源记录数0377777705626169647503636f6d0000010001查询名()查询类型查询类c00c00050001指针,指向DNS头部开始偏移12位,即查询名开始位置第一个资源记录的响应类型第一个资源记录的响应类00000213000f第一个资源记录的生存时间第一个资源记录的数据长度0377777701610673686966656ec016第一个资源记录的数据,c016之前对应,c016又是指针,指向DNS头部开始偏移22位,即查询名中的03636f6d00,也就是.comc02b00010001第二个资源记录的NAME,指针,指向DNS头部开始偏移43位,即第一个资源记录中的数据第二个资源记录的响应类型第二个资源记录的响应类000001790004第二个资源记录的生存时间第二个资源记录的数据长度774bd533c02b第二个资源记录的数据,即IP:119.75.213.51第三个资源记录的NAME,指针,指向DNS头部开始偏移43位,即第一个资源记录中的数据0001000100000179第三个资源记录的响应类型第三个资源记录的响应类型第三个资源记录的生存时间0004774bd532第三个资源记录的数据长度第二个资源记录的数据,即IP:119.75.213.50