4. 名称服务器
4.1. 引言
名称服务器是构成域名数据库的信息存储库. 数据库被划分为称为区域 (zones) 的部分, 这些部分分布在各名称服务器之间. 虽然名称服务器可以有几个可选功能和数据来源, 但名称服务器的基本任务是使用其区域中的数据回答查询. 按照设计, 名称服务器可以以简单的方式回答查询; 响应始终可以仅使用本地数据生成, 要么包含问题的答案, 要么引用到 "更接近" 所需信息的其他名称服务器.
给定区域将从多个名称服务器获得, 以确保在主机或通信链路故障时的可用性. 按照管理规定, 我们要求每个区域至少在两台服务器上可用, 许多区域具有更多的冗余.
给定名称服务器通常支持一个或多个区域, 但这只给它提供了关于域树一小部分的权威信息. 它也可能有关于树其他部分的一些缓存的非权威数据. 名称服务器对其查询响应进行标记, 以便请求者可以判断响应是否来自权威数据.
4.2. 数据库如何划分为区域
域名数据库以两种方式分区: 按类 (class), 以及在名称空间中节点之间进行 "切割".
类分区
类分区很简单. 任何类的数据库都与所有其他类分开组织、委托和维护. 由于按照惯例, 所有类的名称空间相同, 因此可以将独立的类视为并行名称空间树的数组. 请注意, 附加到节点的数据对于这些不同的并行类将有所不同. 创建新类的最常见原因是需要现有类型的新数据格式, 或者希望对现有名称空间进行单独管理的版本.
区域切割
在一个类中, 可以在任意两个相邻节点之间对名称空间进行 "切割". 完成所有切割后, 每组连接的名称空间就是一个独立的区域. 该区域被称为对连接区域中所有名称具有权威性. 请注意, 名称空间中的 "切割" 对于不同的类可能在不同的位置, 名称服务器可能不同等.
这些规则意味着每个区域至少有一个节点, 因此有一个域名, 它对此具有权威性, 并且特定区域中的所有节点都是连接的. 给定树结构, 每个区域都有一个最高节点, 它比区域中的任何其他节点更接近根. 此节点的名称通常用于标识区域.
虽然可以 (但不特别有用) 将名称空间分区, 使每个域名都在单独的区域中, 或者所有节点都在单个区域中. 相反, 数据库在特定组织想要接管子树控制的点进行分区. 一旦组织控制了自己的区域, 它就可以单方面更改区域中的数据, 增长连接到区域的新树部分, 删除现有节点, 或在其区域下委托新的子区域.
如果组织有子结构, 它可能希望进行进一步的内部分区以实现名称空间控制的嵌套委托. 在某些情况下, 这种划分纯粹是为了使数据库维护更加方便.
4.2.1. 技术注意事项
描述区域的数据有四个主要部分:
- 区域内所有节点的权威数据.
- 定义区域顶部节点的数据 (可以视为权威数据的一部分).
- 描述委托子区域的数据, 即区域底部周围的切割.
- 允许访问子区域名称服务器的数据 (有时称为 "粘合 (glue)" 数据).
所有这些数据都以 RR 的形式表示, 因此区域可以用一组 RR 完整描述. 整个区域可以通过传输 RR 在名称服务器之间传输, 可以在一系列消息中携带, 也可以通过 FTP 传输作为文本表示的主文件.
权威数据
区域的权威数据就是附加到区域顶部节点到叶节点或区域底部边缘切割上方节点的所有节点的所有 RR.
虽然逻辑上是权威数据的一部分, 但描述区域顶部节点的 RR 对区域管理特别重要. 这些 RR 有两种类型: 名称服务器 RR, 每个 RR 列出区域的一个服务器; 以及描述区域管理参数的单个 SOA RR.
委托数据
描述区域底部切割的 RR 是命名子区域服务器的 NS RR. 由于切割在节点之间, 这些 RR 不是区域权威数据的一部分, 应与子区域顶部节点中相应的 RR 完全相同. 由于名称服务器始终与区域边界关联, NS RR 只在作为某个区域顶部节点的节点处找到. 在构成区域的数据中, NS RR 在区域顶部节点处找到 (并且是权威的), 在区域底部周围的切割处找到 (在那里它们不是权威的), 但从不在两者之间.
粘合数据
区域结构的目标之一是任何区域都拥有与任何子区域的名称服务器建立通信所需的所有数据. 也就是说, 父区域拥有访问其子区域服务器所需的所有信息. 命名子区域服务器的 NS RR 通常不足以完成此任务, 因为它们命名了服务器, 但没有给出其地址. 特别是, 如果名称服务器的名称本身在子区域中, 我们可能面临这样的情况: NS RR 告诉我们, 为了了解名称服务器的地址, 我们应该使用我们希望了解的地址联系该服务器. 为了解决这个问题, 区域包含 "粘合" RR, 它们不是权威数据的一部分, 是服务器的地址 RR. 这些 RR 只有在名称服务器的名称 "低于" 切割时才是必要的, 并且只作为引用响应的一部分使用.
4.2.2. 管理注意事项
当某个组织想要控制自己的域时, 第一步是确定适当的父区域, 并让父区域的所有者同意委托控制. 虽然在树中可以在哪里进行此操作没有特定的技术限制, 但 [RFC-1032] 中讨论了一些处理顶层组织的管理分组, 中间层区域可以自由创建自己的规则. 例如, 一所大学可能选择使用单个区域, 而另一所大学可能选择按专门用于各个系或学院的子区域组织. [RFC-1033] 列出了可用的 DNS 软件并讨论了管理程序.
一旦选择了新子区域的适当名称, 应要求新所有者展示冗余名称服务器支持. 请注意, 没有要求区域的服务器驻留在该域中具有名称的主机上. 在许多情况下, 如果区域的服务器广泛分布而不是在管理该区域的同一组织控制的物理设施内, 则区域对整个互联网更易访问. 例如, 在当前 DNS 中, 英国 (UK 域) 的名称服务器之一位于美国. 这允许美国主机在不使用有限的跨大西洋带宽的情况下获取英国数据.
作为最后的安装步骤, 使委托生效所需的委托 NS RR 和粘合 RR 应添加到父区域. 两个区域的管理员应确保标记切割两侧的 NS 和粘合 RR 是一致的并保持一致.
4.3. 名称服务器内部机制
4.3.1. 查询与响应
名称服务器的主要活动是回答标准查询. 查询及其响应都以 [RFC-1035] 中描述的标准消息格式携带. 查询包含 QTYPE, QCLASS 和 QNAME, 描述所需信息的类型和类以及感兴趣的名称.
名称服务器回答查询的方式取决于它是否以递归模式运行:
-
非递归模式: 服务器最简单的模式是非递归模式, 因为它只能使用本地信息回答查询: 响应包含错误、答案或对 "更接近" 答案的某个其他服务器的引用. 所有名称服务器必须实现非递归查询.
-
递归模式: 客户端最简单的模式是递归模式, 因为在此模式下名称服务器充当解析器的角色, 返回错误或答案, 但从不返回引用. 此服务在名称服务器中是可选的, 名称服务器也可以选择限制可以使用递归模式的客户端.
何时使用递归服务
递归服务在以下几种情况下很有帮助:
- 相对简单的请求者, 缺乏使用直接答案以外任何内容的能力.
- 需要跨越协议或其他边界的请求, 可以发送到可以充当中介的服务器.
- 我们希望集中缓存而不是为每个客户端单独缓存的网络.
如果请求者能够追踪引用并对有助于未来请求的信息感兴趣, 则非递归服务是合适的.
递归协商
递归模式的使用仅限于客户端和名称服务器都同意使用的情况. 协议通过查询和响应消息中的两个位进行协商:
-
递归可用 (RA) 位 由名称服务器在所有响应中设置或清除. 如果名称服务器愿意为客户端提供递归服务, 则该位为真, 无论客户端是否请求递归服务. 也就是说, RA 表示可用性而不是使用.
-
查询包含期望递归 (RD) 位. 此位指定请求者是否希望对此查询进行递归服务. 客户端可以向任何名称服务器请求递归服务, 但只应依赖于之前发送过 RA 的服务器, 或通过私人协议或 DNS 协议之外的其他方式同意提供服务的服务器.
当设置了 RD 的查询到达愿意提供递归服务的服务器时, 就会发生递归模式; 客户端可以通过检查回复中 RA 和 RD 都已设置来验证是否使用了递归模式. 请注意, 名称服务器不应在未通过 RD 请求的情况下执行递归服务, 因为这会干扰名称服务器及其数据库的故障排除.
响应类型
如果请求并可用递归服务, 对查询的递归响应将是以下之一:
- 查询的答案, 可能在答案之前有一个或多个 CNAME RR, 指定在到达答案途中遇到的别名.
- 名称错误, 表示名称不存在. 这可能包括 CNAME RR, 表示原始查询名称是不存在名称的别名.
- 临时错误指示.
如果未请求或不可用递归服务, 非递归响应将是以下之一:
- 权威名称错误, 表示名称不存在.
- 临时错误指示.
- 以下某种组合:
- 回答问题的 RR, 以及数据来自区域还是缓存的指示.
- 对具有比发送回复的服务器更接近名称的祖先区域的名称服务器的引用.
- 名称服务器认为对请求者有用的 RR.
4.3.2. 算法
名称服务器使用的实际算法将取决于本地操作系统和用于存储 RR 的数据结构. 以下算法假设 RR 组织在几个树结构中, 每个区域一个, 另一个用于缓存:
-
根据名称服务器是否愿意提供递归服务, 在响应中设置或清除递归可用值. 如果递归服务可用且通过查询中的 RD 位请求, 则转到步骤 5, 否则转到步骤 2.
-
搜索可用区域, 查找最接近 QNAME 祖先的区域. 如果找到这样的区域, 转到步骤 3, 否则转到步骤 4.
-
在区域中逐标签向下匹配. 匹配过程可以以几种方式终止:
a. 如果 QNAME 的整体匹配, 我们找到了节点.
如果节点上的数据是 CNAME, 且 QTYPE 与 CNAME 不匹配, 将 CNAME RR 复制到响应的应答节, 将 QNAME 更改为 CNAME RR 中的规范名称, 然后返回步骤 1.
否则, 将所有匹配 QTYPE 的 RR 复制到应答节并转到步骤 6.
b. 如果匹配会将我们带出权威数据, 我们有一个引用. 当我们遇到带有 NS RR 的节点, 标记区域底部的切割时, 就会发生这种情况.
将子区域的 NS RR 复制到回复的权威节. 将任何可用地址放入附加节, 如果地址无法从权威数据或缓存获得, 则使用粘合 RR. 转到步骤 4.
c. 如果在某个标签处, 匹配不可能 (即对应的标签不存在), 查看 "*" 标签是否存在.
如果 "*" 标签不存在, 检查我们正在查找的名称是查询中的原始 QNAME 还是由于 CNAME 而跟踪的名称. 如果名称是原始的, 在响应中设置权威名称错误并退出. 否则直接退出.
如果 "" 标签确实存在, 将该节点的 RR 与 QTYPE 匹配. 如果有匹配, 将它们复制到应答节, 但将 RR 的所有者设置为 QNAME, 而不是带有 "" 标签的节点. 转到步骤 6.
-
在缓存中向下匹配. 如果在缓存中找到 QNAME, 将附加到它的所有匹配 QTYPE 的 RR 复制到应答节. 如果没有来自权威数据的委托, 从缓存中查找最佳委托, 并将其放入权威节. 转到步骤 6.
-
使用本地解析器 或其算法的副本 (参见本备忘录的解析器部分) 来回答查询. 将结果 (包括任何中间 CNAME) 存储在响应的应答节中.
-
仅使用本地数据, 尝试将可能对查询附加节有用的其他 RR 添加进去. 退出.
4.3.3. 通配符
在前面的算法中, 对所有者名称以标签 "*" 开头的 RR 给予了特殊处理. 这样的 RR 称为通配符. 通配符 RR 可以被视为合成 RR 的指令. 当满足适当条件时, 名称服务器创建所有者名称等于查询名称且内容取自通配符 RR 的 RR.
此功能最常用于创建用于将邮件从互联网转发到其他邮件系统的区域. 一般思路是, 该区域中在查询中呈现给服务器的任何名称都将被假定存在, 具有某些属性, 除非存在明确的相反证据. 请注意, 此处使用区域而不是域是有意的; 此类默认值不会跨越区域边界传播, 尽管子区域可以通过设置类似的默认值来实现该外观.
通配符语法和语义
通配符 RR 的内容遵循 RR 的通常规则和格式. 区域中的通配符有一个所有者名称, 控制它们将匹配的查询名称. 通配符 RR 的所有者名称形式为 *.<anydomain>, 其中 <anydomain> 是任何域名. <anydomain> 不应包含其他 * 标签, 并且应在区域的权威数据中. 通配符可能适用于 <anydomain> 的后代, 但不适用于 <anydomain> 本身. 另一种看法是 "*" 标签始终匹配至少一个完整标签, 有时更多, 但始终是完整标签.
通配符不适用的情况
通配符 RR 不适用于:
-
当查询在另一个区域时. 也就是说, 委托取消通配符默认值.
-
当查询名称或通配符域和查询名称之间的名称已知存在时. 例如, 如果通配符 RR 的所有者名称为 "*.X", 且区域还包含附加到 B.X 的 RR, 则通配符将适用于名称 Z.X 的查询 (假设没有 Z.X 的明确信息), 但不适用于 B.X, A.B.X 或 X.
查询名称中出现的 * 标签没有特殊效果, 但可用于测试权威区域中的通配符; 这样的查询是获取包含所有者名称中带有 * 的 RR 的响应的唯一方法. 此类查询的结果不应被缓存.
请注意, 通配符 RR 的内容在用于合成 RR 时不会被修改.
通配符示例
为了说明通配符 RR 的使用, 假设一家拥有大型非 IP/TCP 网络的大公司想要创建一个邮件网关. 如果公司名为 X.COM, 且支持 IP/TCP 的网关机器名为 A.X.COM, 则可以在 COM 区域中输入以下 RR:
X.COM MX 10 A.X.COM
*.X.COM MX 10 A.X.COM
A.X.COM A 1.2.3.4
A.X.COM MX 10 A.X.COM
*.A.X.COM MX 10 A.X.COM
这将导致对以 X.COM 结尾的任何域名的任何 MX 查询返回指向 A.X.COM 的 MX RR. 需要两个通配符 RR, 因为 *.X.COM 处通配符的效果在 A.X.COM 子树中被 A.X.COM 的明确数据所抑制. 还请注意, X.COM 和 A.X.COM 处的明确 MX 数据是必需的, 并且上述 RR 中没有一个会匹配查询名称 XX.COM.
4.3.4. 否定响应缓存 (可选)
DNS 提供了一种可选服务, 允许名称服务器分发带有 TTL 的否定结果, 解析器可以缓存这些结果. 例如, 名称服务器可以随名称错误指示一起分发 TTL, 接收此类信息的解析器被允许在 TTL 期间假设该名称不存在, 而无需查询权威数据. 类似地, 解析器可以使用匹配多种类型的 QTYPE 进行查询, 并缓存某些类型不存在的事实.
此功能在实现使用搜索列表的命名简写的系统中特别重要, 因为流行的简写 (恰好需要搜索列表末尾附近的后缀) 每次使用时都会生成多个名称错误.
实现方法
方法是名称服务器可以在响应为权威时向响应的附加节添加 SOA RR. SOA 必须是应答节中权威数据来源的区域的 SOA, 或者如果适用则是名称错误. SOA 的 MINIMUM 字段控制否定结果可以缓存的时间长度.
请注意, 在某些情况下, 应答节可能包含多个所有者名称. 在这种情况下, SOA 机制应仅用于与 QNAME 匹配的数据, 这是本节中唯一的权威数据.
名称服务器和解析器不应尝试将 SOA 添加到非权威响应的附加节, 或尝试推断权威响应中未直接说明的结果. 这有几个原因, 包括: 缓存信息通常不足以匹配 RR 及其区域名称, SOA RR 可能由于直接 SOA 查询而被缓存, 以及名称服务器不需要在权威节中输出 SOA.
此功能是可选的, 尽管预计将来会成为标准协议的一部分. 名称服务器不需要在所有权威响应中添加 SOA RR, 解析器也不需要缓存否定结果. 两者都是推荐的. 所有解析器和递归名称服务器都需要至少能够在响应中存在 SOA RR 时忽略它.
还提出了一些将使用此功能的实验. 其思路是, 如果已知缓存数据来自特定区域, 并且获得了区域 SOA 的权威副本, 并且区域的 SERIAL 自数据被缓存以来没有改变, 则如果缓存数据的 TTL 小于区域 MINIMUM 值, 可以将其重置为区域 MINIMUM 值. 此用法仅供规划目的提及, 目前不推荐.
4.3.5. 区域维护与传输
区域管理员的工作之一是维护对区域具有权威性的所有名称服务器上的区域. 当不可避免地进行更改时, 必须将其分发到所有名称服务器. 虽然可以使用 FTP 或其他临时程序完成此分发, 但首选方法是 DNS 协议的区域传输部分.
区域传输模型
自动区域传输或刷新的一般模型是, 其中一个名称服务器是区域的主服务器 (master) 或主要服务器 (primary). 更改在主服务器上协调, 通常通过编辑区域的主文件. 编辑后, 管理员向主服务器发出信号以加载新区域. 区域的其他非主服务器或辅助服务器 (secondary) 定期检查更改 (以可选择的间隔), 并在进行更改时获取新的区域副本.
通过 SERIAL 检测更改
为了检测更改, 辅助服务器只需检查区域 SOA 的 SERIAL 字段. 除了进行的任何其他更改外, 每当对区域进行任何更改时, 区域 SOA 中的 SERIAL 字段总是会递增. 递增可以是简单的增量, 也可以基于主文件的写入日期和时间等. 目的是通过比较序列号来确定区域的两个副本中哪个更新. 序列号递增和比较使用序列空间算法, 因此理论上对区域更新速度有限制, 基本上是旧副本必须在序列号覆盖其 32 位范围的一半之前消亡. 实际上, 唯一的关注点是比较操作能正确处理最正和最负 32 位数字之间边界附近的比较.
区域传输的 SOA 参数
辅助服务器的定期轮询由区域 SOA RR 中的参数控制, 这些参数设置最小可接受轮询间隔. 这些参数称为 REFRESH, RETRY 和 EXPIRE. 每当在辅助服务器中加载新区域时, 辅助服务器在向主服务器检查新序列号之前等待 REFRESH 秒. 如果此检查无法完成, 则每 RETRY 秒启动新的检查. 检查是对主服务器的区域 SOA RR 的简单查询. 如果辅助服务器区域副本中的序列字段等于主服务器返回的序列, 则没有发生更改, 并重新启动 REFRESH 间隔等待. 如果辅助服务器发现在 EXPIRE 间隔内无法执行序列检查, 则必须假设其区域副本已过时并丢弃它.
AXFR 区域传输
当轮询显示区域已更改时, 辅助服务器必须通过对区域的 AXFR 请求来请求区域传输. AXFR 可能导致错误 (如拒绝), 但通常由一系列响应消息回答. 第一条和最后一条消息必须包含区域顶部权威节点的数据. 中间消息携带区域中的所有其他 RR, 包括权威和非权威 RR. 消息流允许辅助服务器构建区域的副本. 由于准确性至关重要, AXFR 请求必须使用 TCP 或其他可靠协议.
每个辅助服务器都需要对主服务器执行以下操作, 但也可以选择对其他辅助服务器执行这些操作. 当主服务器由于主机停机或网络问题而不可用时, 或者当辅助服务器与 "中间" 辅助服务器的网络访问比与主服务器的网络访问更好时, 此策略可以改善传输过程.