摘要
- NXDOMAIN 否定的是有效查询名称本身;NODATA 否定的只是该名称下的某一种记录。前者按名称与类别缓存,后者还必须带上记录类型,否则一个缺失的 A 记录就可能把仍然存在的 MX、TXT 或 AAAA 一起抹掉。
- RFC 2308 让否定回答能够在解析器之间传递,同时必须死亡。权威区的 SOA 随回答同行,负 TTL 取 SOA 自身 TTL 与
MINIMUM的较小值;倒计时归零后,缓存不得继续使用这份证据。 - DNSSEC、NXDOMAIN 子树截断和积极否定缓存后来扩大了一份证据能覆盖的问题范围。效率越高,范围判断和过期纪律越重要;签名只能证明 DNS 链中的来源与完整性,不能证明法律权利或永久不存在。
空 Answer 不是结论
解析器查询 service.example 的 A 记录,收到的 Answer 区为空。仅凭这一点,至少有四种解释:名称不存在;名称存在但没有 A;回答其实是转介;服务器暂时失败或无法到达。超时与 SERVFAIL 更不能说明区内数据是什么。
如果把第二种情况缓存成第一种,后续对 MX 的查询可能根本不会抵达权威服务器,尽管邮件记录真实存在。反过来,如果把真正的 NXDOMAIN 只记成“没有 A”,解析器还会继续追问 AAAA、TXT 等类型,为一个已经被否定的名称制造无用流量。
NXDOMAIN 是 DNS 的 Name Error。在 CNAME 链处理完成后,它针对有效 QNAME 与类别。NODATA 没有专属 RCODE:报文仍是 NOERROR,解析器必须结合相关答案缺失以及 Authority 区的信息,排除转介后才能推断它。
RFC 2308 把语义差异写进缓存键:NXDOMAIN 使用 <QNAME, QCLASS>,NODATA 使用 <QNAME, QTYPE, QCLASS>。多出来的 QTYPE 不是格式细节,而是保护同一名称下其他数据的边界。
别名会移动否定证据的对象
用户输入的标签未必是权威服务器最后否定的标签。一个真实存在的别名可以通过 CNAME 指向不存在的规范名称。此时 NXDOMAIN 属于最后的目标,而不是已经成功返回 CNAME 的别名。
若缓存为了方便把否定挂到最初的名称上,就把针对目标的证据扩张到了另一个对象。NODATA 也一样:目标缺少一种类型,并不代表别名没有其他记录,更不代表整条链上的名称都不存在。
这正是 RFC 2308 仔细定义 QNAME 的原因。分布式系统要共享“没有”,必须先回答“谁没有什么”。
从本机记忆变成可传递陈述
RFC 1034 在 1987 年已经描述负缓存,但仍把它视为可选功能。搜索后缀、拼写错误与自动发现机制会反复提出同一个失败问题;记住否定结果能够减少延迟与权威查询。
最初方案的缺口在传播。服务器可以在本地记住错误,却无法把缓存后的否定回答连同相同的证据和剩余寿命安全地交给另一个解析器。一个“否”能被记住,却不能完整旅行。
1998 年 3 月发布的 RFC 2308 补上了这一环。凡是使用缓存的解析器,都必须处理负回答。权威服务器报告 NXDOMAIN 或 NODATA 时,必须在 Authority 区放入所属区域的 SOA。SOA 既说明哪一个区有资格作出这项 DNS 陈述,也携带它可被复用多久的材料。
负 TTL 取 SOA 记录 TTL 与 MINIMUM 的较小值。缓存保存否定结果时也保存 SOA;从缓存返回时,TTL 已扣除停留时间。归零之后,旧结论必须作废,解析器重新观察权威状态。
RFC 2308 的作者行记录了 Mark Andrews 当时的 CSIRO 任职。这是规范作者的来源信息,不是本文的机构主题。共同标准及其后续修订则通过 IETF 文档进程形成。
每一跳重置时钟,否定就不会死亡
域名空间是树,查询路径却可能形成图。两个配置错误的服务器可以互相把对方设为 forwarder。若负回答没有可传递的递减时钟,每一台服务器都可能收到它、重新赋予一个短 TTL,再转回去。
于是“短期错误”可以无限循环。RFC 2308 因此指出,没有 SOA 的负回答不应缓存。本地的短时限制若在下一跳重新开始,就根本不是限制。SOA 的作用,是让不同缓存继承同一份证据逐渐衰减的边界。
规范也借此整理了旧字段。RFC 1035 曾把 SOA MINIMUM 描述为 TTL 下限,部署又把它同时当作默认 TTL 和负缓存时长。RFC 2308 废弃没有真正被实践的普遍下限含义,用 $TTL 承担区文件默认值,并保留 MINIMUM 作为负 TTL 的输入。运行代码先暴露歧义,后来的共同规范再把它收窄。
实现先发现了“两种没有”
RFC 2308 的历史附录没有塑造一位孤独发明者。它记录了 1980 年代末 CHIVES 对权威错误的缓存:搜索路径带来大量重复失败,ARPANET 拥塞让减少这些查询产生实际收益。它也记录了 1990 年代初 BIND 的演进——先区分名称错误与 NOERROR_NODATA,再保留 SOA,使缓存结果可以带着证据返回。
这些回忆不是全网普查,但说明实现者遇到的是同一个语义问题:“空”不足以成为一种可互操作状态。RFC 2181 对 RRset 的澄清与 RFC 2308 的元组规则,把实现经验变成了更精确的共同语言。
记住否定,也会延迟新生
负回答在收到时可能完全正确,区数据变化后却会过时。名称新建之前若已有 NXDOMAIN 被缓存,部分用户仍会看到它不存在。一个已有名称新增 AAAA 之前若出现过针对 AAAA 的 NODATA,IPv6 可达性就可能落后于权威区更新,而 MX 等其他记录继续正常。
TTL 不是置信度评分,而是负载与修复速度的交换。时间越长,重复查询越少,新建或修复被隐藏得也越久。RFC 2308 允许递归解析器设置更小的本地上限,并记录一到三小时可作为合理默认值,而超过一天的值曾带来问题。
全网不存在统一过期时刻。不同解析器在不同时候接收否定,也可能使用不同上限。区文件已经修好,不代表所有客户端立刻放下过去的证据。上线计划必须考虑变更前谁缓存过什么,而不仅是变更后权威服务器返回什么。
故障则必须留在另一类语义中。超时、不可达与 SERVFAIL 是无法获得答案,不是不存在。把暂时失败伪装成 NXDOMAIN,可能令邮件、身份验证或服务发现作出难以撤销的决定。
一份否定证据覆盖更多问题
DNSSEC 让不存在可以被密码学验证。RFC 4034 定义 NSEC:它按规范顺序连接现有名称,并列出某个 owner 具有的类型;RFC 4035 规定验证器怎样据此证明 NXDOMAIN 或 NODATA。
签名不会抹平两者。一段名称间隔可以证明某个名称缺失;现有 owner 的类型位图可以证明某一种记录缺失。密码学提高的是证据来源与完整性,不会扩大证据对象。
RFC 5155 引入采用哈希名称的 NSEC3,也带来 Opt-Out。Opt-Out 是明确的推断边界:覆盖某段哈希空间的记录,不一定证明其中每一个可能名称都不存在。
RFC 8020 随后允许在规定边界内把某节点的 NXDOMAIN 用作其下名称也不存在的依据。树上不存在父名称,自然不能拥有后代;NODATA 不具备这个含义,因为缺少 A 的名称仍可能有其他类型与子名称。
RFC 8198 又允许验证型解析器积极利用缓存中的 NSEC/NSEC3,合成从未向权威服务器发出的负回答。它减少延迟与包数,也扩大旧证据的影响:若覆盖区间内新增名称,用户可能要等相关 TTL 结束才能看见。
协议证据有边界
区运营者决定当前内容与时长;权威服务器构造回答;递归解析器分类、验证、选择缓存键、施加本地上限并最终丢弃;应用再决定它对邮件、登录或发现流程意味着什么。权力沿链条分布,却没有因此合并成一个“真理所有者”。
DNSSEC 证明 DNS 链中的来源与完整性,不证明名称的法律归属,也不证明机构在现实世界已经消失。缓存可以放大一份正确否定,却不能让它超出 TTL 成为永久裁决。
这段历史最重要的进步很克制:互联网给“没有”加上精确对象、类型、负责的区和过期时间。NXDOMAIN 与 NODATA 的区分,使节省查询不必以抹掉仍然存在的数据为代价。
来源与证据边界
早期缓存与 SOA 语义见 RFC 1034 和 RFC 1035,RRset 澄清见 RFC 2181。两种否定、缓存元组、SOA 倒计时、转发循环与实现历史见 RFC 2308。认证否定以 RFC 4034、RFC 4035 与 RFC 5155 为准;后来子树规则与积极合成见 RFC 8020 和 RFC 8198。本文不把后来的 DNSSEC 能力投射回 1987 年,也不把历史附录当作完整部署统计。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
