一个bug引发的“血案”:1600万.de域名集体宕机
一个Bug搞瘫1600万个域名:.de DNS故障复盘
说实话,大多数人只有在DNS出问题时才会想起它。一旦出了问题?什么都完了。
2026年5月5日,德国域名注册局DENIC在一次例行的DNSSEC密钥轮换中,深刻体会到了这一点。大约三个小时里,访问.de域名就像抛硬币——有时候能打开,大多数时候打不开。全球的验证解析器不断抛出"伪造"错误,就像派对上撒了一地的彩纸,只是这场派对彻底砸了。
技术层面的原因其实很简单:自定义轮换软件里的一个错误。但这个错误为什么会发生,才是真正值得每个开发者和运维工程师深思的地方。
到底发生了什么
.de域名的DNSSEC签名基础设施,用的是标准软件(Knot resolver)和内部定制开发的组合,全都跑在HSM(硬件安全模块)上。可以把HSM想象成加密金库,专门生成和存储保护DNS区域的私钥。
2026年5月那次例行密钥轮换,负责生成密钥材料并分发到各个HSM的自定义"轮换代理"程序出了故障。问题很隐蔽,但后果很严重。
问题出在这里:这套有bug的代码本该生成一套密钥对然后分发给所有HSM,结果它生成了三套独立的密钥对——每个HSM一套。更糟糕的是,这三套密钥的元数据完全相同,包括同一个key tag(33834)。
结果就是:发布区域时,三套HSM里只有一台拥有与公钥DNSKEY记录匹配的私钥。这意味着只有大约三分之一的DNSSEC签名能通过验证。剩下的?全是无效的。在DNSSEC的世界里,无效签名不等于"应该没问题",而是直接被判为"伪造"。
为什么测试没发现这个bug
这里才是故事最值得借鉴的地方——所有写基础设施代码的人都该好好看看。
这个轮换代理的bug,只在多个HSM同时连接时才会触发。问题来了:测试环境里只有一台HSM,放在一个地点。
当你只有一台HSM的时候,"每台HSM生成一套密钥对"和"所有HSM共用一套密钥对",结果是完全一样的。所以有bug的代码通过了所有测试,因为测试环境根本没有模拟真实生产场景。
这就是经典的环境一致性缺失——每个开发者理论上都知道这个问题,但偏偏还是会遇到。测试环境一直"够用",直到它不够用了。
监控悖论
这里特别让人郁闷:DENIC的监控系统其实检测到了问题。
三套独立的验证工具一直在运行,持续检查缺失或无法验证的签名。这些系统做了它们该做的事——发现了异常。
但问题是,生成的告警没有被正确处理。通知发出了,但人没收到,或者收到了没来得及处理。带着问题的区域被持续发布了三个小时。
这是我们反复看到的模式:能检测问题的监控,值多少钱完全取决于incident响应流程能不能跟上。你可以搭建全世界最牛的观测平台,但告警石沉大海、响应手册含糊不清的话,你照样是在蒙眼开车。
有些大型解析器运营商看出了端倪,临时禁用了.de域名的DNSSEC验证——相当于告诉解析器"对于德国域名,先相信再说"。这确实帮他们的用户减少了损失,但也暴露了一个问题:我们对验证机制的假设有多脆弱。
连锁反应:为什么没用DNSSEC的域名也挂了
这里有个细节让这次事故特别值得学习:出问题的域名,不一定自己用了DNSSEC。
DNSSEC验证是递归进行的。当解析器查询.de域名时,响应会包含NSEC3记录,用来证明某些记录在区域里不存在。这些NSEC3记录必须被签名——如果签名无效,整个响应都会被标记为可疑。
所以,哪怕你的德国创业公司域名压根没配置DNSSEC,证明你域名存在的授权链仍然需要有效签名。当验证失败像多米诺骨牌一样传导下去,那些自己根本没动过DNSSEC配置的域名也变得无法解析了。
DNSSEC的强度取决于最薄弱的那个区域。 .de区域的签名出了问题,验证解析器眼里整个TLD都像是被入侵了。
基础设施团队应该学到什么
1. 在接近生产环境的地方测试
说起来容易,做起来难。如果你的代码跑一台HSM和三台HSM行为完全不同,测试环境就得有三台HSM。是的,成本更高。是的,更复杂。但还是得做。
2. 失败场景也要测,不能只测正常路径
代码review漏掉这个bug,是因为测试场景只覆盖了理想路径。网络分区了怎么办?HSM增加了或减少了怎么办?密钥不同步了怎么办?对自己的假设进行对抗性测试,不是可选项。
3. 没有预案的监控就是噪音
没人知道怎么处理的告警,或者凌晨三点响了但没有明确升级路径的告警——这些不会阻止故障,只会在故障报告里出现。每个告警都要有对应的预案,每个预案都要每季度演练。
4. 冗余不光是硬件的事
DENIC的基础设施确实把HSM分布在两个地理位置不同的数据中心。但软件架构假设所有HSM行为完全一致。真正的冗余,是为你的假设会出错而设计,而不只是为硬件会损坏而设计。
5. 算清楚影响范围
设计关键基础设施的时候,多问问自己:这个挂了会怎样,影响会扩散多远?.de事故波及的域名,很多根本跟DNSSEC没什么直接关系。这提醒我们,在分布式系统里,依赖关系走向往往出人意料。
好消息
DENIC的处理方式相当透明。最终报告详细说明了哪里出了问题、现有防护为什么失效、以及正在采取的具体措施——包括改进代码review流程、完善incident响应机制。
DNSSEC生态从这些事故中学习。每一次大的故障——不管是.de、Dyn还是Cloudflare的小状况——都教会我们一些关于构建更韧性基础设施的道理。关键是真正把这些教训用起来。
总结: DNS是互联网的无名英雄,直到它不是。2026年5月的.de故障提醒我们,哪怕再成熟、再有资金、防护层再多的运营方,也可能在某个特定时刻被一个恰到好处的bug击溃。
对开发者和基础设施团队来说,学到的不是恐惧,而是警醒。发布前测试,测试后监控,别天真地以为测试环境能完美复刻生产环境。
因为DNS一挂,什么都得挂。而这个教训,越是在技术栈深处学到,代价就越大。