4. Name Servers (名称服务器)
本章深入探讨DNS名称服务器的内部工作原理、区域管理和查询算法。
4.1. Introduction (简介)
名称服务器是构成域数据库的信息存储库。数据库被划分为称为区域 (zones) 的部分,这些区域分布在名称服务器之间。
基本任务
虽然名称服务器可以有几个可选功能和数据源,但名称服务器的基本任务是使用其区域中的数据回答查询。
设计特点:
- 名称服务器可以以简单的方式回答查询
- 响应始终可以仅使用本地数据生成
- 响应包含问题的答案或对"更接近"所需信息的其他名称服务器的引用
冗余性要求
给定区域将从多个名称服务器可用,以确保其在主机或通信链路故障时的可用性。
要求:
- ✅ 通过管理规定,每个区域必须在至少两个服务器上可用
- ✅ 许多区域的冗余度超过此要求
示例架构:
example.com 区域
├── ns1.example.com (主服务器)
├── ns2.example.com (从服务器1)
└── ns3.backup.net (从服务器2,异地)
权威性和缓存
给定名称服务器通常支持一个或多个区域,但这仅为其提供有关域树小部分的权威信息。
数据类型:
-
权威数据 (Authoritative Data)
- 服务器负责的区域数据
- 标记为权威响应
-
缓存数据 (Cached Data)
- 关于树其他部分的非权威数据
- 标记为非权威响应
响应标记:
查询 www.example.com
→ 权威服务器: AA=1 (Authoritative Answer)
→ 缓存数据: AA=0 (Non-Authoritative)
4.2. How the database is divided into zones (数据库如何划分为区域)
域数据库以两种方式分区:按类 (class) 和在名称空间中节点之间的切割 (cuts)。
按类分区 (Class Partition)
类分区很简单。任何类的数据库都与所有其他类分开组织、委派和维护。
特点:
- 按照惯例,所有类的名称空间相同
- 可以将单独的类视为并行名称空间树的数组
- 附加到节点的数据对于这些不同的并行类将不同
创建新类的原因:
- 现有类型需要新的数据格式
- 希望有现有名称空间的单独管理版本
可视化:
IN类 (Internet):
.
/|\
a b c
CH类 (Chaos):
.
/|\
a b c
HS类 (Hesiod):
.
/|\
a b c
按切割分区 (Cuts in Name Space)
在类内,可以在任意两个相邻节点之间进行"切割"。
区域定义:
- 进行所有切割后,每组连接的名称空间是一个单独的区域
- 区域被称为对连接区域中所有名称具有权威性
- 名称空间中的"切割"对于不同类可能在不同位置
规则:
- ✅ 每个区域至少有一个节点,因此有域名
- ✅ 特定区域中的所有节点都是连接的
- ⭐ 每个区域都有一个最高节点,它比区域中任何其他节点更接近根
- ⭐ 此节点的名称通常用于标识区域
区域示例:
. (根区域)
|
+---+---+
| |
com org (com区域从这里开始)
|
example (example.com区域从这里开始)
|
+--+--+
| |
www mail (都在example.com区域内)
委派控制 (Delegation Control)
数据库在特定组织想要接管子树控制权的点进行分区。
组织控制权: 一旦组织控制其自己的区域,它可以单方面:
- ✅ 更改区域中的数据
- ✅ 增长连接到区域的新树部分
- ✅ 删除现有节点
- ✅ 在其区域下委派新的子区域
内部分区:
- 如果组织有子结构,可能希望进行进一步的内部分区
- 实现名称空间控制的嵌套委派
- 有些划分纯粹是为了使数据库维护更方便
4.2.1. Technical considerations (技术考虑)
区域数据的四个主要部分
描述区域的数据有四个主要部分:
1. 区域内所有节点的权威数据 (Authoritative Data)
区域顶部节点到叶节点或区域底部边缘切割上方节点的所有RR。
示例:
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (...)
example.com. 3600 IN NS ns1.example.com.
example.com. 3600 IN NS ns2.example.com.
example.com. 3600 IN A 93.184.216.34
www.example.com. 3600 IN A 93.184.216.34
mail.example.com. 3600 IN A 93.184.216.35
2. 定义区域顶部节点的数据 (Top Node Data)
关键RR类型:
NS记录: 列出区域的所有服务器,每个服务器一个RR
example.com. 3600 IN NS ns1.example.com.
example.com. 3600 IN NS ns2.example.com.
SOA记录: 描述区域管理参数的单个记录
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (
2024010101 ; Serial (序列号)
3600 ; Refresh (刷新间隔)
1800 ; Retry (重试间隔)
604800 ; Expire (过期时间)
86400 ) ; Minimum TTL (最小TTL)
SOA字段说明:
- Serial: 区域的版本号,用于同步
- Refresh: 从服务器检查更新的间隔
- Retry: 刷新失败后的重试间隔
- Expire: 如果无法刷新,何时停止提供区域
- Minimum TTL: 否定响应的缓存时间
3. 描述委派子区域的数据 (Delegated Subzones)
描述区域底部边缘切割的NS RR,命名子区域的服务器。
特点:
- 这些RR不是区域权威数据的一部分
- 应该与子区域顶部节点中的相应RR完全相同
示例:
; 父区域 (example.com)
sub.example.com. 3600 IN NS ns1.sub.example.com.
sub.example.com. 3600 IN NS ns2.sub.example.com.
; 子区域 (sub.example.com) - 应该有相同的NS记录
位置规则:
- NS RR仅在作为某个区域顶部节点的节点处找到
- 在区域数据中,NS RR位于:
- ✅ 区域的顶部节点 (权威的)
- ✅ 区域底部边缘的切割处 (非权威的)
- ❌ 从不在两者之间
4. 允许访问子区域名称服务器的数据 (Glue Data)
问题: 子区域的NS RR命名服务器,但不提供地址
场景: 如果名称服务器的名称本身在子区域中,我们可能面临循环依赖:
要查询 ns1.sub.example.com 的地址
→ 需要联系 sub.example.com 的服务器
→ 但 sub.example.com 的服务器就是 ns1.sub.example.com
→ 循环!
解决方案: "粘合"记录 (Glue Records)
; 父区域中的委派
sub.example.com. 3600 IN NS ns1.sub.example.com.
sub.example.com. 3600 IN NS ns2.sub.example.com.
; 粘合记录 - 打破循环依赖
ns1.sub.example.com. 3600 IN A 192.0.2.1
ns2.sub.example.com. 3600 IN A 192.0.2.2
规则:
- 仅当名称服务器的名称在切割"下方"时才需要
- 仅作为引用响应的一部分使用
- 不是权威数据的一部分
区域传输
方法:
- 通过传输RR在名称服务器之间传输整个区域
- 可以在一系列消息中传输
- 或通过FTP传输主文件 (文本表示)
区域文件示例:
$ORIGIN example.com.
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2024010101 3600 1800 604800 86400 )
IN NS ns1.example.com.
IN NS ns2.example.com.
IN MX 10 mail.example.com.
IN A 93.184.216.34
www IN A 93.184.216.34
mail IN A 93.184.216.35
4.2.2. Administrative considerations (管理考虑)
创建新子区域的步骤
步骤1: 识别父区域
当某个组织想要控制其自己的域时,第一步是识别适当的父区域,并让父区域的所有者同意委派控制权。
约束:
- 技术上,树中何处可以完成此操作没有特定限制
- 管理上,有一些分组:
- 顶层组织在 [RFC-1032] 中讨论
- 中级区域可以自由创建自己的规则
组织策略示例:
大学A: 使用单个区域
university-a.edu
大学B: 按部门组织子区域
university-b.edu
├── cs.university-b.edu (计算机科学)
├── ee.university-b.edu (电气工程)
└── lib.university-b.edu (图书馆)
步骤2: 演示冗余支持
新所有者应该被要求演示冗余的名称服务器支持。
重要概念:
- 区域的服务器不需要驻留在该域中有名称的主机中
- 如果服务器广泛分布,区域通常对整个互联网更易访问
- 而不是在管理区域的同一组织控制的物理设施内
地理分布示例:
uk域 (United Kingdom)
├── ns1.uk (英国本地)
├── ns2.uk (英国本地)
└── ns3.usa.net (美国) ← 提供跨大西洋冗余
好处:
- 美国主机可以获取UK数据而无需使用有限的跨大西洋带宽
- 提高全球可访问性和性能
步骤3: 添加委派记录
作为最后的安装步骤,应将委派NS RR和粘合RR添加到父区域。
一致性要求:
- 两个区域的管理员应确保标记切割两侧的NS和粘合RR一致
- 并保持一致
委派配置:
; 父区域 (example.com) 配置
sub.example.com. 86400 IN NS ns1.sub.example.com.
sub.example.com. 86400 IN NS ns2.sub.example.com.
ns1.sub.example.com. 86400 IN A 192.0.2.1
ns2.sub.example.com. 86400 IN A 192.0.2.2
; 子区域 (sub.example.com) 配置
@ IN SOA ns1.sub.example.com. admin.sub.example.com. (...)
IN NS ns1.sub.example.com.
IN NS ns2.sub.example.com.
4.3. Name server internals (名称服务器内部)
4.3.1. Queries and responses (查询和响应)
名称服务器的主要活动是回答标准查询。
查询组件:
- QTYPE: 所需信息的类型
- QCLASS: 所需信息的类
- QNAME: 感兴趣的名称
查询模式
非递归模式 (Non-Recursive Mode)
特点:
- 服务器最简单的模式
- 仅使用本地信息回答查询
- 响应包含:错误、答案或引用
要求: ✅ 所有名称服务器必须实现非递归查询
响应类型:
1. 权威名称错误 (NXDOMAIN)
2. 临时错误
3. 组合:
- 回答问题的RR + 数据来源指示
- 对更接近祖先区域的名称服务器的引用
- 服务器认为有用的其他RR
递归模式 (Recursive Mode)
特点:
- 客户端最简单的模式
- 名称服务器充当解析器角色
- 返回错误或答案,从不引用
要求: ⚠️ 此服务在名称服务器中是可选的
服务器可以选择:
- 限制可以使用递归模式的客户端
- 完全不提供递归服务
响应类型:
1. 查询的答案 (可能前面有CNAME RR)
2. 名称错误 (NXDOMAIN)
3. 临时错误指示
递归服务的有用场景
- 简单请求者: 缺乏使用直接答案以外的能力
- 协议桥接: 需要跨越协议或其他边界
- 集中缓存: 希望集中缓存而不是每个客户端单独缓存的网络
递归控制位
RA位 (Recursion Available):
- 在所有响应中由名称服务器设置或清除
- 如果名称服务器愿意为客户端提供递归服务,则为真
- 无论客户端是否请求递归服务
- RA信号可用性而不是使用
RD位 (Recursion Desired):
- 查询包含的位
- 指定请求者是否想要此查询的递归服务
- 客户端可以从任何名称服务器请求递归服务
- 但应该仅依赖从先前发送过RA的服务器接收它
协商机制:
客户端查询:
RD=1 (我想要递归)
↓
服务器响应:
RA=1, RD=1 → 递归模式已使用 ✓
RA=0, RD=1 → 递归不可用,返回引用
重要规则:
- 除非通过RD请求,否则名称服务器不应执行递归服务
- 这避免干扰名称服务器及其数据库的故障排除
4.3.2. Algorithm (算法)
名称服务器使用的实际算法将取决于本地OS和用于存储RR的数据结构。
标准查询算法
以下算法假设RR组织在几个树结构中,每个区域一个,另一个用于缓存:
步骤1: 设置递归可用位
根据名称服务器是否愿意提供递归服务,在响应中设置或清除RA值。
如果 (递归可用 AND 通过查询中的RD位请求):
转到步骤5 (递归处理)
否则:
转到步骤2 (非递归处理)
步骤2: 搜索可用区域
搜索可用区域以查找最接近QNAME祖先的区域。
如果找到这样的区域:
转到步骤3
否则:
转到步骤4
步骤3: 在区域中逐标签匹配
从区域向下,逐标签匹配。匹配过程可以以几种方式终止:
情况a: 匹配整个QNAME
找到了节点。
如果节点的数据是CNAME AND QTYPE不匹配CNAME:
1. 将CNAME RR复制到响应的答案部分
2. 将QNAME更改为CNAME RR中的规范名称
3. 返回步骤1
否则:
1. 将所有匹配QTYPE的RR复制到答案部分
2. 转到步骤6
情况b: 匹配将使我们离开权威数据
这是一个引用。当遇到带有NS RR的节点标记区域底部边缘的切割时发生。
1. 将子区域的NS RR复制到响应的权威部分
2. 将可用地址放入附加部分
- 使用粘合RR (如果地址不可从权威数据或缓存获得)
3. 转到步骤4
情况c: 在某个标签处匹配不可能
查找通配符。
如果"*"标签不存在:
如果我们查找的名称是查询中的原始QNAME:
在响应中设置权威名称错误并退出
否则:
只是退出 (跟随CNAME时)
如果"*"标签存在:
1. 将该节点的RR与QTYPE匹配
2. 如果有匹配,复制到答案部分
3. 设置RR的所有者为QNAME (不是带"*"标签的节点)
4. 转到步骤6
步骤4: 在缓存中匹配
开始在缓存中向下匹配。
如果在缓存中找到QNAME:
1. 将附加到它的所有匹配QTYPE的RR复制到答案部分
2. 如果没有来自权威数据的委派:
- 从缓存中查找最佳的
- 将其放入权威部分
3. 转到步骤6
步骤5: 递归解析
使用本地解析器或其算法的副本来回答查询。
1. 使用解析器回答查询
2. 将结果 (包括任何中间CNAME) 存储在响应的答案部分
3. 转到步骤6
步骤6: 添加附加RR
仅使用本地数据,尝试向查询的附加部分添加其他可能有用的RR。
示例: MX记录的邮件服务器地址
query: example.com MX
answer: example.com MX 10 mail.example.com
additional: mail.example.com A 93.184.216.34
退出算法。
4.3.3. Wildcards (通配符)
基本概念
定义: 所有者名称以标签*开头的RR称为通配符。
用途: 通配符RR可以被视为用于合成RR的指令。
工作原理:
当满足适当条件时,名称服务器创建RR:
- 所有者名称 = 查询名称
- 内容 = 从通配符RR中获取
常见用例
最常用于创建将用于将邮件从互联网转发到其他邮件系统的区域。
概念: 向服务器查询中呈现的该区域中的任何名称都将被假定存在,具有某些属性,除非存在明确的相反证据。
示例:
; 为example.com中所有未明确定义的主机创建A记录
*.example.com. 3600 IN A 192.0.2.100
; 查询
unknown.example.com → 返回 192.0.2.100
anything.example.com → 返回 192.0.2.100
; 但如果有明确定义
www.example.com. 3600 IN A 93.184.216.34
→ 查询www.example.com返回 93.184.216.34 (不使用通配符)
通配符规则
所有者名称格式: *.<anydomain>
约束:
<anydomain>不应包含其他*标签- 应该在区域的权威数据中
- 通配符可能适用于
<anydomain>或其下任何节点的查询
重要: 术语"区域"而不是"域"的使用是有意的
- 这些默认值不跨区域边界传播
- 尽管子区域可以通过设置类似默认值来选择实现该外观
通配符匹配示例
$ORIGIN example.com.
*.example.com. IN A 192.0.2.100
*.sub.example.com. IN A 192.0.2.200
; 查询结果
test.example.com → 192.0.2.100 (匹配第一个通配符)
test.sub.example.com → 192.0.2.200 (匹配第二个通配符)
a.b.example.com → 192.0.2.100 (匹配第一个通配符)
www.example.com → 如果明确定义,使用明确定义的值
4.3.4. Negative response caching (Optional) (负响应缓存,可选)
概念
当名称服务器发现名称不存在时,它可以缓存此信息。
好处:
- 减少对权威服务器的查询
- 提高性能
- 减少网络流量
实现考虑
缓存时间: 使用SOA记录中的最小TTL字段
缓存内容:
查询: nonexistent.example.com
响应: NXDOMAIN (名称不存在)
缓存: "nonexistent.example.com在接下来的N秒内不存在"
注意: 此功能在RFC 1034中标记为可选,后来在RFC 2308中标准化。
关键概念总结
名称服务器架构
- 区域存储: 分布式数据库,按区域组织
- 查询处理: 递归和非递归两种模式
- 缓存机制: 提高性能和减少负载
- 冗余设计: 每个区域至少2个服务器
区域管理
- 委派机制: 父区域委派给子区域
- 粘合记录: 解决循环依赖
- 区域传输: 主从同步机制
- 一致性维护: 父子区域NS记录一致
查询算法
- 分步处理: 清晰的算法流程
- 递归支持: 可选但推荐
- 通配符处理: 灵活的默认值
- 缓存优化: 本地缓存提高性能
下一章: 5. Resolvers (解析器) - 探讨DNS解析器的工作原理和实现