找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

213

积分

0

好友

13

主题
发表于 昨天 18:20 | 查看: 6| 回复: 0

image2.webp

2025年12月5日上午8点47分(UTC时间),Cloudflare 网络的部分节点突然出现了大规模故障。这次事故持续了约25分钟,直到9点12分才完全恢复。受影响的客户流量占到了 Cloudflare 总 HTTP 流量的28%左右。

需要说明的是,这次故障并非网络攻击或恶意行为导致,而是在应对 React Server Components 安全漏洞时,内部配置变更引发的连锁反应。

作为一家为全球互联网提供基础设施服务的公司,任何形式的服务中断都是不可接受的。特别是在11月18日刚刚经历过一次类似事故后,我们深知再次让用户失望的严重性。关于如何防止此类事件再次发生,我们将在下周发布详细的改进方案。

事故经过

下图展示了事故期间网络返回的 HTTP 500 错误数量(底部红线),以及未受影响的正常流量(顶部绿线)的对比:

流量对比图

流量对比图

问题的起因

Cloudflare 的 Web 应用防火墙(WAF)负责为客户检测和拦截恶意请求。为了完成这项工作,我们的代理服务器会将 HTTP 请求体缓存到内存中进行分析。此前,这个缓冲区的大小设置为 128KB。

最近,我们一直在努力保护使用 React 的客户免受严重漏洞 CVE-2025-55182 的威胁。为此,我们计划将缓冲区大小提升到 1MB(这是 Next.js 应用的默认限制),以确保尽可能多的客户得到保护。

第一个变更:我们通过渐进式部署系统开始推出缓冲区扩容。

在推出过程中,我们发现内部的 WAF 测试工具不支持新的缓冲区大小。由于这个测试工具当时并不需要使用,且不会影响客户流量,我们决定暂时关闭它。

第二个变更:关闭 WAF 测试工具。

这里出现了关键问题——第二个变更使用的是全局配置系统,而非渐进式部署。这个系统会在几秒钟内将变更同步到全网所有服务器。这正是我们在11月18日事故后正在审查的系统之一。

技术细节

不幸的是,在我们的 FL1 代理版本中,关闭 WAF 测试工具的操作在特定情况下触发了一个错误状态,导致网络开始返回 HTTP 500 错误。

当配置变更传播到全网后,FL1 代理的代码执行触发了规则模块中的一个 bug,产生了以下 Lua 异常:

[lua] Failed to run module rulesets callback late_routing: 
/usr/local/nginx-fl/lua/modules/init.lua:314: 
attempt to index field 'execute' (a nil value)

这直接导致了 HTTP 500 错误的大量出现。

我们在变更应用后很快识别了问题,并在9点12分完成了回滚,之后所有流量恢复正常。

受影响范围

只有同时满足以下两个条件的客户才会受到影响:

  1. 网站资源由较旧的 FL1 代理提供服务
  2. 部署了 Cloudflare 托管规则集

对于符合上述条件的网站,所有请求都会返回 HTTP 500 错误(少数测试端点如 /cdn-cgi/trace 除外)。

不符合上述配置的客户没有受到影响。此外,中国网络的客户流量也完全不受影响。

深层技术原因

Cloudflare 的规则集系统由多组规则构成,每个进入系统的请求都会被这些规则评估。一条规则包含两部分:

  • 过滤器:选择特定流量
  • 动作:对流量施加效果

常见的动作类型包括 "block"(拦截)、"log"(记录)或 "skip"(跳过)。还有一种特殊的动作叫 "execute"(执行),用于触发另一个规则集的评估。

我们的内部日志系统使用这个功能来测试新规则。顶层规则集会执行另一个包含测试规则的规则集。这次我们试图禁用的正是这些测试规则。

Kill Switch 机制的缺陷

我们有一个"紧急开关"(killswitch)子系统,用于快速禁用异常规则。这个系统从全局配置系统接收信息。过去我们多次使用这个机制来缓解事故,并且有完善的标准操作流程。

然而,我们从未对带有 "execute" 动作的规则应用过 killswitch

当 killswitch 被应用时,代码正确地跳过了 execute 动作的评估,没有执行它指向的子规则集。但在处理规则集的整体评估结果时,却遇到了错误:

if rule_result.action == "execute" then
    rule_result.execute.results = ruleset_results[tonumber(rule_result.execute.results_index)]
end

这段代码假设,如果规则集的动作是 "execute",那么 rule_result.execute 对象一定存在。但由于规则被跳过了,rule_result.execute 对象并不存在,Lua 在尝试访问 nil 值时抛出了错误。

这是一个典型的代码错误,已经潜伏多年未被发现。这类错误在具有强类型系统的语言中是可以避免的。事实上,在我们用 Rust 编写的新 FL2 代理中,这个错误并没有出现。

11月18日事故后的改进进展如何?

两周前的11月18日,我们经历了一次类似但影响更大、持续时间更长的事故。两次事故有个共同点:为了帮助客户缓解安全问题而进行的部署传播到了整个网络,导致几乎所有客户都受到了影响。

事故发生后,我们直接与数百位客户进行了沟通,分享了我们的改进计划,以防止单个更新造成如此大范围的影响。

我们相信这些改进措施本可以帮助防止今天的事故,但遗憾的是,相关工作尚未完全部署完成。我们知道这令人失望,但这仍然是整个组织的首要任务。

具体来说,以下项目应该能够遏制此类变更的影响范围:

增强的渐进式发布与版本控制

类似于我们缓慢部署软件并进行严格健康验证的方式,用于快速威胁响应和常规配置的数据也需要具备相同的安全和影响控制特性。这包括健康验证和快速回滚能力等。

优化的紧急操作能力

确保在增加额外安全措施的情况下,关键操作仍然可以顺利执行。


后记

这次事故再次提醒我们,在追求安全性的同时,系统的稳定性和变更管理同样重要。虽然我们的初衷是保护客户免受 React 漏洞的威胁,但配置变更的方式和代码中潜藏的 bug 共同导致了这次中断。

我们将继续推进改进工作,确保类似事故不再发生。下周我们会发布更详细的技术方案和时间表,欢迎持续关注。


:文中提到的 CVE-2025-55182 是 React Server Components 中发现的一个严重漏洞,Cloudflare 正在积极帮助客户防御此类威胁。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-8 14:34 , Processed in 0.083962 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表