cat case/PM-2019-0004.md

Cloudflare 2019-07-02 WAF 规则灾难性正则回溯致全球边缘 CPU 100%

P0 · WAF 规则灾难性正则回溯使全球边缘 CPU 100%,半个互联网 502,Cloudflare 核心代理/CDN/WAF 中断

summary

2019-07-02 13:42 UTC,Cloudflare 通过自动流程对 WAF 托管规则做了一处微小改动,其中一个新规则包含不严谨的正则表达式,在特定请求体上触发灾难性回溯(catastrophic backtracking),使处理 HTTP/HTTPS 流量的每个 CPU 核心耗尽至近 100%,全球边缘代理、CDN 与 WAF 功能中断,用户访问 Cloudflare 域名看到 502。事故持续 27 分钟,打破了 Cloudflare 长达六年的无全球中断记录。

timeline

13:31 UTC 含缺陷正则的 PR 合并。13:37 UTC CI 构建测试通过(合成输入未触发回溯)。13:42 UTC 规则一次性全球推送(WAF 规则按 SOP 走全局快通道,无灰度)。13:45 UTC 综合 WAF 测试首先告警,全球流量下降、大量 502。14:00 UTC 定位 WAF 为根因,但常规回滚依赖已被拖垮的边缘控制台。14:02 UTC 提出使用多年前预留的全球终止开关(global kill switch)。14:07 UTC 执行关闭 WAF,14:09 UTC 流量与 CPU 恢复正常。

root_cause

一条 WAF 托管规则的正则表达式存在无界子模式(如 (.=.) 类结构),对一类真实 HTTP 请求体进入指数级回溯,而 WAF 正则引擎无每评估时间限制。该规则经 CI 后作为数据一次性推送到所有边缘节点(区别于普通软件发布先 dogfood 再全球),在边缘同步引爆 CPU。

amplifiers

① 无灰度推送:WAF 规则 SOP 允许全局一次性推送,绕过普通软件的 dogfood 阶段。② 无时间上限:正则引擎对单请求无超时保护。③ 自断运维:边缘代理、仪表盘、API、状态页均经同一边缘代理,故障后常规管理通道不可用。④ 防护误撤:早前重构时误移除了 CPU 使用率护栏,失去早期熔断。

mitigation

启用多年前预留的全球终止开关(不经常规部署路径)关闭 WAF;隔离坏规则后重新启用其余规则集。后续对正则做静态分析/回缩保护、WAF 规则加灰度与每请求超时、恢复 CPU 护栏。

lessons

对会被全网即时推送的「数据型」变更(规则/配置)必须与代码同等级别对待(灰度+护栏);正则必须防 ReDoS(无界子模式禁入);关键基础设施预留可绕开故障系统的全局熔断开关。

checklist

① 所有对外正则做 ReDoS 静态分析与超时限制。② WAF/规则变更强制灰度+canary。③ 保留不经主通道的全局 kill switch。④ 恢复并持续监控 CPU 护栏。