4. 消息 (Messages)
域协议内部的所有通信都承载在一种称为消息 (message) 的单一格式中.
4.1. 格式 (Format)
消息的顶层格式分为 5 个部分, 其中某些部分在特定情况下可以为空:
+---------------------+
| Header |
+---------------------+
| Question | the question for the name server
+---------------------+
| Answer | RRs answering the question
+---------------------+
| Authority | RRs pointing toward an authority
+---------------------+
| Additional | RRs holding additional information
+---------------------+
部分说明 (Section Descriptions):
- Header: 始终存在. 包含若干字段, 用来指明其余哪些部分存在, 以及该消息是查询还是响应, 是标准查询还是其他 opcode 等.
- Question: 包含描述提交给名称服务器的问题的字段. 这些字段包括查询类型 (QTYPE), 查询类 (QCLASS) 和查询域名 (QNAME).
- Answer: 包含回答问题的 RR.
- Authority: 包含指向权威名称服务器的 RR.
- Additional: 包含与查询相关但并非严格作为问题答案的 RR.
后三个部分具有相同格式: 一个可能为空的资源记录 (RR) 串接列表.
4.1.1. 头部部分格式 (Header Section Format)
头部包含以下字段:
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
字段说明 (Field Descriptions)
ID (16 bits):
- 由生成任意查询的程序分配的 16 位标识符.
- 此标识符会复制到相应回复中.
- 请求方可以用它把回复与未完成查询对应起来.
QR (1 bit):
- Query/Response 标志.
- 指定此消息是查询 (0) 还是响应 (1).
OPCODE (4 bits):
- 指定此消息中的查询种类.
- 由查询发起方设置, 并复制到响应中.
- 取值:
0- 标准查询 (QUERY)1- 反向查询 (IQUERY)2- 服务器状态请求 (STATUS)3-15- 保留供未来使用
AA (1 bit):
- Authoritative Answer, 权威应答.
- 在响应中有效.
- 指定响应名称服务器对 question 部分中的相关域名具有权威性.
- 注意: 由于别名, answer 部分可能有多个所有者名称. AA 位对应与查询名称匹配的名称, 或 answer 部分中的第一个所有者名称.
TC (1 bit):
- TrunCation, 截断.
- 指定此消息由于长度超过传输通道允许值而被截断.
RD (1 bit):
- Recursion Desired, 期望递归.
- 可以在查询中设置, 并复制到响应中.
- 如果设置 RD, 它指示名称服务器递归地继续追踪查询.
- 支持递归查询是可选的.
RA (1 bit):
- Recursion Available, 可用递归.
- 在响应中设置或清除.
- 表示该名称服务器是否提供递归查询支持.
Z (3 bits):
- 保留供未来使用.
- 在所有查询和响应中必须为零.
RCODE (4 bits):
- 响应代码.
- 作为响应的一部分设置.
- 取值:
0- 无错误条件.1- 格式错误, 名称服务器无法解释查询.2- 服务器失败, 名称服务器因自身问题无法处理此查询.3- 名称错误, 仅对权威名称服务器的响应有意义, 表示查询中引用的域名不存在.4- 未实现, 名称服务器不支持请求的查询种类.5- 拒绝, 名称服务器出于策略原因拒绝执行指定操作.6-15- 保留供未来使用.
QDCOUNT (16 bits): 无符号 16 位整数, 指定 question 部分中的条目数量.
ANCOUNT (16 bits): 无符号 16 位整数, 指定 answer 部分中的资源记录数量.
NSCOUNT (16 bits): 无符号 16 位整数, 指定 authority records 部分中的名称服务器资源记录数量.
ARCOUNT (16 bits): 无符号 16 位整数, 指定 additional records 部分中的资源记录数量.
4.1.2. 问题部分格式 (Question Section Format)
问题部分用于在多数查询中承载"问题", 也就是定义所询问信息的参数.
该部分包含 QDCOUNT 个条目, 通常为 1 个. 每个条目格式如下:
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 (variable):
- 表示为标签序列的域名.
- 每个标签由一个长度八位组后跟该数量的八位组组成.
- 域名以根的空标签对应的零长度八位组结束.
- 注意: 此字段可以是奇数个八位组; 不使用填充.
QTYPE (16 bits):
- 指定查询类型的两个八位组代码.
- 此字段的值包括所有对 TYPE 字段有效的代码, 以及一些可匹配多种 RR 类型的更通用代码.
QCLASS (16 bits):
- 指定查询类的两个八位组代码.
- 例如, Internet 的 QCLASS 字段为 IN.
4.1.3. 资源记录格式 (Resource Record Format)
answer, authority 和 additional 部分共享同一种格式: 数量可变的资源记录, 记录数量由头部中对应的计数字段指定.
每个资源记录具有以下格式:
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 (variable): 此资源记录所关联的域名.
TYPE (16 bits): 两个八位组, 包含一个 RR 类型代码. 此字段指定 RDATA 字段中数据的含义.
CLASS (16 bits): 两个八位组, 指定 RDATA 字段中数据的类.
TTL (32 bits): 32 位无符号整数, 指定资源记录在应被丢弃前可缓存的时间间隔, 单位为秒. 值为 0 表示该 RR 只能用于当前事务, 不应缓存.
RDLENGTH (16 bits): 无符号 16 位整数, 指定 RDATA 字段的八位组长度.
RDATA (variable): 可变长度八位组串, 描述资源. 其格式随资源记录的 TYPE 和 CLASS 而变化. 例如, 如果 TYPE 为 A 且 CLASS 为 IN, RDATA 字段就是 4 个八位组的 ARPA Internet 地址.
4.1.4. 消息压缩 (Message Compression)
为了减小消息大小, 域系统使用一种压缩方案, 消除消息中重复出现的域名.
压缩方法 (Compression Method)
在此方案中, 一个完整域名或域名末尾的一组标签会被替换为指向同一名称先前出现位置的指针.
指针格式 (Pointer Format):
指针形式如下:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1| OFFSET |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- 前两位为 1.
- 这允许把指针与标签区分开, 因为标签必须以两个零位开始.
- OFFSET 字段指定从消息起始处开始的偏移, 即从域头部 ID 字段的第一个八位组开始.
- 零偏移表示 ID 字段的第一个字节, 依此类推.
压缩规则 (Compression Rules)
压缩方案允许消息中的域名用以下任一方式表示:
- 以零八位组结束的标签序列.
- 一个指针.
- 以指针结束的标签序列.
重要限制 (Important Restrictions):
- 指针只能用于格式不依赖具体类的域名出现位置.
- 否则, 名称服务器或解析器就必须知道其处理的所有 RR 的格式.
- 目前还没有这样的情况, 但未来的 RDATA 格式可能会出现.
允许压缩的位置 (Compression is Allowed):
- 资源记录的 NAME 字段.
- 问题条目的 QNAME 字段.
- RDATA 字段中出现域名的位置, 仅限格式已知的特定 RR 类型.
不允许压缩的位置 (Compression is NOT Allowed):
- RDATA 格式未知或可变的 RR 类型的 RDATA 中.
示例 (Example)
如果查询包含:
www.example.com
mail.example.com
第二次出现的 example.com 可以被替换为指向第一次出现位置的指针, 从而节省字节.
4.2. 传输 (Transport)
DNS 消息可以由不同传输协议承载:
4.2.1. UDP 使用 (UDP Usage)
- 默认传输 (Default Transport): UDP 是 DNS 查询和响应的首选传输.
- 最大大小 (Maximum Size): 通过 UDP 发送的 DNS 消息不应超过 512 个八位组.
- 截断 (Truncation): 如果响应超过 512 个八位组, 应在头部设置 TC 位.
- 重试 (Retry): 当 TC=1 时, 客户端应使用 TCP 重试查询.
UDP 的优点 (Advantages of UDP):
- 对普通查询开销低.
- 不需要连接建立.
- 适合短小查询和响应.
4.2.2. TCP 使用 (TCP Usage)
TCP 用于区域传送以及 UDP 响应被截断后的重试. 通过 TCP 传输时, 消息前面带有一个两八位组长度字段, 指定随后 DNS 消息的长度, 但不包括该长度字段本身.