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网络地址。