DNSSEC 开通与验证:给解析结果加签名
DNS 查询本身没有防篡改能力,中间人改了应答,客户端也照单全收。DNSSEC 用签名补上这一环:每个答案带签名,客户端从根一路验到你的域,验过才采信。读完这篇,你能看懂 DS 记录的四个参数,知道开通要改两处(Cloudflare 与注册商),也会在出故障时按正确顺序回滚。
前置是把域接进 Cloudflare,见 49-add-domain-to-cloudflare.md。记录与 TTL 的基础见 50-dns-records-tutorial.md。
1. 信任链串在哪
DNSSEC 不像 HTTPS 那样有证书颁发机构,它的信任来自父区对子区的背书:
| 环节 | 存放位置 | 作用 |
|---|---|---|
| DNSKEY | 你的域(子区) | 公钥,用来验本区签名 |
| DS | 父区(如 .com) | 子区公钥的摘要,父区签字背书 |
| RRSIG | 随答案返回 | 对该记录集的签名 |
| AD 标志 | 解析器返回的应答头 | 表示"我验过了,有效" |
客户端不需要自己验,它信任递归解析器(1.1.1.1、8.8.8.8 或运营商 DNS),由解析器完成验证并在应答里置 AD 位。所以判断一个域有没有配好 DNSSEC,最省事的办法是看 AD 位。
2. 开通:两处操作
第一处在 Cloudflare:DNS 面板进 Settings,找 DNSSEC,点 Enable。开启后会给出四个参数,面板提供一键复制。
第二处在注册商:把四个参数填进 DS 记录。这一步不能省,少了它父区不知道你的公钥摘要,验证链断开,所有查询返回 SERVFAIL。
本机未执行开通,没有该域的 Zone 权限。真实域名的 DS 参数长这样(Verisign RDAP 与 DoH 查询所得):
| 域名 | Key Tag | Algorithm | Digest Type | Digest |
|---|---|---|---|---|
| example.com | 2371 | 13 | 2 | C988EC423E3880EB8DD8A46FE06CA230EE23F35B578D64E78B29C3E1C83D245A |
| cloudflare.com | 2371 | 13 | 2 | 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D63826F2B9 |
Algorithm 13 是 ECDSAP256SHA256,Digest Type 2 是 SHA-256,这两个数字在各家注册商的表单里都是下拉选项,选错会验证失败。
两个域的 Key Tag 都是 2371,但 Digest 不同。这说明 Key Tag 只是公钥的短标识,碰撞很常见,不能用它判断"是不是同一把钥匙",真正比对的是 Digest。
3. 验证:三个层次
最轻的验证看 AD 位,本机用 DoH 查到的结果:
curl.exe -s -H "accept: application/dns-json" "https://cloudflare-dns.com/dns-query?name=example.com&type=A"
应答里 "AD":true,说明解析器验证通过。同一方式查 github.com,返回 "AD":false,A 记录是 20.205.243.166,说明这个域没有启用 DNSSEC,解析照常工作,只是没有签名保护。
第二层是直接查 DS,确认父区真的有这条记录:
Resolve-DnsName -Name example.com -Type DS
返回里有 KeyTag 2371、Algorithm 13、DigestType 2,与 Cloudflare 面板给出的四个参数逐项对上才算配好。
第三层是查 DNSKEY,确认子区公钥存在。cloudflare.com 的 DNSKEY 查询返回两条记录,一条 KSK 一条 ZSK,这是正常的双密钥结构。
Resolve-DnsName 还支持 -DnssecOk 参数,它会在查询里带上 DO 位,让应答附带 RRSIG,适合排查"签名到底有没有返回"。
还有一处容易误读:AD 位只代表"这个解析器验过了",不是"这个域有签名"。部分解析器出于性能或配置原因不做验证,对有签名的域也返回 AD:false。判断一个域有没有开 DNSSEC,DS 与 DNSKEY 查询比 AD 位可靠,AD 位只用来确认"这条链路当前是验过的"。
4. 出错时的表现与恢复顺序
DNSSEC 配错不会降级,会直接不可用。典型表现是全域名 SERVFAIL,浏览器报 DNS 错误,而 nslookup 用非验证解析器可能还能查出结果,这种不一致最容易误判。
| 故障 | 原因 | 处理 |
|---|---|---|
| 全站 SERVFAIL | DS 填错或没填 | 核对四个参数,或先在注册商删 DS |
| 部分解析器失败 | 算法不被支持 | 换 ECDSA P-256(算法 13)或 RSA/SHA-256(算法 8) |
| 刚换 DNS 商就挂 | 旧 DS 还留在父区 | 先删 DS,再改 NS,最后在新商重开 |
| 偶发失败 | 密钥轮换窗口 | 等 TTL 过期,别反复开关 |
换 DNS 服务商时的顺序是硬性的:先在注册商删掉 DS,等 TTL 过期,再改 NS,最后在新服务商重新开启并填新的 DS。反过来做,父区还指着旧公钥,新解析商签的答案验不过,全站挂掉。
5. 什么时候先别开
- 正在做多解析商切换或灰度,签名链会随 NS 变化,这段时间开了只是给自己加故障面。
- 域下有大量老设备或自建解析器,部分老客户端对 DNSSEC 支持不完整。
- 团队里没人能处理 SERVFAIL 级别的故障,开通等于埋一个无人值守的雷。
这几类情况下,先把解析稳定下来再开。DNSSEC 的价值在防篡改,不在性能,也不影响 SEO。
常见问题
开了 DNSSEC 会不会变慢?
首包多一次签名校验,解析器侧通常有缓存,实际感知不到。真正变慢的是配置错误时的重试。
能不能只对子域开?
可以,子域委派出去之后由对方的区负责签名,父区给一条 DS 即可。主域不开、子域开是常见组合。
注册商不支持填 DS 怎么办?
换注册商,或者不开。DS 只能由父区(注册商侧)写入,Cloudflare 无法代劳。这也是选注册商时要确认的一项能力。
小结
DNSSEC 的机制不复杂,难在它是"全有或全无":链上任何一环错,结果都是不可用,而不是降级。所以开通前要确认两件事,注册商能填 DS,团队能处理 SERVFAIL。
真正容易踩的是迁移顺序:删 DS、等 TTL、改 NS、重开 DNSSEC。把这个顺序写进变更单,比记住任何命令都有用。域名转移相关的坑见 93-domain-transfer-renewal.md。
数据来源与检索时间
检索时间 2026-11-10。DS 与 AD 标志为本机实查。
| 来源 | URL | 对应数据 |
|---|---|---|
| Cloudflare DNSSEC 文档 | https://developers.cloudflare.com/dns/dnssec/ | 一键开启、DS 参数、与注册商的配合步骤 |
| Cloudflare DNSSEC 故障排查 | https://developers.cloudflare.com/dns/dnssec/troubleshooting/ | SERVFAIL 表现、算法选择、迁移顺序 |
| Verisign RDAP | https://rdap.verisign.com/com/v1/domain/example.com | secureDNS.delegationSigned 与 dsData(KeyTag 2371、Algorithm 13、DigestType 2) |
| RFC 4033 | https://www.rfc-editor.org/rfc/rfc4033 | DNSSEC 信任链、AD 标志语义 |
核验说明
- 实查:
example.com的 DS(RDAP 与Resolve-DnsName双向核对,KeyTag 2371 / Algorithm 13 / DigestType 2)、cloudflare.com的 DS 与 DNSKEY(返回两条)、example.com与cloudflare.com的 A 查询AD:true、github.com的 A 查询AD:false(20.205.243.166)。 - 依据文档:Cloudflare 侧开启步骤、注册商填 DS 的表单字段、迁移时的删 DS 顺序、算法选择建议。
- 未执行:开启 DNSSEC、写入 DS、删除 DS、切换 NS,均未在账号或注册商处执行,本机没有对应权限。文中 DS 值来自公开查询,不构成我配置过的证据。