摘要

  • NXDOMAIN 表示名称不存在;NODATA 表示名称可能存在,但缺少所查询的记录类型。前者按名称与类缓存,后者还必须包含类型。
  • RFC 2308 要求权威否定携带所属区域的 SOA。SOA 自身 TTL 与 MINIMUM 中较小的值成为负 TTL,并在每次缓存转发中继续倒数;归零后不得再使用。
  • 没有 SOA 的否定不应缓存,因为互相转发的服务器可能在每一跳重置短暂寿命,让错误永远循环。
  • DNSSEC 后来用 NSEC/NSEC3 验证不存在,并允许验证型解析器从缓存范围推导新否定。签名证明 DNS 链中的来源与完整性,不证明制度权利或永久真相。

先分清沉默与否定

一次成功查询带回可以缓存的资源记录;一次失败查询却可能什么也没留下。搜索后缀会把一个拼错的名称扩展成多个请求,服务发现会反复寻找尚未部署的端点,许多客户端也会重复同一个缺失。若每次都上溯至权威服务器,最空的答案反而制造最多工作。

可是解析器不能把任何沉默都当成“不存在”。超时可能来自丢包,SERVFAIL 表示服务器无法完成处理,空回答可能要求继续跟随委派。只有负责该命名空间的权威源,在明确范围内发出的否定,才适合被其他节点重复使用。

1987 年的 RFC 1034 已把负响应缓存列为可选能力。权威名称错误可以带一个寿命。这个思路延续了 DNS 的基本交易:数据靠近使用者能够降低全局成本,数据源则用时间限制陈旧副本的影响。

但早期方案没有完整解决传播。RFC 2308 后来指出,服务器无法把自己缓存的否定以同样有用的证据形式交给另一个解析器。系统能记住“否”,却还不能保证这条记忆在传播时继续变老。

两种“没有”不能共用一个抽屉

NXDOMAIN 是 Name Error 响应码,它否定有效查询名称本身的存在。在 CNAME 链中,被否定的可能是最后一个规范目标,而不是最初别名。解析器按名称和类保存结论;如果名称根本不存在,换问另一种记录类型不会让它出现。

NODATA 更窄,也没有专用响应码。报头仍是 NOERROR,回答区没有所需类型,权威区的结构让解析器能够把它与委派区分开。一个名称可能拥有 MX、TXT 或 AAAA,却没有 A。

因此 NODATA 的键必须是名称、类型和类。把“没有 A”写成“没有这个名称”,会连真实存在的 MX 一起屏蔽。负缓存是否安全,首先取决于它是否保存了原始否定的粒度。

SOA 为错误提供同一只倒计时钟

RFC 2308 于 1998 年 3 月发布,由当时隶属 CSIRO 的 Mark Andrews 撰写,这使一家澳大利亚公共研究机构明确进入这条 DNS 运行规则的文献谱系。IETF 提供了标准化场所,使这份契约及后来的 DNSSEC 修订成为共同互联网规范。两种机构角色并不相同:本文关联 CSIRO,是因为关键规范记载了作者的这一机构归属;IETF 流程则把文本变成互联网的共同契约。

当权威服务器报告 NXDOMAIN 或 NODATA 时,必须在权威区附上包含该名称的区域 SOA。SOA 既说明哪一个区域有资格作出否定,也提供否定寿命。负 TTL 取 SOA 记录自身 TTL 与 SOA MINIMUM 两者的较小值。

解析器把 SOA 与否定一起保存。它从缓存回答下一个客户端时,要扣除已经经过的时间。计数到零,原否定就不能再使用,解析器必须重新询问。这使“不存在”从永久断言变成租约:在这段时间和范围内,区域最近如此回答;期限之后,证据需要更新。

这份规范也清理了 MINIMUM 的多重含义。RFC 1035 原先把它描述为区域导出 TTL 的下限,运行软件却又拿它作缺省 TTL 和负缓存时间。RFC 2308 废弃通用下限含义,用 $TTL 处理区域文件缺省值,并保留 MINIMUM 对负 TTL 的作用。

每一跳都重新开始的十分钟永远不会结束

DNS 名称空间是一棵树,查询流向却可能形成环。两台配置错误的服务器可以互相设为转发器,失效委派也可能制造循环。

如果一条没有 SOA 的负响应只按本地策略缓存十分钟,服务器 A 把它交给 B 时,B 会得到新的十分钟;B 再交回 A,又重新开始。每个节点都遵守短寿命,整体错误却可能永不消失。

RFC 2308 因而要求没有 SOA 的负响应不应缓存。随 SOA 携带并持续减少的 TTL,把时间约束绑定到证据本身,而不是某一份局部副本。分布式系统中的限制,只有在跨越边界后仍然保留,才是真限制。

标准吸收了已经运行的代码

RFC 2308 的历史附录记载,CHIVES 在 1987 年末已经依据 SOA MINIMUM 缓存权威错误。搜索路径产生大量失败请求,ARPANET 拥塞让节省这些查询具有直接价值。少量运行 CHIVES 的机器获得显著响应改善,但这不是全网流量统计。

附录还记录了 1993 年 BIND 4.9.2 ALPHA 的工作:先采用十分钟负 TTL,并区分 NXDOMAIN 与 NOERROR_NODATA,随后保存 SOA,让缓存否定能带着证据返回。

这些故事不支持“单一发明者”。它们说明公共协议如何被运行经验收紧:使用正确的键、保存权威上下文、让寿命可传递,并兼容曾误读权威区的软件。

缓存一次不存在,会延迟下一次存在

负缓存直接减少包、延迟和权威服务器负载。代价在创建时出现:运营者增加新名称,或给既有名称添加过去缺失的类型,持有旧否定的解析器仍会回答“不存在”,直到各自 TTL 结束。

不同缓存收到负响应的时刻不同,有的还会设置更小的本地上限,因此没有一个全球同时恢复的秒点。RFC 2308 提到一至三小时是合理缺省,超过一天往往出现问题,尽管协议数值范围能够表达远长得多的时间。

错误分类还会改变下游后果。RFC 指出,注入的 NXDOMAIN 可能让邮件立即退回;一个错误地址却可能让邮件排队,等待修复。把暂时故障伪装成不存在,会把可逆网络事故升级为不可逆业务决定。

签名否定从一个答案扩展成一段范围

DNSSEC 改变了解析器能验证的内容。NSEC 按规范顺序连接现有名称,并列出某个名称拥有的记录类型;RFC 4035 的规则让验证器证明一个区间内没有精确名称,或一个现有名称缺少某类型。

NSEC 也容易暴露区域内容。RFC 5155 引入哈希名称的 NSEC3 和 Opt-Out。Opt-Out 覆盖的区间不保证其中每一个未签名委派存在或不存在,验证者不能把这处空白扩大成确定结论。

RFC 8020 后来明确 NXDOMAIN cut:树上的一个节点不存在,其下子节点也不存在。这个规则只属于 NXDOMAIN;NODATA 所指名称仍可拥有其他类型和后代。

RFC 8198 又允许验证型解析器在缓存已有足够 NSEC/NSEC3 证据时,为区间内另一条查询合成否定,无需访问权威服务器。一个已验证证明由此服务多个问题,降低延迟和查询泄露。

扩大复用也扩大陈旧影响。若区间内增加新名称,它可能在相关负证据过期前无法使用。DNSSEC 证明某个区域密钥签署的数据在传输中未被篡改;它不证明删除是合理的,不证明机构已经消失,也不赋予缓存以命名主权。

来源与证据边界

这些 RFC 记录协议设计、要求和有限的实现历史,不是全量部署普查。DNSSEC 否定、NXDOMAIN 子树规则和积极负缓存属于后来的阶段,不能倒推到 1987 或 1998 年的解析器。