DNS 手册域名系统参考

DNSSEC:签名与信任链

DNSSEC 给 DNS 数据加上数字签名,让验证者能确认“这条记录确实来自区的持有者,而且没被改过”。它不加密,也不保证可用,只回答一个问题:数据是真的吗?

最后修订 · 约 6 分钟读完

它保护什么,不保护什么#

  • 保护:数据来源与完整性。缓存投毒、途中篡改,在验证者那里都会显示为验证失败。
  • 保护:经过认证的“不存在”。攻击者无法伪造一个可信的 NXDOMAIN。
  • 不保护:机密性。签名的数据仍然以明文传输,任何人都能看。
  • 不保护:可用性。攻击者丢掉应答,验证者只会得到 SERVFAIL。
  • 不保护:验证者之后的一段。如果 stub 只看解析器给的 AD 位,而到解析器的链路未加密,AD 位本身可以被篡改。

相关记录#

DNSKEY
区的公钥,放在区顶点。flags 字段为 256 表示区签名密钥(ZSK),257 表示带 SEP 标志的密钥,惯例上用作密钥签名密钥(KSK)。KSK 只签 DNSKEY 集合,ZSK 签区里的其他数据——这种分工不是协议要求,而是为了让常换的 ZSK 不必每次都通知父区。
RRSIG
对一个 RRset(同名、同类、同类型的一组记录)的签名。字段包括被签名的类型、算法、标签数、原始 TTL、生效与过期时间、签名密钥的标签(key tag)、签名者名字和签名本身。签名有有效期,过期了即使数据没变也会验证失败。
DS
放在父区里,是子区某个 DNSKEY(通常是 KSK)的摘要。它把父区的信任传给子区,是信任链上的连接点。
NSEC
按规范顺序把区内名字串成链,每条 NSEC 写明“下一个存在的名字”和“本名字上有哪些类型”。查询落在两个名字之间,就由对应的 NSEC 证明不存在。副作用是可以顺着链枚举整个区(zone walking)。
NSEC3
把名字散列后再串链,增加枚举的难度(但离线字典攻击仍然可行)。RFC 9276 建议迭代次数设为 0、不用盐:额外的迭代几乎不增加安全性,却显著增加验证者的计算成本,一些验证者会把迭代次数过高的区当作不安全。

信任链#

验证 www.example.com 的 A 记录,验证者需要走完这样一条链:

  1. 手里有根区 KSK 的信任锚(内置或经 RFC 5011 更新)。
  2. 用它验证根区的 DNSKEY 集合,进而信任根区的 ZSK。
  3. 用根区 ZSK 验证根区里 com. 的 DS 记录。
  4. 拿 com. 的 DNSKEY 和这个 DS 比对,信任 com. 的 KSK,再验证其 DNSKEY 集合。
  5. 同理验证 com. 区里 example.com. 的 DS,以及 example.com. 的 DNSKEY 集合。
  6. 最后用 example.com. 的 ZSK 验证 www.example.com. A 记录的 RRSIG。

任何一环断开都会改变结论。如果 com. 区里根本没有 example.com. 的 DS(并有签名的不存在证明),说明这个域没有启用 DNSSEC,结论是“不安全”而不是“失败”。

四种验证结果#

状态含义验证型解析器的处理
Secure信任链完整,签名有效返回答案并置 AD=1
Insecure有经过验证的证据表明这一段没有签名(缺少 DS 且其不存在已被证明)正常返回答案,AD=0
Bogus应该有签名却验证失败:签名错误、过期、缺失,或 DS 对不上返回 SERVFAIL,通常附带扩展错误码(EDE 6 至 12)
Indeterminate无法得出结论,例如缺少必要的信任锚按实现策略处理

RFC 4033 §5 定义了这四种状态。客户端发查询时置 CD=1,可以让解析器跳过验证、把原始数据交回——排查“验证失败还是数据本身有问题”时很有用。

算法与摘要类型#

编号算法现状
5RSASHA1不应再用于签名
7RSASHA1-NSEC3-SHA1不应再用于签名
8RSASHA256使用最广;根区和许多顶级域使用
10RSASHA512可用,使用较少
13ECDSAP256SHA256签名小、验证快,新部署的常见选择
14ECDSAP384SHA384可用,使用较少
15Ed25519RFC 8080;签名小,支持面逐年扩大
16Ed448RFC 8080;支持面较窄

DS 的摘要类型:1 为 SHA-1(不应再新建),2 为 SHA-256(最常用),4 为 SHA-384。各算法的实现要求见 RFC 8624。验证者不支持某个算法时,按规范应把该区视为不安全,而不是失败——所以换用新算法本身不会让老验证者拒绝你的区。

密钥轮换#

密钥要换,换的过程中缓存里还留着旧数据,这是 DNSSEC 运维最容易出错的地方。两种基本做法:

  • 预发布(多用于 ZSK):先把新密钥加进 DNSKEY 集合、但暂不用它签名;等旧 DNSKEY 集合在各地缓存里过期后,改用新密钥签名;再等旧签名过期,删除旧密钥。
  • 双签(多用于 KSK):新旧密钥同时签 DNSKEY 集合,在父区换上新 DS,等旧 DS 在缓存里过期后撤下旧密钥。

每一步之间的等待时间取决于相关记录的 TTL,而不是你觉得够了就行。KSK 轮换还牵涉父区:传统上要到注册商那里手动换 DS,容易遗漏。CDS 与 CDNSKEY 记录(RFC 7344、RFC 8078)让子区直接发布“请把 DS 改成这个”,支持的父区会自动扫描并更新。

常见故障#

  • 签名过期:签名工具停止运行或定时任务失效,几天后整个区在验证型解析器上解析失败。监控 RRSIG 的过期时间应当和监控证书过期一样严格。
  • DS 与 DNSKEY 对不上:换了 KSK 却没更新父区的 DS,或者换托管商时把旧 DS 留在了注册商那里。迁移 DNS 托管时,先撤 DS(或换成新托管的 DS 并等待 TTL)再切 NS。
  • 时钟偏差:验证者按本机时间判断签名是否生效,时间错了,有效签名也会被判为未生效或已过期。没有电池的小设备开机时尤其容易出现。
  • 应答太大:大 RSA 密钥加多个签名让应答超过 UDP 限制,而 TCP/53 又被防火墙挡住,表现为部分网络下间歇失败。
  • 验证器被拖垮:2024 年公布的 KeyTrap(CVE-2023-50387)利用大量密钥标签相同的密钥和签名,让验证者进行海量的签名校验。主流解析器已经加入了对验证工作量的限制。

用工具检查#

shell
$ dig +dnssec +multi example.com DNSKEY
$ dig @a.gtld-servers.net +norecurse example.com DS
$ delv @1.1.1.1 example.com A +rtrace
$ dig +cd @1.1.1.1 example.com A

delv 在本机做完整的验证并说明结论,比只看 AD 位可靠得多。+cd 能拿到解析器未验证的原始数据:如果加了 +cd 才能解析,问题几乎一定出在 DNSSEC 上。

DNS 手册 · 内容依据 IETF RFC 与各运营方公开资料整理,出现分歧时以原文为准。回到顶部