非官方中文译本声明:本页为 IETF RFC 1035《DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION》非官方中文译本,由 ztpop.net 整理翻译,仅供学习参考。RFC 文档由 IETF 发布、不受版权限制;依据 BCP 78,本译本为署名翻译作品,译文力求忠实但不构成官方版本,权威性以英文原文为准。英文原文见 rfc-editor.org/rfc/rfc1035

RFC 1035《域名系统——实现与规范》中文译本

摘要

本备忘录(RFC 1035)与配套文档《域名系统——概念与设施》(RFC 1034,STD 13 第一部分)共同构成了互联网域名系统(DNS)的权威规范。RFC 1035 是 STD 13 的第二部分,详细描述了域名系统的协议与实现细节:包括域名空间在报文中的表示方式与各类资源记录(RR)的线格式(TYPE/QTYPE/CLASS/QCLASS 取值表)、DNS 报文(Message)的五段式结构与报文压缩方案、UDP/TCP 传输约定、主文件(Master Files)的文本语法与区域文件示例、名称服务器(Name Server)的实现架构与查询处理流程、解析器(Resolver)的算法细节、以及邮件路由所依赖的邮件交换(MX)绑定机制。全文内容以报文格式图、区域文件示例与算法描述为主,是理解 DNS 解析、邮件投递与 SPF/DKIM/DMARC 认证底层查询机制的根基。

本备忘录取代 RFC 882、RFC 883 与 RFC 973。

1. 本备忘录的状态

本 RFC 描述了域名系统与协议(domain system and protocol)的细节,并假定读者熟悉配套 RFC《域名系统——概念与设施》(Domain Names - Concepts and Facilities)[RFC-1034] 中所讨论的概念。

域名系统是两类内容的一种混合体:一类是构成正式协议(official protocol)的功能与数据类型,另一类是仍处于试验阶段(experimental)的功能与数据类型。由于域名系统被有意设计为可扩展的,因此在官方协议之外的系统部分中,总应预见到新的数据类型与试验性行为。官方协议部分包括标准查询、标准响应以及 Internet 类的 RR 数据格式(例如主机地址)。自上一组 RFC 发布以来,若干定义已经发生变化,因此此前的一些定义已经废弃。

试验性或已废弃的功能在这些 RFC 中都有明确标注,使用此类信息时应加以谨慎。

特别提醒读者:不要依赖示例中出现的取值是当前有效或完整的,因为这些取值的用途主要是教学性的。本备忘录的分发不受限制。

2. 引言

2.1. 概述

域名的目标是提供一种对资源进行命名的机制,使这些名称能够在不同的主机、网络、协议族、互联网与管理组织中使用。

从用户的视角看,域名可作为参数传给一个称为「解析器」(resolver)的本地代理,由它来获取与域名相关联的信息。因此,用户可以请求某特定域名所关联的主机地址或邮件信息。为了让用户能够请求特定类型的信息,一种恰当的查询类型会随域名一起传给解析器。对用户而言,域名树是一个单一的信息空间;解析器负责对用户隐藏数据在名称服务器之间的分布情况。

从解析器的视角看,构成域名空间的数据库分布在各名称服务器之间。域名空间的不同部分存储在不同的名称服务器中,不过某个特定的数据项通常会被冗余存储在两台或更多名称服务器中。解析器启动时至少知道一台名称服务器的信息。当解析器处理一个用户查询时,它向一台已知的名称服务器询问所需信息;作为回报,解析器要么得到所需的信息,要么得到一个指向另一台名称服务器的转介(referral)。借助这些转介,解析器可以了解到其他名称服务器的身份与内容。解析器负责处理域名空间的分布问题,并负责通过查询其他服务器上的冗余数据库来应对名称服务器故障所造成的影响。

名称服务器管理两类数据。第一类数据按被称为「区」(zone)的集合来组织;每个区是域名空间中某个特定「剪枝后」子树的完整数据库。这类数据被称为「权威数据」(authoritative)。名称服务器周期性地检查自己的区是否最新,如果不是,则从本地保存的主文件(master file)或另一台名称服务器获取更新后区的新副本。第二类数据是缓存数据(cached data),由本地解析器获取。这类数据可能不完整,但当反复访问非本地数据时,它能改善检索过程的性能。缓存数据最终会被一种超时机制所丢弃。

这种功能结构把用户界面、故障恢复与数据分布的问题隔离在解析器中,而把数据库更新与刷新的问题隔离在名称服务器中。

2.2. 常见配置

一台主机可以通过多种方式参与域名系统,具体取决于:该主机是否运行从域名系统检索信息的程序,是否运行应答其他主机查询的名称服务器,或者两者功能的某种组合。最简单、或许也最具代表性的配置如下图所示:

                 Local Host                        |  Foreign
                                                   |
    +---------+               +----------+         |  +--------+
    |         | user queries  |          |queries  |  |        |
    |  User   |-------------->|          |---------|->|Foreign |
    | Program |               | Resolver |         |  |  Name  |
    |         |<--------------|          |<--------|--| Server |
    |         | user responses|          |responses|  |        |
    +---------+               +----------+         |  +--------+
                                |     A            |
                cache additions |     | references |
                                V     |            |
                              +----------+         |
                              |  cache   |         |
                              +----------+         |

用户程序通过解析器与域名空间交互;用户查询与用户响应的格式因主机及其操作系统而异。用户查询通常是操作系统调用,解析器及其缓存将成为主机操作系统的一部分。能力较弱的主机可以选择把解析器实现为一个子程序,链接到每个需要其服务的程序中。解析器通过查询外部名称服务器以及查询本地缓存所获取的信息来应答用户的查询。

请注意,为了应答一个特定的用户查询,解析器可能需要向多台不同的外部名称服务器发出多个查询,因此一个用户查询的解析过程可能涉及多次网络访问与任意长的时间。发给外部名称服务器的查询及相应的响应采用本备忘录所描述的、标准化的格式,且可以是数据报(datagram)。

根据其能力的不同,名称服务器可以是专用机器上的独立程序,也可以是大规模分时主机上的一个或多个进程。一个简单的配置可能如下:

                 Local Host                        |  Foreign
                                                   |
      +---------+                                  |
     /         /|                                  |
    +---------+ |             +----------+         |  +--------+
    |         | |             |          |responses|  |        |
    |         | |             |   Name   |---------|->|Foreign |
    |  Master |-------------->|  Server  |         |  |Resolver|
    |  files  | |             |          |<--------|--|        |
    |         |/              |          | queries |  +--------+
    +---------+               +----------+         |

在这里,主名称服务器(primary name server)通过从其本地文件系统读取主文件来获取一个或多个区的信息,并应答来自外部解析器的、关于这些区的查询。

DNS 要求所有区都由两台以上的名称服务器冗余支持。指定的辅助服务器(secondary server)可以利用 DNS 的区传送协议(zone transfer protocol),从主服务器获取区并检查更新。这种配置如下所示:

                 Local Host                        |  Foreign
                                                   |
      +---------+                                  |
     /         /|                                  |
    +---------+ |             +----------+         |  +--------+
    |         | |             |          |responses|  |        |
    |         | |             |   Name   |---------|->|Foreign |
    |  Master |-------------->|  Server  |         |  |Resolver|
    |  files  | |             |          |<--------|--|        |
    |         |/              |          | queries |  +--------+
    +---------+               +----------+         |
                                A     |maintenance |  +--------+
                                |     +------------|->|        |
                                |      queries     |  |Foreign |
                                |                  |  |  Name  |
                                +------------------|--| Server |
                             maintenance responses |  +--------+

在这种配置中,名称服务器周期性地与外部名称服务器建立一条虚电路(virtual circuit),以获取某个区的副本,或者检查现有副本是否未发生变化。这些维护活动所发送的报文采用与查询和响应相同的形式,但报文序列略有不同。

一台支持域名系统所有方面的主机中的信息流如下所示:

                 Local Host                        |  Foreign
                                                   |
    +---------+               +----------+         |  +--------+
    |         | user queries  |          |queries  |  |        |
    |  User   |-------------->|          |---------|->|Foreign |
    | Program |               | Resolver |         |  |  Name  |
    |         |<--------------|          |<--------|--| Server |
    |         | user responses|          |responses|  |        |
    +---------+               +----------+         |  +--------+
                                |     A            |
                cache additions |     | references |
                                V     |            |
                              +----------+         |
                              |  Shared  |         |
                              | database |         |
                              +----------+         |
                                A     |            |
      +---------+     refreshes |     | references |
     /         /|               |     V            |
    +---------+ |             +----------+         |  +--------+
    |         | |             |          |responses|  |        |
    |         | |             |   Name   |---------|->|Foreign |
    |  Master |-------------->|  Server  |         |  |Resolver|
    |  files  | |             |          |<--------|--|        |
    |         |/              |          | queries |  +--------+
    +---------+               +----------+         |
                                A     |maintenance |  +--------+
                                |     +------------|->|        |
                                |      queries     |  |Foreign |
                                |                  |  |  Name  |
                                +------------------|--| Server |
                             maintenance responses |  +--------+

共享数据库(shared database)为本地名称服务器和解析器保存域名空间的数据。共享数据库的内容通常是两种数据的混合:由名称服务器周期性刷新操作维护的权威数据,以及先前解析器请求所产生的缓存数据。域名数据的结构以及名称服务器与解析器之间同步的必要性,决定了这个数据库的一般特征,但其实际格式由本地实现者决定。

信息流还可以被剪裁,使一组主机协同工作以优化相关活动。有时这样做是为了减轻能力较弱主机的负担,使它们不必实现完整的解析器。这对于 PC 或那些希望尽量少写新网络代码的主机来说可能是合适的。这种方案还可以让一组主机共享少量缓存,而不是各自维护大量相互独立的缓存,其前提是集中式缓存会有更高的命中率。无论哪种情况,解析器都被替换为「桩解析器」(stub resolver),它们充当位于一台或多台已知提供递归服务的名称服务器中解析器的前端:

                   Local Hosts                     |  Foreign
                                                   |
    +---------+                                    |
    |         | responses                          |
    | Stub    |<--------------------+              |
    | Resolver|                     |              |
    |         |----------------+    |              |
    +---------+ recursive      |    |              |
                queries        |    |              |
                               V    |              |
    +---------+ recursive     +----------+         |  +--------+
    |         | queries       |          |queries  |  |        |
    | Stub    |-------------->| Recursive|---------|->|Foreign |
    | Resolver|               | Server   |         |  |  Name  |
    |         |<--------------|          |<--------|--| Server |
    +---------+ responses     |          |responses|  |        |
                              +----------+         |  +--------+
                              |  Central |         |
                              |   cache  |         |
                              +----------+         |

在任何情况下都请注意:只要可能,域组件总是会被复制,以提升可靠性。

2.3. 约定

域名系统在若干低层但根本性的问题上有一系列约定。虽然实现者可以自由地在自己的系统内部违反这些约定,但在所有从其他主机可观察到的行为中,他必须遵守这些约定。

2.3.1. 首选名称语法

DNS 规范力图在构造域名的规则上尽可能通用。其思路是:任何现存对象的名称都可以用尽量少的改动表达为一个域名。

然而,当为一个对象分配域名时,审慎的用户会选择一个既满足域名系统规则、又满足该对象任何现有规则的名称——无论这些规则是公开发布的,还是由现有程序所隐含的。

例如,当为一个邮件域命名时,用户应当同时满足本备忘录的规则与 RFC-822 的规则。当创建新的主机名时,应当遵循 HOSTS.TXT 的旧规则。这样做可以避免旧软件改用域名时出现问题。

下面这种语法在使用域名的许多应用(例如邮件、TELNET)中引发的麻烦最少:

<domain> ::= <subdomain> | " "

<subdomain> ::= <label> | <subdomain> "." <label>

<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]

<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>

<let-dig-hyp> ::= <let-dig> | "-"

<let-dig> ::= <letter> | <digit>

<letter> ::= A 至 Z 大写与 a 至 z 小写这 52 个字母字符中的任意一个

<digit> ::= 数字 0 至 9 这十个数字中的任意一个

请注意,虽然域名中允许出现大写与小写字母,但大小写不附带任何意义。也就是说,拼写相同但大小写不同的两个名称应当被视为相同。

标签必须遵循 ARPANET 主机名的规则。标签必须以字母开头,以字母或数字结尾,内部字符只能是字母、数字与连字符。在长度上还有一些限制。标签必须不超过 63 个字符。

例如,下列字符串标识了 Internet 中的主机:

A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA

2.3.2. 数据传输顺序

本文档所描述的信头与数据的传输顺序被精确到八位组(octet)一级。每当一个示意图展示一组八位组时,这些八位组的传输顺序就是它们以英文正常阅读的顺序。例如,在下面的示意图中,八位组按编号顺序传输。

     0                   1
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       1       |       2       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       3       |       4       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |       5       |       6       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

每当一个八位组表示一个数值时,示意图中最左边的位是高位,即最高有效位。也就是说,标号为 0 的位是最高有效位。例如,下面的示意图表示数值 170(十进制)。

     0 1 2 3 4 5 6 7
    +-+-+-+-+-+-+-+-+
    |1 0 1 0 1 0 1 0|
    +-+-+-+-+-+-+-+-+

类似地,每当一个多八位组字段表示一个数值时,整个字段最左边的位是最高有效位。当一个多八位组数值被传输时,最高有效八位组最先传输。

2.3.3. 字符大小写

对于 DNS 中属于官方协议的所有部分,所有字符串(例如标签、域名等)之间的比较都以不区分大小写的方式完成。目前,这一规则在整个域名系统中毫无例外地生效。然而,超出当前用法的未来扩展可能需要利用名称中完整的二进制八位组能力,因此应当避免试图把域名存储为 7 位 ASCII,或使用特殊字节来终止标签等做法。

当数据进入域名系统时,只要有可能就应保留其原始大小写。在某些情况下这无法做到。例如,如果两条 RR 存储在数据库中,一条在 x.y、一条在 X.Y,它们实际上存储在数据库中的同一位置,因而只会保留一种大小写。基本规则是:只有当数据被用于在数据库中定义结构,且两个名称在不区分大小写比较时相同的情况下,大小写才可以被舍弃。

区分大小写的数据的丢失必须最小化。因此,虽然 x.y 与 X.Y 的数据可以都存储在 x.y 或 X.Y 这一单个位置下,但 a.x 与 B.X 的数据绝不会存储在 A.x、A.X、b.x 或 b.X 下。一般而言,这样会保留域名第一个标签的大小写,但会迫使内部节点标签标准化。

如果系统对大小写敏感,那么向域名数据库录入数据的系统管理员应当注意:他们提供给域名系统的数据要采用大小写一致的表示方式。域名系统中的数据分发机制将确保一致的表示得以保留。

2.3.4. 大小限制

DNS 中的各种对象与参数都有大小限制。它们列在下面。其中一些很容易更改,另一些则更为根本。

对象 / 参数限制
标签(labels)不超过 63 个八位组
名称(names)不超过 255 个八位组
TTL带符号 32 位数的正值
UDP 报文(UDP messages)不超过 512 个八位组

3. 域名空间与 RR 定义

3.1. 名称空间定义

报文中的域名以一串标签(label)的序列来表达。每个标签表示为一个单八位组的长度字段,后跟相应数量的八位组。由于每个域名都以根的零长度标签结尾,因此域名以一个长度字节为零来终止。每个长度八位组的高两位必须为零,长度字段的其余六位把标签限制为不超过 63 个八位组。

为简化实现,域名的总长度(即标签八位组与标签长度八位组之和)被限制为不超过 255 个八位组。

虽然构成标签的八位组中可以包含任何 8 位值,但强烈建议标签遵循本备忘录其他部分所描述的、与现有主机命名约定兼容的首选语法。名称服务器与解析器必须采用不区分大小写的方式(即 A=a)比较标签,前提是采用零奇偶校验的 ASCII。非字母代码必须精确匹配。

3.2. RR 定义

3.2.1. 格式

所有 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                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

3.2.2. TYPE 取值

TYPE 字段用于资源记录中。请注意,这些类型是 QTYPE 的子集。

TYPE含义
A1主机地址(a host address)
NS2权威名称服务器(an authoritative name server)
MD3邮件目标(已废弃,改用 MX)
MF4邮件转发器(已废弃,改用 MX)
CNAME5别名的规范名称(the canonical name for an alias)
SOA6标记权威区起点(marks the start of a zone of authority)
MB7邮箱域名(试验性)
MG8邮件组成员(试验性)
MR9邮件改名域名(试验性)
NULL10空 RR(试验性)
WKS11知名服务描述(a well known service description)
PTR12域名指针(a domain name pointer)
HINFO13主机信息(host information)
MINFO14邮箱或邮件列表信息(mailbox or mail list information)
MX15邮件交换(mail exchange)
TXT16文本字符串(text strings)

3.2.3. QTYPE 取值

QTYPE 字段出现在查询的问题部分(question part)中。QTYPE 是 TYPE 的超集,因此所有 TYPE 都是有效的 QTYPE。此外,还定义了以下 QTYPE:

QTYPE含义
AXFR252请求传输整个区(a request for a transfer of an entire zone)
MAILB253请求邮箱相关记录(MB、MG 或 MR)
MAILA254请求邮件代理 RR(已废弃,参见 MX)
*255请求所有记录(a request for all records)

3.2.4. CLASS 取值

CLASS 字段出现在资源记录中。定义了以下 CLASS 助记符与取值:

CLASS含义
IN1Internet(the Internet)
CS2CSNET 类(已废弃,仅用于某些已废弃 RFC 中的示例)
CH3CHAOS 类
HS4Hesiod [Dyer 87]

3.2.5. QCLASS 取值

QCLASS 字段出现在查询的问题部分中。QCLASS 取值是 CLASS 取值的超集;每个 CLASS 都是有效的 QCLASS。除 CLASS 取值之外,还定义了以下 QCLASS:

QCLASS含义
*255任何类(any class)

3.3. 标准 RR

以下 RR 定义预期至少潜在地出现在所有类中。特别是,NS、SOA、CNAME 与 PTR 将用于所有类,并且在所有类中具有相同的格式。由于它们的 RDATA 格式是已知的,这些 RR 的 RDATA 部分中的所有域名都可以被压缩。

<domain-name> 是一个以一系列标签表示、并以零长度标签终止的域名。<character-string> 是单个长度八位组后跟相应数量字符的字符串。<character-string> 按二进制信息处理,长度最长可达 256 个字符(含长度八位组)。

3.3.1. CNAME RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                     CNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

CNAME RR 不引发附加部分(additional section)处理,但在某些情况下,名称服务器可以选择在规范名称处重新开始查询。详情参见 [RFC-1034] 中名称服务器逻辑的描述。

3.3.2. HINFO RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                      CPU                      /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                       OS                      /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

CPU 与 OS 的标准取值可在 [RFC-1010] 中找到。

HINFO 记录用于获取关于主机的一般信息。其主要用途是供 FTP 等协议使用,这类协议在同类型机器或操作系统之间通信时可以采用特殊流程。

3.3.3. MB RDATA 格式(试验性)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   MADNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MB 记录引发附加部分处理,该处理会查找与 MADNAME 对应的 A 类型 RR。

3.3.4. MD RDATA 格式(已废弃)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   MADNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MD 记录引发附加部分处理,该处理会查找与 MADNAME 对应的 A 类型记录。

MD 已废弃。有关新方案的细节,参见 MX 的定义与 [RFC-974]。对主文件中出现的 MD RR,推荐的处理策略是拒绝它们,或者把它们转换为偏好值为 0 的 MX RR。

3.3.5. MF RDATA 格式(已废弃)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   MADNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MF 记录引发附加部分处理,该处理会查找与 MADNAME 对应的 A 类型记录。

MF 已废弃。有关新方案的细节,参见 MX 的定义与 [RFC-974]。对主文件中出现的 MF RR,推荐的处理策略是拒绝它们,或者把它们转换为偏好值为 10 的 MX RR。

3.3.6. MG RDATA 格式(试验性)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   MGMNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MG 记录不引发附加部分处理。

3.3.7. MINFO RDATA 格式(试验性)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                    RMAILBX                    /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                    EMAILBX                    /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MINFO 记录不引发附加部分处理。虽然这些记录可以与单个邮箱相关联,但它们通常与邮件列表一起使用。

3.3.8. MR RDATA 格式(试验性)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   NEWNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MR 记录不引发附加部分处理。MR 的主要用途是作为已迁移到不同邮箱的用户的转发条目。

3.3.9. MX RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  PREFERENCE                   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   EXCHANGE                    /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

MX 记录会针对 EXCHANGE 所指定的主机引发 A 类型附加部分处理。MX RR 的用途在 [RFC-974] 中有详细说明。

3.3.10. NULL RDATA 格式(试验性)

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                  <anything>                   /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

只要长度不超过 65535 个八位组,RDATA 字段中可以放任何内容。

NULL 记录不引发附加部分处理。NULL RR 不允许出现在主文件中。NULL 在 DNS 的某些试验性扩展中被用作占位符。

3.3.11. NS RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   NSDNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

NS 记录既引发通常的、用于定位 A 类型记录的附加部分处理;当用于转介(referral)时,还会对其所在区进行胶水信息(glue information)的特殊搜索。

NS RR 声明:被指名的主机预期拥有一个起始于指定类所有者名称的区。请注意,类可能并不指示应当用于与该主机通信的协议族,尽管它通常是一个很强的提示。例如,作为 Internet(IN)类或 Hesiod(HS)类信息的名称服务器的主机,通常使用 IN 类协议进行查询。

3.3.12. PTR RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   PTRDNAME                    /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

PTR 记录不引发附加部分处理。这些 RR 用于特殊域中,以指向域名空间中其他位置。这些记录是简单数据,不暗示任何类似 CNAME 所执行的那种标识别名的特殊处理。参见 IN-ADDR.ARPA 域的描述中的示例。

3.3.13. SOA RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                     MNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                     RNAME                     /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    SERIAL                     |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    REFRESH                    |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     RETRY                     |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    EXPIRE                     |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    MINIMUM                    |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

SOA 记录不引发附加部分处理。

所有时间都以秒为单位。

这些字段中的大多数仅与名称服务器的维护操作相关。然而,MINIMUM 用于所有从区中检索 RR 的查询操作中。每当一条 RR 在对查询的响应中被发送时,TTL 字段被设置为该 RR 的 TTL 字段与相应 SOA 中 MINIMUM 字段两者中的最大值。因此,MINIMUM 是本区所有 RR 的 TTL 字段的下界。请注意,这种 MINIMUM 的使用应当发生在 RR 被复制进响应时,而不是发生在区从主文件加载或经由区传送加载时。这样规定的原因是:允许未来的动态更新设施以已知的语义更改 SOA RR。

3.3.14. TXT RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    /                   TXT-DATA                    /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

TXT RR 用于保存描述性文本。文本的语义取决于其所在的域。

3.4. Internet 专用 RR

3.4.1. A RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ADDRESS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

具有多个 Internet 地址的主机将具有多条 A 记录。

A 记录不引发附加部分处理。主文件中 A 行的 RDATA 部分是一个 Internet 地址,表示为四个十进制数,用点分隔,中间不嵌入空格(例如 "10.2.0.52" 或 "192.0.5.6")。

3.4.2. WKS RDATA 格式

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ADDRESS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |       PROTOCOL        |                       |
    +--+--+--+--+--+--+--+--+                       |
    |                                               |
    /                   <BIT MAP>                   /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

WKS 记录用于描述某个特定 Internet 地址上、某个特定协议所支持的知名服务。PROTOCOL 字段指定一个 IP 协议号,位图对指定协议的每个端口各有一个位。第一个位对应端口 0,第二个位对应端口 1,依此类推。如果位图不包含某关注协议的位,则该位被假定为零。端口与协议的适当取值与助记符在 [RFC-1010] 中规定。

例如,如果 PROTOCOL=TCP(6),则第 26 位对应 TCP 端口 25(SMTP)。如果该位被置位,则应当有一台 SMTP 服务器在 TCP 端口 25 上监听;如果为零,则指定地址上不支持 SMTP 服务。

WKS RR 的目的是为 TCP 与 UDP 服务器提供可用性信息。如果一台服务器同时支持 TCP 与 UDP,或者具有多个 Internet 地址,则使用多条 WKS RR。

WKS RR 不引发附加部分处理。

在主文件中,端口与协议都用助记符或十进制数表示。

3.5. IN-ADDR.ARPA 域

Internet 使用一个特殊域来支持网关定位以及 Internet 地址到主机的映射。其他类可以在其他域中采用类似的策略。该域的目的是提供一种有保障的方法来完成主机地址到主机名的映射,并方便那些用于定位 Internet 上特定网络中所有网关的查询。

请注意,这两种服务与逆查询(inverse query)可以完成的功能类似;区别在于,域名空间的这一部分按地址来组织,因此能够保证无需穷举搜索域名空间即可定位到适当的数据。

该域起始于 IN-ADDR.ARPA,其子结构遵循 Internet 的寻址结构。

IN-ADDR.ARPA 域中的域名被定义为:除了 IN-ADDR.ARPA 后缀之外,最多还有四个标签。每个标签表示 Internet 地址的一个八位组,并表达为 0-255 范围内一个十进制值的字符串(前导零省略,但零八位组例外,它由单个零表示)。

主机地址由四个标签全部指定的域名表示。因此,Internet 地址 10.2.0.52 的数据位于域名 52.0.2.10.IN-ADDR.ARPA 处。这种反转虽然读起来别扭,但它允许委派正好一个地址空间网络的区。例如,10.IN-ADDR.ARPA 可以是一个包含 ARPANET 数据的区,而 26.IN-ADDR.ARPA 可以是 MILNET 的一个独立区。地址节点用于保存指向正常域名空间中主主机名的指针。

网络号对应 IN-ADDR.ARPA 域中各种深度上的一些非终端节点,因为 Internet 网络号是 1、2 或 3 个八位组。网络节点用于保存指向连接到该网络的网关的主主机名的指针。由于网关按定义位于不止一个网络上,因此通常会有两个或更多网络节点指向它。网关在其完全限定的地址处还会有主机级指针。

网络节点上的网关指针与完整地址节点上的普通主机指针,都使用 PTR RR 指回相应主机的首选域名。

例如,IN-ADDR.ARPA 域将包含有关 ISI 网关(位于网络 10 与 26 之间)、MIT 网关(从网络 10 通往 MIT 的网络 18)以及主机 A.ISI.EDU 与 MULTICS.MIT.EDU 的信息。假定 ISI 网关的地址为 10.2.0.22 与 26.0.0.103、名称为 MILNET-GW.ISI.EDU,MIT 网关的地址为 10.0.0.77 与 18.10.0.4、名称为 GW.LCS.MIT.EDU,那么域名数据库将包含:

    10.IN-ADDR.ARPA.           PTR MILNET-GW.ISI.EDU.
    10.IN-ADDR.ARPA.           PTR GW.LCS.MIT.EDU.
    18.IN-ADDR.ARPA.           PTR GW.LCS.MIT.EDU.
    26.IN-ADDR.ARPA.           PTR MILNET-GW.ISI.EDU.
    22.0.2.10.IN-ADDR.ARPA.    PTR MILNET-GW.ISI.EDU.
    103.0.0.26.IN-ADDR.ARPA.   PTR MILNET-GW.ISI.EDU.
    77.0.0.10.IN-ADDR.ARPA.    PTR GW.LCS.MIT.EDU.
    4.0.10.18.IN-ADDR.ARPA.    PTR GW.LCS.MIT.EDU.
    103.0.3.26.IN-ADDR.ARPA.   PTR A.ISI.EDU.
    6.0.0.10.IN-ADDR.ARPA.     PTR MULTICS.MIT.EDU.

因此,一个想要定位网络 10 上网关的程序,将发起 QTYPE=PTR、QCLASS=IN、QNAME=10.IN-ADDR.ARPA 的查询。它将在响应中收到两条 RR:

    10.IN-ADDR.ARPA.           PTR MILNET-GW.ISI.EDU.
    10.IN-ADDR.ARPA.           PTR GW.LCS.MIT.EDU.

然后该程序可以针对 MILNET-GW.ISI.EDU. 与 GW.LCS.MIT.EDU. 发起 QTYPE=A、QCLASS=IN 的查询,以发现这些网关的 Internet 地址。

一个想要查找与 Internet 主机地址 10.0.0.6 相对应的主机名的解析器,将发起 QTYPE=PTR、QCLASS=IN、QNAME=6.0.0.10.IN-ADDR.ARPA 的查询,并收到:

    6.0.0.10.IN-ADDR.ARPA.     PTR MULTICS.MIT.EDU.

使用这些服务时有几点告诫:

3.6. 定义新类型、新类与特殊命名空间

此前定义的类型与类是截至本备忘录日期所使用的。应当预期会出现新的定义。本节面向那些考虑扩展现有设施的设计者提出一些建议。邮件列表 NAMEDROPPERS@SRI-NIC.ARPA 是进行设计问题一般性讨论的论坛。

一般来说,当需要就现有对象向数据库添加新信息,或者我们为某种全新的对象需要新的数据格式时,定义一个新类型是合适的。设计者应当努力定义那些普遍适用于所有类、并避免信息重复的类型及其 RDATA 格式。当 DNS 要用于一种新协议、或某协议需要新的类专属数据格式时,或者当希望得到现有命名空间的副本、但需要一个独立的管理域时,定义新类是合适的。

新类型与新类需要主文件使用的助记符;主文件的格式要求类型与类的助记符互不相交。

TYPE 与 CLASS 取值必须分别是 QTYPE 与 QCLASS 的真子集。

现行系统使用多条 RR 来表示一个类型的多个值,而不是在单条 RR 的 RDATA 部分中存储多个值。这对大多数应用而言效率较低,但确实使 RR 更短。多条 RR 这一假定已被纳入某些关于动态更新方法的试验性工作中。

现行系统力图最大限度地减少数据库中的数据重复,以确保一致性。因此,为了找到邮件交换的主机地址,需要把邮件域名映射为主机名,再把主机名映射为地址,而不是直接映射为主机地址。之所以偏好这种做法,是因为它避免了产生不一致的机会。

在定义一种新类型的数据时,不应当使用多种 RR 类型来在条目之间建立顺序,或为等价的绑定表达不同的格式;相反,这些信息应当承载在 RR 的主体中,并使用单一类型。这一策略避免了缓存多种类型以及定义匹配多种类型的 QTYPE 所带来的问题。

例如,邮件交换绑定的原始形式使用两种 RR 类型,一种表示「较近的」交换(MD),一种表示「较远的」交换(MF)。困难在于:缓存中存在一种 RR 类型并不能传达关于另一种类型的任何信息,因为获取缓存信息的查询可能使用了 MF、MD 或 MAILA(同时匹配两者)的 QTYPE。重新设计的服务使用单一类型(MX),并在 RDATA 部分携带一个可以给不同 RR 排序的「偏好」(preference)值。然而,如果缓存中发现了任何 MX RR,那么所有 MX RR 都应当在缓存中。

4. 报文

4.1. 格式

域协议内部的所有通信都采用一种称为「报文」(message)的单一格式来承载。报文的顶层格式分为 5 个部分(在某些情况下其中一些为空),如下所示:

    +---------------------+
    |     Header 信头      |
    +---------------------+
    |    Question 问题    | 给名称服务器的问题
    +---------------------+
    |     Answer 应答     | 回答该问题的 RR
    +---------------------+
    |   Authority 权威    | 指向权威的 RR
    +---------------------+
    |  Additional 附加    | 承载附加信息的 RR
    +---------------------+

信头部分始终存在。信头中包含指定其余各部分中哪些存在的字段,还指定该报文是查询还是响应、是标准查询还是某种其他操作码(opcode)等等。

信头之后各部分的名称源自它们在标准查询中的用途。问题部分(question section)包含描述向名称服务器提出的问题的字段。这些字段是查询类型(QTYPE)、查询类(QCLASS)与查询域名(QNAME)。后三个部分具有相同的格式:一个可能为空的、由资源记录(RR)连接而成的列表。应答部分(answer section)包含回答该问题的 RR;权威部分(authority section)包含指向权威名称服务器的 RR;附加记录部分(additional records section)包含与查询相关、但并非严格意义上该问题答案的 RR。

4.1.1. 信头部分格式

信头包含以下字段:

                                    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                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

请注意,由于别名(alias)的存在,应答部分的内容可能具有多个所有者名称。AA 位对应于与查询名称相匹配的名称,或应答部分中的第一个所有者名称。

4.1.2. 问题部分格式

问题部分用于在大多数查询中承载「问题」,即定义所询问内容的参数。该部分包含 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                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

4.1.3. 资源记录格式

应答、权威与附加部分共享相同的格式:数量可变的资源记录,记录数量由信头中相应的计数字段指定。每条资源记录具有以下格式:

                                    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                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

其中:

4.1.4. 报文压缩

为了减小报文的大小,域名系统采用一种压缩方案,消除报文中域名的重复。在该方案中,一个完整的域名或域名末尾的一系列标签被替换为指向先前相同名称出现位置的指针。

该指针采用两八位组序列的形式:

    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 1  1|                OFFSET                   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

前两位为 1。这样可以把指针与标签区分开来,因为标签必须以两个零位开头(标签被限制为不超过 63 个八位组)。(10 与 01 组合保留用于将来使用。)OFFSET 字段指定从报文起点(即域信头中 ID 字段的第一个八位组)算起的偏移量。零偏移量指定 ID 字段的第一个字节,依此类推。

该压缩方案允许报文中的域名以以下任一方式表示:

指针只能用于域名出现在格式不属于类专属的地方。如果不是这样,名称服务器或解析器将需要知道它所处理的所有 RR 的格式。目前还没有这样的情况,但未来的 RDATA 格式中可能会出现。

如果域名包含在报文的一个受长度字段约束的部分中(例如 RR 的 RDATA 部分),并且使用了压缩,则在长度计算中使用压缩后名称的长度,而不是展开后名称的长度。

程序可以自由地避免在其生成的报文中使用指针,尽管这会降低数据报容量,并可能引起截断。但所有程序都被要求能够理解所收到的、包含指针的报文。

例如,一个数据报可能需要使用域名 F.ISI.ARPA、FOO.F.ISI.ARPA、ARPA 与根。忽略报文的其他字段,这些域名可以表示为:

       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    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 上。ARPA 的域名在偏移 64 处定义,使用一个指向偏移 20 处 F.ISI.ARPA 名称中 ARPA 成分的指针;请注意,该指针依赖于 ARPA 是 20 处字符串的最后一个标签。根域名由 92 处的单个零八位组定义;根域名没有任何标签。

4.2. 传输

DNS 假定报文将作为数据报传输,或作为由虚电路承载的字节流传输。虽然虚电路可用于任何 DNS 活动,但对于查询而言,数据报因其更低的开销与更好的性能而更受青睐。由于需要可靠传输,区刷新活动必须使用虚电路。

Internet 既支持使用 TCP [RFC-793] 在服务器端口 53(十进制)上进行名称服务器访问,也支持使用 UDP [RFC-768] 在 UDP 端口 53(十进制)上进行数据报访问。

4.2.1. UDP 的使用

使用 UDP 发送的报文使用服务器端口 53(十进制)。

由 UDP 承载的报文被限制为 512 字节(不计 IP 或 UDP 信头)。更长的报文会被截断,并在信头中置位 TC 位。

UDP 不适用于区传送,但它是 Internet 中标准查询的推荐方法。使用 UDP 发送的查询可能会丢失,因此需要一种重传策略。查询或它们的响应可能会因网络或名称服务器中的处理而被重新排序,因此解析器不应当依赖它们按顺序返回。

最佳的 UDP 重传策略将随 Internet 的性能与客户端的需求而变化,但以下建议是合理的:

关于服务器选择与重传策略的更多建议,可参见本备忘录的解析器一节。

4.2.2. TCP 的使用

通过 TCP 连接发送的报文使用服务器端口 53(十进制)。报文前会加上一个两字节长度字段,给出报文长度(不含该两字节长度字段)。该长度字段允许底层处理在开始解析报文之前就装配出完整的报文。

推荐以下连接管理策略:

5. 主文件

主文件(master file)是包含文本形式 RR 的文本文件。由于一个区的内容可以表示为 RR 列表的形式,主文件最常用于定义一个区,尽管它也可以用于列出缓存的内容。因此,本节首先讨论主文件中 RR 的格式,然后讨论用主文件在某台名称服务器中创建区时的特殊考虑。

5.1. 格式

这些文件的格式是一系列条目(entry)。条目主要按行组织,不过可以使用圆括号把一个条目列表延续到跨行边界,文本字面量中也可以包含 CRLF。制表符与空格的任意组合充当构成条目的各个独立项之间的分隔符。主文件中任何一行的结尾都可以跟一条注释。注释以 ";"(分号)开始。

定义了以下条目:

    <blank>[<comment>]

    $ORIGIN <domain-name> [<comment>]

    $INCLUDE <file-name> [<domain-name>] [<comment>]

    <domain-name><rr> [<comment>]

    <blank><rr> [<comment>]

空行(带或不带注释)可以出现在文件中的任何位置。

定义了两个控制条目:$ORIGIN 与 $INCLUDE。$ORIGIN 后跟一个域名,并把当前相对域名的源(origin)重置为所声明的名称。$INCLUDE 把命名的文件插入当前文件,并且可以选择指定一个设置被包含文件相对域名源的域名。$INCLUDE 也可以带注释。请注意,$INCLUDE 条目永远不会改变父文件的相对源,无论被包含文件内部对相对源做了何种更改。

最后两种形式表示 RR。如果某条 RR 的条目以空白开始,则该 RR 被假定为由最后声明的所有者所拥有。如果某条 RR 的条目以 <domain-name> 开始,则所有者名称被重置。

<rr> 的内容采用以下两种形式之一:

    [<TTL>] [<class>] <type> <RDATA>

    [<class>] [<TTL>] <type> <RDATA>

RR 以可选的 TTL 与类字段开始,后跟一个类型以及与该类型和类相适应的 RDATA 字段。类与类型使用标准助记符,TTL 是一个十进制整数。省略的类与 TTL 取值默认为最后一次显式声明的取值。由于类型与类助记符互不相交,解析是唯一的。(请注意,这个顺序与示例中以及实际 RR 中使用的顺序不同;这里给出的顺序允许更容易的解析与默认取值。)

<domain-name> 构成了主文件数据中的很大一部分。域名中的标签表示为字符字符串,并以点分隔。引号约定允许在域名中存储任意字符。以点结尾的域名称为绝对名称(absolute),被视为完整名称。不以点结尾的域名称为相对名称(relative);实际的域名是相对部分与一个源的拼接,该源由 $ORIGIN、$INCLUDE 指定,或作为主文件加载例程的参数给出。当没有可用源时,相对名称是一种错误。

<character-string> 以两种方式之一表示:作为一组不含内部空格的连续字符,或作为以 " 开始并以 " 结尾的字符串。在 " 定界的字符串内部,除 " 本身之外可以出现任何字符," 必须使用 \(反斜杠)转义。

由于这些文件是文本文件,因此需要若干特殊编码来允许加载任意数据。特别是:

编码含义
@一个独立的 @ 用于表示当前的源(origin)。
\X其中 X 是除数字(0-9)以外的任何字符,用于转义该字符,使其特殊含义不生效。例如,可以用 "\." 在标签中放置一个点字符。
\DDD其中每个 D 都是数字,表示与十进制数 DDD 相对应的八位组。得到的八位组被假定为文本,不检查其特殊含义。
( )圆括号用于对跨越行边界的数据进行分组。实际上,圆括号内的行终止不会被识别。
;分号用于开始一条注释;该行的其余部分被忽略。

5.2. 使用主文件定义区

当使用主文件加载一个区时,如果主文件中遇到任何错误,则该操作应当被中止。这样做的理由是:单个错误可能带来广泛的影响。例如,假设定义一次委派(delegation)的 RR 存在语法错误;那么服务器将对子区中的所有名称返回权威名称错误(除非该子区也存在于这台服务器上)。

除确保文件语法正确之外,还应当执行以下若干有效性检查:

  1. 文件中的所有 RR 应当具有相同的类。
  2. 区的顶部应当恰好存在一条 SOA RR。
  3. 如果存在委派且需要胶水信息,则胶水信息应当存在。
  4. 区中权威节点之外出现的信息应当是胶水信息,而不是源错误或类似错误的产物。

5.3. 主文件示例

下面是一个示例文件,它可以用源(origin)ISI.EDU 加载,用来定义 ISI.EDU 区:

@   IN  SOA     VENERA      Action\.domains (
                                 20     ; SERIAL
                                 7200   ; REFRESH
                                 600    ; RETRY
                                 3600000; EXPIRE
                                 60)    ; MINIMUM

        NS      A.ISI.EDU.
        NS      VENERA
        NS      VAXA
        MX      10      VENERA
        MX      20      VAXA

A       A       26.3.0.103

VENERA  A       10.1.0.52
        A       128.9.0.32

VAXA    A       10.2.0.27
        A       128.9.0.33


$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT

其中文件 <SUBSYS>ISI-MAILBOXES.TXT 为:

    MOE     MB      A.ISI.EDU.
    LARRY   MB      A.ISI.EDU.
    CURLEY  MB      A.ISI.EDU.
    STOOGES MG      MOE
            MG      LARRY
            MG      CURLEY

请注意 SOA RR 中 \ 字符的使用:它用于指定负责人邮箱 "Action.domains@E.ISI.EDU"。

6. 名称服务器实现

6.1. 架构

名称服务器的最佳结构将取决于主机操作系统,以及该名称服务器是否通过与解析器集成来支持递归服务、或是否与解析器共享其数据库。本节讨论一台与解析器共享数据库的名称服务器的实现考虑,但其中大多数问题在任意名称服务器中都会存在。

6.1.1. 控制

一台名称服务器必须采用多个并发活动,无论这些活动是作为主机 OS 中的独立任务实现,还是在单个名称服务器程序内部进行多路复用。名称服务器在等待 TCP 数据进行刷新或查询活动期间,阻塞 UDP 请求的服务是绝对不可接受的。类似地,名称服务器不应当试图在不对这类请求进行并行处理的情况下提供递归服务,尽管它可以选择串行化来自单个客户端的请求,或者把来自同一客户端的相同请求视为重复请求。名称服务器不应当在其从主文件重新加载一个区、或把新刷新的区并入其数据库时,大幅度延迟请求。

6.1.2. 数据库

虽然名称服务器实现可以自由选择任何内部数据结构,但建议的结构由三个主要部分组成:

所有这些数据结构都可以用相同的树形结构格式实现,不同部分在节点上链接不同的数据:在目录中,数据是指向区的指针;而在区与缓存数据结构中,数据是 RR。在设计树框架时,设计者应当认识到:查询处理将需要使用不区分大小写的标签比较来遍历树;而且在真实数据中,少数节点的分支因子非常高(100-1000 或更多),但绝大多数节点的分支因子非常低(0-1)。

解决大小写问题的一种方法是把每个节点的标签存储为两部分:标签的一种标准化大小写表示,其中所有 ASCII 字符采用单一大小写;同时配一个位掩码,标明哪些字符实际使用了不同的大小写。分支因子的差异可以通过对节点使用简单链表来处理(直到分支因子超过某个阈值),并在超过阈值后转换为散列结构。无论如何,用于存储树片段的散列结构都必须确保散列函数与流程保留 DNS 的大小写约定。

为数据库的不同部分使用独立结构,是出于若干因素的考虑:

数据库设计的一个重要方面是选择一种让名称服务器能够应对其主机崩溃的结构。名称服务器应当在系统崩溃之间保存的状态信息包括目录结构(包括每个区的刷新状态)以及区数据本身。

6.1.3. 时间

RR 的 TTL 数据与刷新活动的定时数据都依赖于以秒为单位的 32 位计时器。在数据库内部,刷新计时器与缓存数据的 TTL 在概念上「倒计时」,而区中的数据则保持恒定的 TTL。

一个推荐的实现策略是同时以两种方式存储时间:作为相对增量与作为绝对时间。实现这一点的一种方法是:一种类型使用正的 32 位数,另一种使用负数。区中的 RR 使用相对时间;刷新计时器与缓存数据使用绝对时间。绝对数相对于某个已知原点取值,并在放入对查询的响应时转换为相对值。当绝对 TTL 在转换为相对值后为负时,说明数据已过期,应当被忽略。

6.2. 标准查询处理

标准查询处理的主要算法在 [RFC-1034] 中给出。

当处理 QCLASS=* 或某个匹配多个类的其他 QCLASS 的查询时,响应绝不应当是权威的,除非服务器能够保证响应覆盖了所有类。

在组合响应时,那些将被插入附加部分、但会与应答或权威部分中的 RR 重复的 RR,可以从附加部分中省略。

当响应太长而需要截断时,截断应当从响应的末尾开始,并在数据报中向前推进。因此,如果权威部分有任何数据,应答部分就保证是完整的。

SOA 中的 MINIMUM 值应当用于为从区中分发出去的数据的 TTL 设定下限。该下限功能应当在数据被复制进响应时执行。这将允许未来的动态更新协议更改 SOA MINIMUM 字段,而不产生语义歧义。

6.3. 区刷新与重新加载处理

尽管服务器尽了最大努力,它仍可能由于语法错误等原因无法从主文件加载区数据,或者无法在其过期参数之内刷新一个区。在这种情况下,名称服务器应当像它本不该拥有该区那样来应答查询。

如果一台主服务器正在通过 AXFR 向外发送某个区,而传送过程中创建了新版本,则主服务器应当尽可能继续发送旧版本。无论如何,它绝不应当发送一个版本的一部分和另一个版本的一部分。如果无法完成,主服务器应当重置进行区传送的连接。

6.4. 逆查询(可选)

逆查询(inverse query)是 DNS 的一个可选部分。名称服务器不被要求支持任何形式的逆查询。如果一台名称服务器收到一条它不支持的逆查询,它返回一条在信头中设置了「Not Implemented」(未实现)错误的错误响应。虽然逆查询支持是可选的,但所有名称服务器都必须至少能够返回该错误响应。

6.4.1. 逆查询与响应的内容

逆查询反转了标准查询操作所执行的映射;标准查询把域名映射为资源,而逆查询把资源映射为域名。例如,标准查询可以把域名绑定到主机地址;相应的逆查询把主机地址绑定到域名。

逆查询的形式是:报文应答部分中有一条 RR,问题部分为空。查询 RR 的所有者名称与其 TTL 不重要。响应在问题部分承载问题,这些问题标识所有拥有该查询 RR 的、名称服务器所知道的名称。由于没有哪台名称服务器知道整个域名空间,响应永远不能被假定为完整。因此,逆查询主要用于数据库管理与调试活动。逆查询不是把主机地址映射为主机名的可接受方法;请改用 IN-ADDR.ARPA 域。

只要可能,名称服务器应当为逆查询提供不区分大小写的比较。因此,一条询问 "Venera.isi.edu" 的 MX RR 的逆查询,应当与询问 "VENERA.ISI.EDU" 的查询得到相同的响应;一条针对 HINFO RR "IBM-PC UNIX" 的逆查询应当与针对 "IBM-pc unix" 的逆查询产生相同的结果。然而,这一点无法保证,因为名称服务器可能拥有包含字符字符串的 RR,但名称服务器并不知道这些数据是字符。

当名称服务器处理一条逆查询时,它要么返回:

  1. 所指定资源的零个、一个或多个域名,作为问题部分中的 QNAME;
  2. 或者一个错误代码,指示名称服务器不支持所指定资源类型的逆映射。

当对逆查询的响应包含一个或多个 QNAME 时,应答部分中定义该逆查询的 RR 的所有者名称与 TTL 会被修改为与在第一个 QNAME 处找到的一条 RR 完全匹配。

逆查询中返回的 RR 不能用与标准查询应答相同的机制来缓存。原因之一是:一个名称可能具有同类型的多条 RR,而只会出现一条。例如,对一台多穴主机的单个地址的逆查询,可能造成该主机只有单个地址的印象。

6.4.2. 逆查询与响应示例

一条用于检索与 Internet 地址 10.1.0.52 相对应的域名的逆查询的整体结构如下所示:

                         +-----------------------------------------+
           Header        |          OPCODE=IQUERY, ID=997          |
                         +-----------------------------------------+
          Question       |                 <empty>                 |
                         +-----------------------------------------+
           Answer        |        <anyname> A IN 10.1.0.52         |
                         +-----------------------------------------+
          Authority      |                 <empty>                 |
                         +-----------------------------------------+
         Additional      |                 <empty>                 |
                         +-----------------------------------------+

这条查询询问一个其答案为 Internet 风格地址 10.1.0.52 的问题。由于所有者名称未知,任何域名都可以用作占位符(并被忽略)。通常使用一个零八位组来表示根,因为它最小化报文长度。该 RR 的 TTL 不重要。这条查询的响应可能是:

                         +-----------------------------------------+
           Header        |         OPCODE=RESPONSE, ID=997         |
                         +-----------------------------------------+
          Question       |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU |
                         +-----------------------------------------+
           Answer        |  VENERA.ISI.EDU  A IN 10.1.0.52         |
                         +-----------------------------------------+
          Authority      |                 <empty>                 |
                         +-----------------------------------------+
         Additional      |                 <empty>                 |
                         +-----------------------------------------+

请注意,对逆查询的响应中的 QTYPE 与逆查询应答部分中的 TYPE 字段相同。当逆映射不唯一时,对逆查询的响应可能包含多个问题。如果响应中的问题部分不为空,则应答部分中的 RR 会被修改为与第一个 QNAME 处的一条 RR 精确对应(即成为它的精确副本)。

6.4.3. 逆查询处理

支持逆查询的名称服务器可以通过对其数据库的穷举搜索来支持这些操作,但随着数据库规模的增大,这会变得不切实际。另一种方法是根据搜索键反转数据库。

对于支持多个区与大量数据的名称服务器,推荐的方法是为每个区单独反转。当某个特定区在刷新期间发生更改时,只需要重做它的反转即可。

对这种反转的传送支持可能会包含在域名系统的未来版本中,但本版本不支持。

6.5. 完成查询与响应

RFC-882 与 RFC-883 中描述的可选完成服务(completion services)已被删除。重新设计的服务将来可能会可用。

7. 解析器实现

推荐解析器算法的顶层在 [RFC-1034] 中讨论。本节在假定采用本备忘录名称服务器实现一节所建议的数据库结构的前提下,讨论实现细节。

7.1. 把用户请求转换为查询

解析器采取的第一步,是把客户端的请求(以适合本地 OS 的格式表述)转换为针对特定名称处、匹配特定 QTYPE 与 QCLASS 的 RR 的搜索规范。只要可能,QTYPE 与 QCLASS 应当对应单一类型与单一类,因为这会使缓存数据的使用简单得多。这样做的原因在于:缓存中一种类型的数据的存在,并不能确认其他类型数据的存在或不存在,因此要确定唯一可靠的办法是咨询权威来源。如果使用 QCLASS=*,则不会有权威应答可用。

由于解析器若要高效地履行其职能,就必须能够多路复用多个请求,因此每个未决请求通常用某个状态信息块来表示。这个状态块通常包含:

请注意,使用时间戳优于使用当前时间,因为它允许 TTL 为零的 RR 以通常的方式进入缓存,但仍可用于当前请求,即使经过了许多秒的间隔(由于系统负载、查询重传超时等原因)。

解析器响应客户端请求将做的工作量必须受到限制,以防数据库错误(例如循环 CNAME 引用)与操作问题(例如阻止解析器访问其所需名称服务器的网络分区)。虽然限制解析器向某特定名称服务器地址重传某个特定查询的次数的本地限制是必不可少的,但解析器还应当有一个全局的、按请求计数的计数器来限制单个请求上的工作量。该计数器应当被设置为某个初始值,并在解析器执行任何动作(重传超时、重传等)时递减。如果计数器越过零,则请求以临时错误终止。

请注意,如果解析器结构允许一个请求并行启动其他请求(例如,当为一个请求访问名称服务器的需要引起对名称服务器地址的并行解析时),派生的请求应当以较低的计数器启动。这可以防止数据库中的循环引用引发解析器活动的连锁反应。

该结构在请求必须等待外部名称服务器应答时跟踪请求的状态。

7.2. 发送查询

如 [RFC-1034] 所述,解析器的基本任务是制定一个能够回答客户端请求的查询,并把该查询导向能够提供信息的名称服务器。解析器通常只能以 NS RR 的形式得到关于该询问哪些服务器很强提示,并且可能不得不根据 CNAME 修改查询,或根据把解析器引向更接近所需信息的名称服务器的委派响应,修改解析器正在询问的名称服务器集合。除了客户端请求的信息之外,解析器可能还必须动用自身的服务来确定它希望联系的名称服务器的地址。

无论如何,本备忘录所用的模型假定解析器在多个请求之间多路复用注意力,其中一些来自客户端,一些是内部生成的。每个请求由一些状态信息表示,所期望的行为是:解析器以最大化请求被回答的概率、最小化请求所花时间、并避免过多传输的方式向名称服务器发送查询。关键算法利用请求的状态信息来选择下一个要查询的名称服务器地址,并计算一个超时值,若响应未到达则触发下一个动作。下一个动作通常是对另一台服务器的传输,但也可能向客户端返回临时错误。

解析器总是从一张要查询的服务器名称列表(SLIST)开始。该列表将是与解析器所知道的最近祖先区相对应的所有 NS RR。为避免启动问题,解析器应当有一组默认服务器,当它当前没有合适的 NS RR 时使用这些默认服务器。然后,解析器把名称服务器的所有已知地址添加到 SLIST 中,并且当解析器只有名称、没有地址时,可以启动并行请求来获取名称服务器的地址。

为了完成 SLIST 的初始化,解析器把其拥有的任何历史信息附加到 SLIST 中的每个地址上。这通常包括该地址响应时间的某种加权平均值,以及该地址的「命中率」(即该地址对请求作出任何响应的频率)。请注意,这些信息应当按地址保存,而不是按名称服务器保存,因为特定服务器的响应时间与命中率可能因地址而异。还请注意,这些信息实际上特定于「解析器地址 / 服务器地址」这一对组合,因此具有多个地址的解析器可能希望为其每个地址保留独立的历史。该步骤的一部分必须处理没有此类历史的地址;在这种情况下,期望的往返时间应当以 5-10 秒为最坏情况,而对同一本地网络等则采用更低的估计。

请注意,每当跟随一次委派时,解析器算法都会重新初始化 SLIST。

这些信息确立了可用名称服务器地址的局部排序。每次选择一个地址后,状态都应被修改,以防止在尝试完所有其他地址之前再次选择它。每次传输的超时应当比平均预测值大 50-100%,以容许响应的波动。

一些细节问题:

7.3. 处理响应

处理到达的响应数据报的第一步是解析该响应。该流程应当包括:

下一步是把响应与当前的解析器请求相匹配。推荐的策略是先用域信头中的 ID 字段进行初步匹配,然后验证问题部分与当前所需的信息相对应。这要求传输算法在域 ID 字段中留出几个位给某种请求标识符。这一步有几个细节:

7.4. 使用缓存

一般而言,我们期望解析器缓存它在响应中收到的所有数据,因为这些数据可能对回答未来的客户端请求有用。然而,有几种类型的数据不应被缓存:

类似地,当解析器在响应中拥有一组针对某名称的 RR、并想要缓存这些 RR 时,它应当检查其缓存中是否已有 RR。根据具体情况,响应中的数据或缓存中的数据更受偏好,但两者绝不应当被合并。如果响应中的数据来自应答部分中的权威数据,则它总是更受偏好。

8. 邮件支持

域名系统为把邮箱映射为域名定义了一种标准,并提供了两种利用邮箱信息推导邮件路由信息的方法。第一种方法称为邮件交换绑定(mail exchange binding),另一种方法称为邮箱绑定(mailbox binding)。邮箱编码标准与邮件交换绑定是 DNS 官方协议的一部分,是 Internet 中推荐的邮件路由方法。邮箱绑定是一种试验性功能,仍处于开发之中,随时可能更改。

邮箱编码标准假定邮箱名称的形式为 "<local-part>@<mail-domain>"。虽然这些部分的允许语法在各类邮件互联网之间差异很大,但 ARPA Internet 的首选语法在 [RFC-822] 中给出。

DNS 把 <local-part> 编码为单个标签,并把 <mail-domain> 编码为一个域名。来自 <local-part> 的单个标签被前置到来自 <mail-domain> 的域名之前,构成与该邮箱相对应的域名。因此,邮箱 HOSTMASTER@SRI-NIC.ARPA 被映射为域名 HOSTMASTER.SRI-NIC.ARPA。如果 <local-part> 包含点或其他特殊字符,则它在主文件中的表示将需要使用反斜杠转义,以确保域名被正确编码。例如,邮箱 Action.domains@ISI.EDU 将表示为 Action\.domains.ISI.EDU。

8.1. 邮件交换绑定

邮件交换绑定使用邮箱规范的 <mail-domain> 部分来确定邮件应当发送到哪里。<local-part> 甚至不被考虑。[RFC-974] 详细规定了这种方法,在尝试使用邮件交换支持之前应当阅读该文档。

这种方法的一个优点是:它以查找函数中增加一层间接为代价,把邮件目标命名与支持邮件服务的主机解耦。然而,这增加的层次应当消除在 <local-part> 中进行复杂的 "%"、"!" 等编码的需要。

该方法的要点是:<mail-domain> 被用作域名来定位 MX 类型的 RR,这些 RR 列出愿意为 <mail-domain> 接受邮件的主机,并带有偏好值,偏好值按照 <mail-domain> 的管理员所指定的顺序对主机进行排序。

在本备忘录中,<mail-domain> ISI.EDU 被用于示例,主机 VENERA.ISI.EDU 与 VAXA.ISI.EDU 作为 ISI.EDU 的邮件交换。如果一台邮件程序有一封发给 Mockapetris@ISI.EDU 的邮件,它将通过查找 ISI.EDU 的 MX RR 来路由它。ISI.EDU 处的 MX RR 指名 VENERA.ISI.EDU 与 VAXA.ISI.EDU,类型 A 查询可以找到主机地址。

8.2. 邮箱绑定(试验性)

在邮箱绑定中,邮件程序使用完整的邮件目标规范来构造一个域名。该邮箱的编码域名被用作 QTYPE=MAILB 查询中的 QNAME 字段。

该查询有几种可能的结果:

  1. 该查询可以返回一个名称错误,指示该邮箱作为域名不存在。

    从长远看,这将表明指定的邮箱不存在。然而,在邮箱绑定的使用普及之前,应当把这一错误条件解释为:由全局部分所标识的组织不支持邮箱绑定。此时适当的做法是回退到交换绑定。

  2. 该查询可以返回一条邮件改名(MR)RR。

    MR RR 在其 RDATA 字段中携带新的邮箱规范。邮件程序应当用新邮箱替换旧邮箱并重试该操作。

  3. 该查询可以返回一条 MB RR。

    MB RR 在其 RDATA 字段中携带一台主机的域名。邮件程序应当通过任何适用的协议(例如 SMTP)把消息投递给那台主机。

  4. 该查询可以返回一条或多条邮件组(MG)RR。

    这种状况意味着该邮箱实际上是一个邮件列表或邮件组,而不是单个邮箱。每条 MG RR 的 RDATA 字段标识一个属于该组成员的邮箱。邮件程序应当把消息的一份副本投递给每个成员。

  5. 该查询可以同时返回一条 MB RR 与一条或多条 MG RR。

    这种状况意味着该邮箱实际上是一个邮件列表。邮件程序可以要么把消息投递给 MB RR 所指定的主机(由它再向所有成员投递),要么自己使用 MG RR 进行扩展。

在任何这些情况下,响应都可能包含一条邮件信息(MINFO)RR。该 RR 通常与邮件组相关联,但与 MB 一起使用也是合法的。MINFO RR 标识两个邮箱。其中一个标识原始邮箱名称的负责人。该邮箱应当用于请求加入邮件组等事宜。MINFO RR 中的第二个邮箱名称标识一个应当接收邮件失败错误消息的邮箱。这特别适用于邮件列表——当成员名称出现错误时,应当向除向列表发送消息的人之外的某个人报告。

将来可能向该 RR 添加新字段。

9. 参考文献与书目