详细打开看协议 https://www.ietf.org/rfc/rfc1035.txt 。
摘要:
TYPE value and meaning
A 1 a host address
NS 2 an authoritative name server
MD 3 a mail destination (Obsolete - use MX)
MF 4 a mail forwarder (Obsolete - use MX)
CNAME 5 the canonical name for an alias
SOA 6 marks the start of a zone of authority
MB 7 a mailbox domain name (EXPERIMENTAL)
MG 8 a mail group member (EXPERIMENTAL)
MR 9 a mail rename domain name (EXPERIMENTAL)
NULL 10 a null RR (EXPERIMENTAL)
WKS 11 a well known service description
PTR 12 a domain name pointer
HINFO 13 host information
MINFO 14 mailbox or mail list information
MX 15 mail exchange
TXT 16 text strings
3.4.1. A RDATA format
+--+--+--+--+--+--+--+--+--+--+
| ADDRESS |
+--+--+--+--+--+--+--+--+--+--+
where:
ADDRESS A 32 bit Internet address.
Hosts that have multiple Internet addresses will have multiple A
records.
DNS数据包格式
DNS的数据互换格式并不复杂,但其中有很多概念,包含根域名服务器,权威服务器,递归请求等等,在我们程序中并不会用到,要全盘了解DNS,最好还是认真的阅读RFC1035,如果像我这样只是要写一个请求客户端,那只要有一个原理上的了解即可。
说到这本来数据包格式也可以省掉了,直接上程序即可,不过为了照顾不想看RFC的同学,还是简单抄一下吧:
每个DNS数据包限制在512字节之内(防止IP包超过MTU被碎片化),数据包的总体格式为:
+-----------------+
| Header | 头包信息12字节
+-----------------+
| Question | 提问条目,在请求包和回应包中
+-----------------+
| Answer | 回答的资源目录,在回应包中
+-----------------+
| Authority | 指向权威服务器的资源目录,我们程序没有使用
+-----------------+
| Additional | 附加的资源目录,我们程序没有使用
+-----------------+
包头信息
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode(4) |AA|TC|RD|RA| Z | RCODE(4) |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
ID 一个16位的ID,请求时指定这个ID,回应指返回相同的ID,用来标识同一个会话。
QR 占1位,0表示请求,1表示响应。
OPCODE 操作码占4位,0表示标准请求。
RD 期望递归查询,请求时一般指定为1。
RCODE 占4位,响应包返回结果:0 无错,其他值为各种错误
QDCOUNT 指明提问的数量,请求时一般为1个。
ANCOUNT 指明回答的资源记录的数量,回应时可能有多个。
提问部分
请求包需要至少1个提问条目,回应包也会返回提问条件,格式如下:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+
| |
| QNAME |
| |
+--+--+--+--+--+--+--+--+--+
| QTYPE |
+--+--+--+--+--+--+--+--+--+
| QCLASS |
+--+--+--+--+--+--+--+--+--+
QNAME 域名是由点和多个标签组成的,比如http://www.google.com一共有三个标签www, google, com:
QNAME正常的存储方式是:标签1长度(1字节)+标签1内容+标签2长度(1字节)+标签2内容+...这样的,最后以\0结尾。
还有一种压缩的存储,这是解析程序比较复杂的部分:解析标签时头两位是11,那么剩余的14位表示一个偏移(基于数据包),名字就在偏移处。由于我们不关心域名,所以直接跳过它就行。
QNAME 域名是由点和多个标签组成的,比如http://www.google.com一共有三个标签www, google, com:
QNAME正常的存储方式是:标签1长度(1字节)+标签1内容+标签2长度(1字节)+标签2内容+...这样的,最后以\0结尾。
还有一种压缩的存储,这是解析程序比较复杂的部分:解析标签时头两位是11,那么剩余的14位表示一个偏移(基于数据包),名字就在偏移处。由于我们不关心域名,所以直接跳过它就行。
回答部分
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NAME |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| CLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TTL |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME 和上面的QNAME一样
TYPE 和上面的QTYPE一样
CLASS 和上面的QCLASS一样
TTL 生命周期,DNS有缓存机制,这个表示缓存的时间(S)。
RDLENGTH 资源长度(即RDATA长度)
RDATA 资源内容,A为4个字节的地址,AAAA为16个字节的地址,其他的略过。