RFC 1035
Domain names - implementation and specification —— 报文怎么排、标签怎么编码、指针怎么压缩。概念篇是 RFC 1034,实现篇是这一份。
至今仍在用的那些号码
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.2.4 CLASS,不再并入 TYPE]
3.2.4. CLASS values
CLASS fields appear in resource records. The following CLASS mnemonics
and values are defined:
IN 1 the Internet
CS 2 the CSNET class (Obsolete - used only for examples in
some obsolete RFCs)
CH 3 the CHAOS class
HS 4 Hesiod [Dyer 87]
注解
实验室最常见的是 QTYPE=A(1)或后来的 AAAA(28,不在 1035 里)。NS 做委派,CNAME 是别名,SOA 是区的权威起点,PTR 做反向解析。
CLASS 今天几乎总是 IN=1。CS/CH/HS 留给考古。QTYPE 是 TYPE 的超集,另有 AXFR=252、*=255;“查所有类型”现在常被 RFC 8482 改写成最小回应,不要假定 * 还能拉回整包记录。
一条 DNS 报文的五段
+---------------------+
| 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 + Question(QDCOUNT=1,其余计数为 0)。应答把 RR 填进 Answer / Authority / Additional。Header 永远在,后面四段是否出现看四个计数器。
Authority 里常见 NS(“去问这台权威”),Additional 里常见 glue A/AAAA(“那台权威的地址,免得再查一次”)。EDNS OPT 伪 RR 也出现在 Additional。
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 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+[……节选 OPCODE / AA 与页眉]
ID A 16 bit identifier assigned by the program that
generates any kind of query. This identifier is copied
the corresponding reply and can be used by the requester
to match up replies to outstanding queries.
QR A one bit field that specifies whether this message is a
query (0), or a response (1).[……节选 OPCODE、AA 跨页部分]
TC TrunCation - specifies that this message was truncated
due to length greater than that permitted on the
transmission channel.
RD Recursion Desired - this bit may be set in a query and
is copied into the response. If RD is set, it directs
the name server to pursue the query recursively.
Recursive query support is optional.
RA Recursion Available - this be is set or cleared in a
response, and denotes whether recursive query support is
available in the name server.
Z Reserved for future use. Must be zero in all queries
and responses.[……下接官方 RCODE 0–4;5 Refused 跨页,见注解]
RCODE Response code - this 4 bit field is set as part of
responses. The values have the following
interpretation:
0 No error condition
1 Format error - The name server was
unable to interpret the query.
2 Server failure - The name server was
unable to process this query due to a
problem with the name server.
3 Name Error - Meaningful only for
responses from an authoritative name
server, this code signifies that the
domain name referenced in the query does
not exist.
4 Not Implemented - The name server does
not support the requested kind of query.
注解
ID 用来配对问答。16 bit 太短,加上源端口可预测时会被缓存投毒——后来有源端口随机化、RFC 5452 等补丁。读 1035 先记住“用 ID 匹配”。
标志口诀:QR 问还是答;AA 权威;TC 截断(UDP 装不下,客户端改走 TCP);RD 我想递归;RA 我能递归。Stub 解析器发给递归解析器时 RD=1;递归解析器问根/TLD/权威时通常 RD=0。
RD 原文末句是 Recursive query support is optional. 服务器可以不会递归。RCODE 5 是 Refused(策略拒绝,例如不愿做区传送);6–15 保留。Z 在 1035 里必须为 0,后来被 AD/CD 等位占用(DNSSEC)。RCODE=3 是 NXDOMAIN,且只对权威回答有严格含义。
Question 与 RR
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 完整定义]
QNAME a domain name represented as a sequence of labels, where
each label consists of a length octet followed by that
number of octets. The domain name terminates with the
zero length octet for the null label of the root. Note
that this field may be an odd number of octets; no
padding is used.[……节选 QTYPE / QCLASS 与页眉,下接 §4.1.3 RR 图]
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/TYPE/CLASS 字段句,下接 TTL]
TTL a 32 bit unsigned integer that specifies the time
interval (in seconds) that the resource record may be
cached before it should be discarded. Zero values are
interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached.
注解
www.example.com 在线上是 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00——长度字节 + 标签,根是 0。没有点号,也不对齐填充。
Question 没有 TTL。TTL 只活在 RR 里,是权威给缓存的租期。0 表示“这次能用,不要记住”。负缓存(NXDOMAIN 要记多久)由 SOA MINIMUM 等后来的规则管,见 RFC 2308。
IN/A 的 RDATA 就是 4 字节 IPv4。AAAA 是 16 字节,不在 1035。
0xC0 指针
The pointer takes the form of a two octet sequence:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1| OFFSET |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The first two bits are ones. This allows a pointer to be distinguished
from a label, since the label must begin with two zero bits because
labels are restricted to 63 octets or less. (The 10 and 01 combinations
are reserved for future use.) The OFFSET field specifies an offset from
the start of the message (i.e., the first octet of the ID field in the
domain header). A zero offset specifies the first byte of the ID field,
etc.[……下接三种合法表示]
The compression scheme allows a domain name in a message to be represented as either: - a sequence of labels ending in a zero octet - a pointer - a sequence of labels ending with a pointer
[……节选 class-specific / 长度计算]
Programs are free to avoid using pointers in messages they generate, although this will reduce datagram capacity, and may cause truncation. However all programs are required to understand arriving messages that contain pointers.
注解
标签长度 ≤ 63,所以长度字节的高两位必为 00。高两位 11 就是指针,其余 14 bit 是从报文开头(ID)算起的偏移。应答里 Question 写过的名字,Answer 的 NAME 经常是 C0 0C——跳到偏移 12,也就是首部结束后的第一个 QNAME。
发送方可不用指针,接收方必须会解。自己写解析器时要防循环指针。
易误解:“UDP 超过 512 字节就改 TCP”。1035 时代的上限;现在有 EDNS(0) 扩大 UDP 载荷。TC=1、区域传送、实现策略仍可能迫使走 TCP/53。
抓包对照
实验室样本:Ethernet / IP / UDP / DNS。Wireshark 过滤器 dns、dns.flags.response == 0、dns.qry.name == "example.com"。
- 直接可见:12 字节首部全部标志、四个计数、QNAME 的长度编码、TYPE/CLASS、RR 的 TTL/RDLENGTH/RDATA、0xC0 指针。
- Wireshark 会把指针展开成完整名字;点开 Name 才能看到
c0 0c。 - 先看 UDP 端口 53 和 Length,再看 DNS。TC=1 时下一条往往是同一问题的 TCP 重试。
考点与易错点
- 查询与应答靠 ID 配对;QR 区分方向。RD 是“请递归”,RA 是“我能递归”。
- QNAME 是长度+标签+0,不是 ASCII 带点。根域是单独一个 0 字节。
- 压缩指针高两位为 11,偏移从报文第一个字节(ID)算起。接收方必须实现。
- A=1、NS=2、CNAME=5、SOA=6、PTR=12、MX=15;IN=1。AAAA=28 是后来的。
- TTL 只存在于 RR。0 表示禁止缓存。Question 没有 TTL。
- 512 字节是 1035 的 UDP 旧上限。现代看 EDNS 和 TC 位,不要死记“超 512 必 TCP”。