本篇文章让我们来分析下 DNS 消息协议的组成,当然我们也可以查看 RFC 1035。
文章中所用的 byte 而不是 octet sequence,我认为更助于理解。好,首先我需要了解一些有关 DNS 相关的知识。
相关术语
相关的记录类型都已经收录在 DNS 一站到家之记录类型。
- RR(resource record),资源记录,用来描述该条资源。
- TTL(time to live),生命周期,一般用来描述某条资源的有效缓存时间等。
- TYPE,资源类型,如
A
、AAAA
、CNAME
等。 - QTYPE,查询类型,是 TYPE 的超集,增加的有:
AXFR
、MAILB
、MAILA
、*
。 - CLASS,查询类,如
IN
、HS
等,查看如上。 - QCLASS。是 CLASS 的超集,增加的有
*
。 - ZONE,你可能需要阅读 DNS 一站到家之历史由来。
- LABEL,消息中的域名均以标签序列表示
- 每个标签代表了一个 byte 的长度字段 + 多个其他 byte。
- 每个表示长度的 byte,高的 2bit 必须为 0,剩余 6bit 表示该标签的长度,故最大为 63.
- 由于每个域名都以 root 节点的 null 标签结尾,故一个域名总是以一个值为 0 的 byte 结尾。
- 为了简化实现,域名的总长度(标签字节 + 标签长度字节)限制为 255 以内。
如:st.deepzz.com. 该域名被划分为三个标签,注意,这里表示为 length + name:
- 2 + st
- 6 + deepzz
- 3 + com
拼起来为:2 + st + 6 + deepzz + 3 + com + .
基本规范
- 域名的命名规范:
- 域名现在是不区分大小的。
- 域名只能包含 [0-9]、[a-z]、- 字符。(08 年之后允许使用其他语言作为域名)。
- 每一级域名长度的限制是 63 个字符,总长度不能超过 253 个字符。
- 数据传输顺序:大端序。
- DNS 服务器使用 TCP 和 UDP 的 53 端口。
- DNS 解析的域名必须以
.
结尾,不过通常程序会帮你自动加上。
消息格式
协议内部的所有通信采用的是单一格式,称作 message。消息的顶层格式分成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
+---------------------+
Header 总是存在,其中包括一些字段,字段规定其余部分中哪些部分存在,也规定消息是查询还是响应,是标准查询还是某个其他的操作码,等等。
下面我们一一介绍这五个部分如何组成。
Header
Header 的格式是这样的:
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
其中:
ID
,16 bit,程序生成,查询请求的 ID 与响应的 ID 必须相同,这样我们就能知道哪个响应对应着哪个请求。QR
,1 bit,标示是查询请求(0)还是还是响应(1)。OPCODE
,4 bit,标示查询种类,需要复制到响应中:- 0,标准查询(QUERY)
- 1,反响查询(IQUERY)
- 2,服务器状态查询(STATUS)
- 3-15,保留将来使用
AA
,1 bit,权威回答(Authoritative Answer),只在响应中有效,规定响应的名称服务器是 Question 部分中域名的权威。注意,由于别名,回答部分的内容可以有多个所有者名称。AA 位对应匹配查询名称的名称,或者 Answer 部分中第一个所有者名称。TC
,1 bit,截断(Truncation),表示这条消息由于长度大于传送通道上准许的长度而被截断。RD
,1 bit,期望递归(Recursion Desired),在查询中这个位可以置 1,并复制进响应中。如果 1,它引导名称服务器递归跟踪查询。支持递归查询是可选项。RA
,1 bit,递归可用(Recursion Available),在响应中这个字段被置 1 或 0,表示名称服务器中是否支持递归查询。Z
,3 bit,保留将来使用。在所有查询和响应中此位必须置 0。RCODE
,4 bit,响应代码(Response code),响应的一部分。其取值:- 0,没有出错
- 1,消息格式错误
- 2,名称服务器故障
- 3,名称错误,名称不存在
- 4,不支持查询种类
- 5,拒绝,拒绝该操作
- 6-15,保留将来使用
QDCOUNT
,无符号 16 bit,Question 部分中条目的数量ANCOUNT
,无符号 16 bit,Answer 部分中资源记录的数量NSCOUNT
,无符号 16 bit,权威记录部分中名称服务器资源记录的数量。ARCOUNT
,无符号 16 bit,附加记录部分中资源记录的数量。
Question
查询请求中携带该字段,大部分响应也会返回,此部分包括 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
,变长,用标签序列表示的域名,如:deepzz.com,其中 deepzz 长度为 6,故 QNAME 的值为(16 进制):06 64 65 65 70 7a 7a 03 63 6f 6d 00
QTYPE
,16 bit,它规定查询的类型。这个字段的值包括所有适用于 TYPE 字段的代码,以及某些更一般的代码(这些代码可以匹配不止一个 RR 类型)QCLASS
,16 bit,它规定查询的类。例如,对于互联网,QCLASS 字段是 IN
Resource record
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
,变长,该记录匹配的域名CLASS
,16 bit,资源类型,影响 RDATA 的数据含义TTL
,32 bit,缓存时间,单位 s,0 为不缓存RELENGTH
,16 bit,指定 RDATA 的长度RDATA
,变长,这条信息的格式根据资源记录的 TYPE 和 CALSS 改变。例如,如果 TYPE 是 A 和 CALSS 是 IN,此 RDATA 字段是 4 byte 的 ARPA 互联网地址,即 IPv4。
消息压缩
为了减小消息大小,域系统使用去除消息中域名重复的压缩方案。在这个方案中,整个域名或在域名底部的标签列表被用一个指针取代,该指针指向同一名称的前一个具体值。
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1| OFFSET |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
前两位是 1。方便与 label 进行区分,因为由于标签被限制在小于等于 63 个 byte,标签必须用两个 0 位开始(10 和 01 这两个组合保留将来使用)。OFFSET 字段规定从消息开始的偏移(即,域首部中 ID 字段的第一个 byte 开始)。0 偏移表示 ID 字段的第一个字节,等等。
此压缩方案使得消息中的域名能够表示为下述之一:
- 以零八位位组结束的标签序列
- 指针
- 用指针结束的标签序列
指针仅能用于这样的域名具体值,该域名中格式不是特定类。如果不是这种情况,将要求名称服务器或解析器知道它所处理的所有 RRs 的格式。到目前为止没有这类情况,但是在将来的 RDATA 格式中可能出现。
如果消息(该消息受长度字段支配)的一部分包括域名(诸如 RR 的 RDATA 部分),并且使用压缩,在长度计算中使用被压缩的名称的长度(而不是扩展名称的长度)。
在由程序生成的消息中是否避免使用指针由程序自主考虑,尽管这将降低数据报的能力,并且可能引起截断。然而,要求所有程序理解包括指针的到达消息。
例如,数据报或许需要使用域名 F.ISI.ARPA、FOO.F.ISI.ARPA、ARPA 和 root。忽略消息的其他字段,这些域名或许如下图所示。
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20 | 1 | F |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22 | 3 | I |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24 | S | I |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26 | 4 | A |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28 | R | P |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30 | A | 0 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40 | 3 | F |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42 | O | O |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44 | 1 1| 20 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
64 | 1 1| 26 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
92 | 0 | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
F.ISI.ARPA 的域名以偏移 20 显示。FOO.F.ISI.ARPA 的域名以偏移 40 显示;这个定义使用了将 FOO 的标签级联到先前定义的 F.ISI.ARPA 的指针。使用以偏移 20 指向名称 F.ISI.ARPA 的 ARPA 分量的指针,以偏移 64 定义域名 ARPA;注意,这个指针依赖于 ARPA,该 ARPA 是在偏移 20 的字符串中的最后一个标签。根域名称由在偏移 92 的值为 0 的 byte 定义;根域名没有标签。
本文链接:https://deepzz.com/post/dns-rfc1035.html,参与评论 »
--EOF--
发表于 2017-05-13 19:25:00,并被添加「dns、rcf1035」标签。
本站使用「署名 4.0 国际」创作共享协议,转载请注明作者及原网址。更多说明 »
提醒:本文最后更新于 2748 天前,文中所描述的信息可能已发生改变,请谨慎使用。
专题「DNS 一站到家」的其它文章 »
- DNS 一站到家之 CAA 记录 (Feb 04, 2018)
- DNS 一站到家之常用工具 (Apr 13, 2017)
- DNS 一站到家之记录类型 (Apr 10, 2017)
- DNS 一站到家之历史由来 (Apr 04, 2017)
Comments