DNS协议介绍

前言

DNS 协议也就是在做 DNS 解析时,客户端与服务端之间的通信协议。DNS 协议建立在 UDP 或 TCP 协议之上,默认使用 53 号端口。客户端默认通过 UDP 协议进行通讯,但是由于广域网中不适合传输过大的 UDP 数据包,因此规定当报文长度超过了 512 字节时,应转换为使用 TCP 协议进行数据传输。详见 RFC1035 4.MESSAGES 部分。

  • 客户端认为 UDP 响应包长度可能超过 512 字节,主动使用 TCP 协议;
  • 客户端使用 UDP 协议发送 DNS 请求,服务端发现响应报文超过了 512 字节,在截断的 UDP 响应报文中将 TC 设置为 1 ,以通知客户端该报文已经被截断,客户端收到之后再发起一次 TCP 请求。

报文格式

整个报文的格式如下,包括了五部分组成。

1
2
3
4
5
6
7
8
9
10
11
+---------------------+
| Header | 报文头,定义了报文是请求还是应答、错误码以及其它的一些标志位
+---------------------+
| Question | 查询请求,包括查询类型(QTYPE)、查询类(QCLASS) 以及查询的域名(QNAME)
+---------------------+
| Answer | 应答资源记录(RRs)
+---------------------+
| Authority | 授权资源记录(RRs)
+---------------------+
| Additional | 附加信息资源记录(RRs)
+---------------------+

报文头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                                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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

字段含义如下:

字段备注
ID16Bits ,用于生成任何类型的查询。响应报文会原样带回,用于客户端区分不同的请求应答。
QR1Bits,请求 (0 Question) ,应答 (1 Response)。
Opcode4Bits,设置查询的种类,0 标准查询 QUERY、1 反向查询 IQUERY、2 服务器状态查询 STATUS、3~15 保留。响应报文会原样带回。
AA1Bits,授权应答(AuthoritativeAnswer),响应报文生效,用于标示服务器响应报文是否为授权服务器返回的结果,可能是在本地 Cache 的缓存。
TC1Bits,截断(TrunCation),报文因为超过了允许的长度,导致被截断。
RD1Bits,用于请求中,期望使用递归查询。
RA1Bits,用于响应中,如果服务器支持递归查询则设置为 1 ,否则设置为 0 。
RCODE4Bits,应答码(ResponseCode),会在响应报文中设置。含义如下:
0 没有错误;
1 报文格式错误(Format Error),服务器解析请求报文时报错;
2 服务器失败(Server Failure),因为服务器的原因导致没办法处理这个请求;
3 名字错误(Name Error),只对授权域名解析服务器有意义,解析的域名不存在;
4 没有实现(Not Implemented),域名服务器不支持查询类型;
5 拒绝(Refused),由于服务器设置的策略拒绝给出应答,通常是安全的配置;
6-15 保留值,暂未使用。
QDCOUNT无符号16位整数,表示报文请求段中的问题记录数。
ANCOUNT无符号16位整数,表示报文回答段中的回答记录数。
NSCOUNT无符号16位整数,表示报文授权段中的授权记录数。
ARCOUNT无符号16位整数,表示报文附加段中的附加记录数。

为加快 DNS 的查询速度,一般会在服务端缓存一段时间,所以有可能 DNS 会返回缓存在 Cache 中的内容,那么此时就会将 AA 响应设置为 0 ,也就是是这里显示的 Non-authoritative answer 。

查询请求

用来标识,查询的请求参数,同时需要在头中设置 QDCOUNT 这个字段。

1
2
3
4
5
6
7
8
9
10
11
                                1  1  1  1  1  1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ QNAME /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QTYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QCLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

字段含义如下:

字段注释
QNAME域名被表示为标签序列,每个标签包含一个字节表示后续字符串长度,以及这个字符串,以0长度和空字符串来表示域名结束。请注意,此字段可能是奇数个字节,不需要进行边界填充对齐。
QTYPE2个字节,表示查询类型,取值可以为任何可用的类型值,以及通配码来表示所有的资源记录。
QCLASS2个字节,表示查询的协议类,比如,IN代表Internet

其它

递归查询 VS. 迭代查询

在递归查询模式下,DNS 服务器在接收到客户机请求时,必须使用一个准确的查询结果回复客户机。也就意味着,如果 DNS 服务器本地没有缓存所查询的 DNS 信息,那么该服务器会询问其它服务器,并将返回的查询结果提交给客户机。

而在使用迭代查询时,DNS 服务器会向客户机提供其它能够解析查询请求的 DNS 服务器地址。也就是说,当客户机发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台 DNS 服务器地址,客户机需要再向这台 DNS 服务器提交请求,依次循环直到返回查询的结果为止。

也就是说,关键的区别是由谁去查询最终的结果。

DDoS

发送大量的 DNS 递归查询会消耗服务端的一定资源,所以,只需要将发送的报文设置一个 RD 标志位即可。

当发送垃圾查询时,例如不存在的域名,必然会导致查询很慢。