Skip to content

Latest commit

 

History

History
113 lines (95 loc) · 7.14 KB

dns协议解析.md

File metadata and controls

113 lines (95 loc) · 7.14 KB
layout title category keywords date author
post
dns协议解析
技术
dns
2015-09-15
lisijie

这两天抽空了解了DNS协议,并写了简单的dns服务dnsagent,这几做下简单的记录,不一定正确。

DNS一般使用UDP协议,端口号为53,报文长度超过512字节时使用TCP协议。

DNS报文格式如下:

+-------------------------------+
| 报文头                         |
+-------------------------------+
| 问题 (向服务器提出的查询部分)    |
+-------------------------------+
| 回答 (服务器回复的资源记录)      |
+-------------------------------+
| 授权 (权威的资源记录)           | 
+-------------------------------+
| 格外的 (格外的资源记录)         |
+-------------------------------+

查询包只有头部和问题两个部分,DNS收到查询包后,根据查询到的信息追加回答信息、授权机构、额外资源记录,并且修改了包头的相关标识再返回给客户端。报文头部长度为固定12个字节,包含查询/回复包的信息,格式如下:

                                 1  1  1  1  1  1
   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                      ID                       |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    QDCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    ANCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    NSCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                    ARCOUNT                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

上面每一行是16bit,即2byte,总共6行12字节。各个字段说明如下:

  • ID:占16位,由客户端设置的标识,应答报文需要带上同样的标识,用于区分是哪个查询的应答报文。
  • QR:占1位,用于表示报文类型,0是请求报文,1是应答报文。DNS回复时将该位置为1。
  • Opcode:4位,定义查询和应答的类型。0表示标准查询,1表示反向查询(由IP地址获得主机域名),2表示请求服务器状态。
  • AA:占1位,授权应答(Authoritative Answer) – 这个比特位在应答的时候才有意义,指出给出应答的服务器是查询域名的授权解析服务器。
  • TC:占1位,截断(TrunCation) – 用来指出报文比允许的长度还要长,导致被截断。
  • RD:占1位,期望递归(Recursion Desired) – 这个比特位被请求设置,应答的时候使用的相同的值返回。如果设置了RD,就建议域名服务器进行递归解析,递归查询的支持是可选的。
  • RA:占1位,支持递归(Recursion Available) – 这个比特位在应答中设置或取消,用来代表服务器是否支持递归查询。
  • Z:占3位,未用保留值,值都为0。
  • RCODE:占4位,返回码,通常为0(没有差错)和3(名字差错)
  • QDCOUNT:占16位,指明报文请求段中的问题记录数,就是要查询的域名,一般为1。
  • ANCOUNT:占16位,指明报文回答段中的回答记录数,查询报文中该字段为0。
  • NSCOUNT:占16位,指明报文授权段中的授权记录数,查询报文中该字段为0。
  • ARCOUNT:占16位,指明报文附加段中的附加记录数,查询报文中该字段为0。

接下来是查询问题部分,这部分查询报文和应答报文都有,并且内容相同,报文头的QDCOUNT指明该报文包含多少个查询结构,每个查询结构如下:

   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                                               |
 /                     QNAME                     /
 /                                               /
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                     QTYPE                     |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                     QCLASS                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  • QNAME:为查询的域名,是可变长的,编码格式为:将域名用.号划分为多个部分,每个部分前面加上一个字节表示该部分的长度,最后加一个0字节表示结束。例如:www.baidu.com 应该编码为 3www5baidu3com\0。
  • QTYPE:占16位,表示查询类型,共有16种,常用值有:1(A记录,请求主机IP地址)、2(NS,请求授权DNS服务器)、5(CNAME别名查询)
  • QCLASS:占16位,表示查询类别,共有4种(1:IN、2:CS、3:CH、4:HS),一般为1表示查询IP。

最后是应答结构,报文头中的ANCOUNT、NSCOUNT、ARCOUNT指明了各种应答资源的数量,每种资源都使用相同的结构:

                                 1  1  1  1  1  1
   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                                               |
 /                                               /
 /                      NAME                     /
 |                                               |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                      TYPE                     |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                     CLASS                     |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                      TTL                      |
 |                                               |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |                   RDLENGTH                    |
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
 /                     RDATA                     /
 /                                               /
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  • NAME:回复查询的域名,不定长,跟查询域名对应,这里为了减少包长度,一般不会直接把域名编码进来,而是使用按偏移量计算的方式进行压缩,方法是:如果第一个字节是0xC0,则表示接下来的内容可以通过计算包的偏移量获取到,下一个字节即表示从头开始算起的偏移量,例如第下一个字节是0x0C,十进制12,表示偏移12个字节,从头算起刚好是第一个QNAME的位置,按照上面的QNAME编码方法读到0x0字节为止,就是回复的域名。
  • TYPE:占16位,跟上面的QTYPE意思一样。
  • CLASS:占16位,跟上面的QCLASS一样。
  • TTL:占32位,无符号整数表示资源记录可以缓存的时间。0代表只能被传输,但是不能被缓存。
  • RDLENGTH:占16位,2个字节无符号整数表示RDATA的长度。
  • RDATA:不定长字符串来表示记录,格式根TYPE和CLASS有关。比如,TYPE是A,CLASS 是 IN,那么RDATA就是一个4个字节的ARPA网络地址。

参考1:http://www.rfc-editor.org/rfc/rfc1035.txt

参考2:http://network.51cto.com/art/201411/456088.htm