开启 DNSSEC 后 SERVFAIL:信任链断了 —— 排查与修复

你在注册商打开 DNSSEC,公网验证型解析器(8.8.8.8 / 1.1.1.1)开始返回 SERVFAIL。注册商处的 DS 和权威 NS 的 DNSKEY 对不上,信任链断了。

你在注册商点开了 DNSSEC,粘贴了 DS 记录,感觉安全感拉满。然后站点在 Google Public DNS(8.8.8.8)和 Cloudflare(1.1.1.1)上挂了——dig 返回 status: SERVFAILdnssec-status: bogus。运营商的 DNS 还是好的,所以你本机访问没问题,但用户用公共 DNS / 企业 DNS 全军覆没。源站没事、记录也对,但所有做 DNSSEC 验证的解析器都因为信任链断了拒绝返回结果。这种故障最坑的地方就是非验证型 DNS 仍然能用,你坐在公司网里以为一切正常,真实用户已经全炸了。

常见原因

按命中率从高到低。

1. 注册商的 DS 和权威 NS 的 DNSKEY 对不上

父区的 DS 记录(Delegation Signer)必须能哈希到子区 DNSKEY RRset 里的某一把 key。你粘的 DS 是半年前的截图、或者 host 那边轮换过 key 但注册商这边没同步,链就断了。

怎么判断dig +dnssec yourdomain.com DNSKEY @8.8.8.8 拿到 key,但 dig DS yourdomain.com @8.8.8.8 的 digest 跟 dnssec-dsfromkey 从 DNSKEY 算出来的不一样。

2. 算法或 digest 类型对不上

注册商的 DS 声明算法 8(RSASHA256),但你的权威 NS 实际签名用的是算法 13(ECDSAP256SHA256);或者 digest 类型还是 1(SHA-1),现代解析器只认 2(SHA-256)。

怎么判断:上 dnsviz.net/d/yourdomain.com/dnssec/,它会把链画出来,对不上的部分标红。

3. 多家 DNS 服务商,只有一家在签名

你有一个会签名的主 NS(Cloudflare、开了 DNSSEC 的 Route 53),加一个不签名的从 NS。解析器随机命中从 NS 时拿不到 RRSIG,直接判 bogus。

怎么判断:分别查每个 NS:dig @ns1.yourprovider.com yourdomain.com +dnssec。有的回 RRSIG、有的没有,就是这条。

4. Key 轮换后旧 DS 没删干净

你轮换了 key,host 把新 DS 推到注册商,但旧 DS 没删(或者你删了新的留了旧的)。解析器会把所有 DS 都拿来验,至少要有一个能对上。只剩旧 DS 而旧 DNSKEY 已经退役,链就断了。

怎么判断dig DS yourdomain.com @8.8.8.8 返回两条 DS,但 dig DNSKEY yourdomain.com 只有新 key。旧 DS 的 keytag 在 DNSKEY 里找不到对应。

5. NSEC / NSEC3 配错导致存在性证明失败

哪怕名字存在,NSEC/NSEC3 还要证明”哪些不存在”。NSEC3 的 salt 或迭代次数配错,存在性证明无效,验证型解析器对什么都说 BOGUS。

怎么判断dnsviz.net 会专门标 NSEC3 错误,或者 delv yourdomain.com 输出 ; bogus

6. TTL 没过期,解析器把坏状态缓存住了

哪怕你已经修好了,解析器还会按原始 TTL(常见 1-24 小时)继续缓存 BOGUS 结论,用户继续 SERVFAIL。

怎么判断dig 看记录都对,但解析器还在 SERVFAIL。查 TTL:dig +noall +answer +ttlunits yourdomain.com

开始前

  • 记下你在哪一侧(注册商还是 host)什么时间开的 DNSSEC。
  • 把注册商的当前 DS 记录用文本保存下来,可能要回滚。
  • 看清楚注册商和 DNS 服务商是不是一家——不是一家的话,问题基本就在这里。
  • 准备一个非验证型解析器做对照测试(运营商 DNS 通常不验证)。

需要收集的信息

  • dig +dnssec yourdomain.com DNSKEY @8.8.8.8 +multiline 输出。
  • dig +dnssec yourdomain.com DS @8.8.8.8 +multiline 输出。
  • delv yourdomain.com @8.8.8.8 输出(会直接给出 BOGUS / SECURE 结论)。
  • 注册商 DS 记录页的截图(算法、digest 类型、key tag)。
  • DNS host 的签名算法设置(Cloudflare / Route 53 等的 RSASHA256 vs ECDSAP256)。

一步步修

按从便宜到破坏性顺序。

第 1 步:确认故障形态

delv +rtrace yourdomain.com @8.8.8.8

delv 会一步步打印验证链。哪一行说 ; bogus,那一环就是断的位置。先把这个输出存下来,作为修复前后的对比。

也可以:

dig +cd yourdomain.com @8.8.8.8

+cd(checking disabled)跳过验证。如果加了 +cd 能拿到正确答案,不加就 SERVFAIL,那么记录是对的、DNSSEC 是断的,这就是本文要修的问题。

第 2 步:从当前 DNSKEY 重新生成 DS

大多数 DNS host(Cloudflare / Route 53 / DNSimple)都有一个”给注册商的 DS”面板。打开它,把当前的值复制下来。不要相信半年前粘过的值。

如果你自己用 BIND 跑权威:

dnssec-dsfromkey -2 Kyourdomain.com.+013+12345.key

-2 强制 SHA-256 digest。拿这个值去注册商。

第 3 步:在注册商替换 DS

登录注册商,删掉旧 DS,加上第 2 步拿到的新 DS,所有字段都要对上:key tag、算法编号、digest 类型、digest。保存。

部分注册商(GoDaddy、老版 Namecheap)让你贴整条字符串,格式:

12345 13 2 ABC123DEF456...

(keytag、算法、digest 类型、digest)

第 4 步:用验证型解析器确认链通了

dig +dnssec yourdomain.com @1.1.1.1

要看到 flags: qr rd ra ad——其中 ad 标志(authenticated data)才说明解析器验证通过。没有 ad = 没验证;SERVFAIL = 还没修好。

每次重试之间等 5-10 分钟,公共解析器会缓存 DNSSEC 负结果。

第 5 步:实在修不好就先临时关掉 DNSSEC

修不动、用户又在受影响的话,去注册商把 DS 删掉:

  1. 登录注册商。
  2. 删除 DS 记录。
  3. 等父区 NS 的 TTL 过期(顶级域 NS 的 TTL,通常 6-24 小时)。

父区 TTL 过期后,信任链层面你的区就是未签名的,解析器不验证、当普通 DNS 给。站点恢复。然后你离线把 key 弄对,再开。

第 6 步:在已知公共解析器手动清负缓存

主流公共解析器都有刷新页面:

  • Google:https://developers.google.com/speed/public-dns/cache?name=yourdomain.com
  • Cloudflare:https://one.one.one.one/purge-cache/

提交一下,能缩短用户卡在 SERVFAIL 的时间。

验证

  • dig +dnssec yourdomain.com @8.8.8.8 返回 ANSWER + RRSIG + ad flag。
  • delv yourdomain.com @8.8.8.8 输出 ; fully validated
  • dnsviz.net/d/yourdomain.com/dnssec/ 显示完整绿链,从根到你的区。
  • 至少 2 个公共解析器(1.1.1.1 / 8.8.8.8 / 9.9.9.9)的非 +cd 查询都成功。
  • 用户那边反馈站点能开。

长期预防

  • 用支持 CDS / CDNSKEY 自动同步的注册商 + DNS host 组合(Cloudflare 加很多 TLD 都支持),注册商自动从 host 拉 DS,省去手动复制。
  • 轮换 key 时按两步走:(1) 推新 DNSKEY、等一个 TTL;(2) 在注册商推新 DS、再等一个 TTL;(3) 才退役旧 key。
  • 任何固定生命周期的 DNSSEC key 都加一个日历提醒——静默过期就是 P1 等爆。
  • 每天 cron 跑一次 dnsvizdnssec-monitor,链漂移要进告警、不能等用户工单。
  • 团队里写清楚 DNSSEC 谁负责。把注册商权限和 DNS 权限分给两个人,就是这个故障复现的温床。

常见坑

  • 在 host 那边打开 DNSSEC,但 DS 从来没复制到注册商。父区没链接,所有 validator 立刻判 BOGUS。
  • DS 粘错一位然后等 DNS “自然恢复”——它不会自己好。
  • 不同 key 用不同算法:KSK 用算法 8、ZSK 用算法 13,validator 行为不一致,有的过、有的挂。
  • 轮换之后旧 DS 留着”以防万一”。旧 DS 指向已删除的 DNSKEY = BOGUS(取决于解析器实现)。
  • 关 DNSSEC 也要等父区 TTL,删 DS 不会瞬间不 BOGUS。

FAQ

Q:运营商 DNS 没事,Google DNS 一直 SERVFAIL,是我的域名挂了吗?

对,用验证型解析器的用户全挂。运营商 DNS 不验证,照旧返回缓存数据。Google / Cloudflare / Quad9、绝大多数企业 DNS 都验证——这些用户就是真挂。按真实故障处理。

Q:直接把 DNSSEC 关了行不行?

短期行。在注册商删 DS,等父区 TTL,区回到普通 DNS。失去完整性保护、换回可用性。等你搞清楚原因再开。

Q:BOGUS 缓存能挂多久?

受 SOA 最小 TTL 或负 TTL 影响,通常 5 分钟到 1 小时,激进缓存能到 24 小时。用上面提到的 flush 页面能缩短。

Q:注册商有两条 DS、host 只有一把 DNSKEY,正常吗?

轮换中正常(新 DS 先发、旧 key 后退)。但不能长期这样。旧 key 从 DNSKEY RRset 完全消失之后,把对应的旧 DS 删掉,dig DS 才干净。

相关问题可看 CAA 记录挡了证书签发绑了自定义域名但 SSL 没发Name server 跟 DNS records 分不清

标签: #排查 #DNS #dnssec #排查