吃土了吃土了吃土了……快给我点钱吃饭!😭😭😭

FreeCookie 卡片广告位招租

支持 外链跳转 + 简短描述

价格:

  • 月付:35 RMB
  • 季付(3 个月):100 RMB
  • 年付:350 RMB

项目状态:

  • 已稳定运行 一年半以上
  • 真跑路了我也会把你没用完的时间退给你

Cloudflare 2025年11月18日服务中断

简要概括:2025年11月18日,Cloudflare因数据库权限变更导致Bot Management系统特征配置文件大小翻倍,超出系统限制,引发全球网络服务中断约8小时。所有时间已从UTC转换为北京时间(UTC+8)。

时间线

  • 19:05 - 数据库访问控制变更部署
  • 19:20 - 网络开始出现核心流量传输失败
  • 19:28 - 影响开始,客户环境中观察到首个HTTP错误
  • 19:31 - 首个自动化测试检测到问题
  • 19:32 - 手动调查开始
  • 19:35 - 事故电话会议创建
  • 19:48 - Cloudflare状态页面发布调查通知
  • 20:03 - 继续调查问题
  • 20:21 - 服务开始恢复,但错误率仍高于正常水平
  • 20:37 - 继续调查问题
  • 20:53 - 继续调查问题
  • 21:04 - 在伦敦禁用WARP访问
  • 21:09 - 问题已识别,正在实施修复
  • 21:13 - Cloudflare Access和WARP恢复,错误率恢复正常
  • 21:05 - 实施Workers KV和Cloudflare Access绕过,影响减少
  • 21:35 - 继续为应用服务客户恢复服务
  • 21:37 - 重点回滚Bot Management配置文件到已知良好版本
  • 21:58 - 继续为应用服务客户恢复服务
  • 22:22 - 继续修复问题
  • 22:24 - 停止创建和传播新的Bot Management配置文件
  • 22:24 - 新文件测试完成
  • 22:30 - 主要影响解决,下游服务错误率开始下降
  • 22:34 - 仪表板服务恢复
  • 22:42 - 修复已实施,事故解决
  • 22:57 - 部分客户仍可能遇到仪表板登录问题
  • 23:23 - 继续监控问题
  • 23:40 - 团队继续专注于修复后恢复服务
  • 00:04 - 机器人评分在全局恢复期间可能间歇性受影响
  • 00:27 - 错误和延迟持续改善,仍有间歇性错误报告
  • 00:46 - 错误持续下降
  • 01:14 - 继续监控系统恢复,错误和延迟恢复正常水平
  • 01:44 - Cloudflare服务当前运行正常,不再观察到网络错误或延迟升高
  • 03:28 - 事故已解决

2025-11-18

Matthew Prince

img

2025年11月18日北京时间19:20(本文中的所有时间均为北京时间,UTC+8),Cloudflare的网络开始出现核心网络流量传输的重大故障。对于尝试访问我们客户站点的互联网用户来说,这表现为显示Cloudflare网络内部故障的错误页面。

HTTP error page displayed during the incident

问题并非由网络攻击或任何类型的恶意活动直接或间接引起。 相反,它是由对我们数据库系统之一的权限更改触发的,这导致数据库输出多个条目到我们的Bot Management系统使用的"特征文件"中。该特征文件随后大小翻倍。比预期更大的特征文件然后传播到组成我们网络的所有机器。

在这些机器上运行以路由我们网络流量的软件读取此特征文件以保持我们的Bot Management系统与不断变化的威胁保持最新。该软件对特征文件的大小有限制,低于其翻倍后的大小。这导致软件失败。

在我们最初错误地怀疑我们看到的症状是由超大规模DDoS攻击引起后,我们正确识别了核心问题,并能够停止比预期更大的特征文件的传播,并用文件的早期版本替换它。核心流量在22:30基本正常流动。我们在接下来的几个小时内努力缓解我们网络各个部分因流量迅速恢复在线而增加的负载。截至01:06,Cloudflare的所有系统都正常运行。

我们对客户和整个互联网造成的影响感到抱歉。鉴于Cloudflare在互联网生态系统中的重要性,我们任何系统的任何中断都是不可接受的。我们的网络有一段时间无法路由流量,这对我们团队的每个成员来说都是深深的痛苦。我们知道我们今天让您失望了。

这篇文章是对确切发生的事情以及哪些系统和流程失败的深入叙述。它也是我们计划确保此类中断不再发生的开始,尽管不是结束。

中断

下面的图表显示了Cloudflare网络服务的5xx错误HTTP状态码的数量。通常这应该非常低,直到中断开始前确实如此。

Volume of HTTP 5xx requests served by the Cloudflare network

19:20之前的数量是我们网络中观察到的5xx错误的预期基线。峰值和随后的波动显示我们的系统由于加载错误的特征文件而失败。值得注意的是,我们的系统随后会恢复一段时间。这对于内部错误来说是非常不寻常的行为。

解释是文件每五分钟由在ClickHouse数据库集群上运行的查询生成,该集群正在逐步更新以改进权限管理。只有在查询在已更新的集群部分运行时才会生成错误数据。结果,每五分钟就有机会生成好或坏的配置文件集,并迅速传播到整个网络。

这种波动使得不清楚发生了什么,因为整个系统会恢复然后再次失败,因为有时好、有时坏的配置文件被分发到我们的网络。最初,这导致我们相信这可能是由攻击引起的。最终,每个ClickHouse节点都在生成错误的配置文件,波动稳定在失败状态。

错误持续到14:30(UTC)开始识别和解决根本问题。我们通过停止错误特征文件的生成和传播,并手动将已知良好文件插入特征文件分发队列来解决此问题。然后强制重启我们的核心代理。

上面图表中剩余的长期尾部是我们的团队重启进入不良状态的剩余服务,5xx错误码数量在01:06恢复正常。

以下服务受到影响:

服务/产品影响描述
核心CDN和安全服务HTTP 5xx状态码。本文顶部的截图显示了交付给最终用户的典型错误页面。
TurnstileTurnstile无法加载。
Workers KVWorkers KV返回了显著升高的HTTP 5xx错误水平,因为对KV"前端"网关的请求由于核心代理失败而失败。
仪表板虽然仪表板大部分可操作,但由于登录页面上Turnstile不可用,大多数用户无法登录。
邮件安全虽然邮件处理和交付未受影响,我们观察到临时失去对IP信誉源的访问,这降低了垃圾邮件检测准确性并阻止了一些新域名年龄检测触发,没有观察到关键客户影响。我们还看到一些自动移动操作失败;所有受影响的消息已审查和修复。
Access大多数用户身份验证失败广泛存在,从事故开始持续到21:05开始回滚。任何现有的Access会话未受影响。所有失败的身份验证尝试导致错误页面,意味着这些用户在身份验证失败时从未到达目标应用程序。在此期间的成功登录在此事故期间正确记录。当时尝试的任何Access配置更新要么完全失败,要么传播非常缓慢。所有配置更新现已恢复。

除了返回HTTP 5xx错误外,我们在影响期间观察到来自我们CDN的响应延迟显著增加。这是由于大量CPU被我们的调试和可观察性系统消耗,这些系统自动用额外的调试信息增强未捕获的错误。

Cloudflare如何处理请求,以及今天出了什么问题

每个到Cloudflare的请求都经过我们网络的明确定义路径。它可能来自加载网页的浏览器、调用API的移动应用程序或来自其他服务的自动化流量。这些请求首先在我们的HTTP和TLS层终止,然后流入我们的核心代理系统(我们称之为FL,代表"Frontline"),最后通过Pingora,它执行缓存查找或在需要时从源获取数据。

我们之前在此处分享了关于核心代理工作原理的更多细节。

Diagram of our reverse proxy architecture

当请求通过核心代理时,我们运行我们网络中可用的各种安全和性能产品。代理应用每个客户的独特配置和设置,从强制执行WAF规则和DDoS保护到将流量路由到Developer Platform和R2。它通过一组特定领域的模块来实现这一点,这些模块将配置和策略规则应用于通过我们代理的流量。

其中一个模块,Bot Management,是今天中断的源头。

Cloudflare的Bot Management包括,除其他系统外,一个机器学习模型,我们使用它为通过我们网络的每个请求生成机器人评分。我们的客户使用机器人评分来控制哪些机器人被允许访问他们的站点 - 或不。

模型将"特征"配置文件作为输入。在此上下文中,特征是机器学习模型用来预测请求是否自动化的个体特征。特征配置文件是单个特征的集合。

此特征文件每几分钟刷新一次并发布到我们的整个网络,使我们能够对互联网上流量流的变化做出反应。它使我们能够对新型机器人和新的机器人攻击做出反应。因此,当恶意行为者快速改变他们的策略时,频繁快速地推出它至关重要。

我们底层ClickHouse查询行为(如下所述)的变更导致它具有大量重复的"特征"行。这改变了先前固定大小的特征配置文件的大小,导致机器人模块触发错误。

结果,处理我们客户流量处理的核心代理系统为任何依赖机器人模块的流量返回了HTTP 5xx错误码。这也影响了依赖核心代理的Workers KV和Access。

与此事故无关,我们当时并且目前正在将我们的客户流量迁移到我们代理服务的新版本,内部称为FL2。两个版本都受到问题的影响,尽管观察到的影响不同。

部署在新FL2代理引擎上的客户观察到HTTP 5xx错误。在我们旧代理引擎(称为FL)上的客户没有看到错误,但机器人评分未正确生成,导致所有流量收到零分的机器人评分。部署了阻止机器人规则的客户会看到大量误报。未在其规则中使用我们机器人评分的客户没有看到任何影响。

让我们困惑并使我们相信这可能是攻击的是我们观察到的另一个明显症状:Cloudflare的状态页面宕机了。状态页面完全托管在Cloudflare基础设施之外,不依赖Cloudflare。虽然结果证明是巧合,但它导致诊断问题的一些团队相信攻击者可能同时针对我们的系统和我们的状态页面。当时访问状态页面的访问者收到错误消息:

Error on the Cloudflare status page

在内部事故聊天室中,我们担心这可能是最近一系列高容量Aisuru DDoS攻击的延续:

Internal chat screenshot

查询行为变更

我上面提到底层查询行为的变更导致特征文件包含大量重复行。有问题的数据库系统使用ClickHouse软件。

对于上下文,了解ClickHouse分布式查询的工作方式很有帮助。ClickHouse集群由许多分片组成。要从所有分片查询数据,我们在名为default的数据库中有所谓的分布式表(由表引擎Distributed提供支持)。分布式引擎查询数据库r0中的底层表。底层表是数据存储在ClickHouse集群的每个分片上的位置。

对分布式表的查询通过共享系统账户运行。作为改进我们分布式查询安全性和可靠性工作的一部分,正在进行工作以使它们在初始用户账户下运行。

在今天之前,ClickHouse用户在查询ClickHouse系统表(如system.tablessystem.columns)中的表元数据时只会看到default数据库中的表。

由于用户已经对r0中的底层表具有隐式访问权限,我们在19:05进行了更改以使此访问显式,以便用户也可以看到这些表的元数据。通过确保所有分布式子查询可以在初始用户下运行,可以以更细粒度的方式评估查询限制和访问授权,避免一个用户的错误子查询影响其他人。

上面解释的变更导致所有用户访问他们有权访问的表的准确元数据。不幸的是,过去做出了假设,像这样的查询返回的列列表将只包括"default"数据库:

SELECT name, type FROM system.columns WHERE table = 'http_requests_features' order by name;

注意查询如何不筛选数据库名称。随着我们逐渐向给定ClickHouse集群的用户推出显式授权,在19:05的变更之后,上面的查询开始返回列的"重复",因为那些是存储在r0数据库中的底层表的列。

不幸的是,这是由Bot Management特征文件生成逻辑执行的查询类型,用于构建本节开头提到的文件的每个输入"特征"。

上面的查询将返回一个列表,如显示的(简化示例):

Example of code block

然而,作为授予用户的额外权限的一部分,响应现在包含r0模式的所有元数据,有效地使响应中的行数翻倍以上,最终影响最终文件输出中的行数(即特征)。

内存预分配

在我们代理服务上运行的每个模块都有许多限制,以避免无界内存消耗并作为性能优化预分配内存。在这个特定实例中,Bot Management系统对可以在运行时使用的机器学习特征数量有限制。目前该限制设置为200,远高于我们当前使用的约60个特征。同样,限制存在是因为出于性能原因我们为特征预分配内存。

当包含超过200个特征的错误文件传播到我们的服务器时,达到了此限制 - 导致系统恐慌。进行检查并且是未处理错误来源的FL2 Rust代码如下所示:

code that generated the error

这导致了以下恐慌,进而导致了5xx错误:

thread fl2_worker_thread panicked: called Result::unwrap() on an Err value

unwrap() 调用是导致系统瘫痪的关键原因:

  • 当特征数量超过200个限制时返回 Err
  • unwrap() 直接解包导致线程恐慌(panic)
  • 恐慌传播导致HTTP 5xx错误

unwrap() 是一个用于处理 Option 或 Result 类型的函数。其主要作用是提取其中的值,但如果值是 None(对于 Option)或是 Err(对于 Result),则会导致程序 panic🤣

说白了就是bro不写错误判断

事故期间的其他影响

依赖我们核心代理的其他系统在事故期间受到影响。这包括Workers KV和Cloudflare Access。团队在21:04减少了这些系统的影响,当时对Workers KV进行了修补以绕过核心代理。随后,所有依赖Workers KV的下游系统(如Access本身)观察到错误率降低。

Cloudflare仪表板也受到影响,因为内部使用Workers KV以及Cloudflare Turnstile部署为我们的登录流程的一部分。

Turnstile受到此中断的影响,导致没有活动仪表板会话的客户无法登录。这表现为两个时间段内的可用性降低:从19:30到21:10,以及22:40到23:30之间,如下面的图表所示。

availability of Cloudflare internal APIs during the incident

第一个时期,从19:30到21:10,是由于对Workers KV的影响,某些控制平面和仪表板功能依赖于此。这在21:10恢复,当时Workers KV绕过了核心代理系统。仪表板的第二个影响时期发生在恢复特征配置数据之后。登录尝试的积压开始压倒仪表板。此积压与重试尝试相结合,导致延迟升高,降低了仪表板可用性。扩展控制平面并发性在约23:30恢复了可用性。

修复和后续步骤

现在我们的系统已重新上线并正常运行,已经开始研究我们将如何加固它们以防止未来发生此类故障。特别是我们:

  • 以与用户生成输入相同的方式强化Cloudflare生成配置文件的摄入
  • 为功能启用更多全局关闭开关
  • 消除核心转储或其他错误报告耗尽系统资源的能力
  • 审查所有核心代理模块的错误条件故障模式

今天是Cloudflare自2019年以来最严重的中断。我们有过使我们的仪表板不可用的中断。一些导致较新功能在一段时间内不可用。但在过去6年多里,我们没有另一个导致大多数核心流量停止流经我们网络的中断。

像今天这样的中断是不可接受的。我们设计了我们的系统具有高度弹性以确保流量将始终继续流动。当我们过去有过中断时,它总是导致我们构建新的、更有弹性的系统。

代表Cloudflare的整个团队,我想为我们今天给互联网造成的痛苦道歉。

时间 (北京时间)状态描述
19:05正常数据库访问控制变更部署
19:28影响开始部署到达客户环境,在客户HTTP流量上观察到首个错误
19:32-21:05团队调查Workers KV服务的流量水平和错误升高初始症状似乎是Workers KV响应率下降导致其他Cloudflare服务的下游影响。尝试了流量操作和账户限制等缓解措施以使Workers KV服务恢复正常运行水平。首个自动化测试在19:31检测到问题,手动调查在19:32开始。事故电话在19:35创建
21:05实施Workers KV和Cloudflare Access绕过 - 影响减少在调查期间,我们使用内部系统绕过Workers KV和Cloudflare Access,使它们回退到我们核心代理的先前版本
21:37工作重点回滚Bot Management配置文件到最后一个已知良好版本我们确信Bot Management配置文件是事故的触发器。团队通过多个工作流致力于修复服务,最快的工作流是恢复文件的先前版本
22:24停止创建和传播新的Bot Management配置文件我们识别出Bot Management模块是500错误的来源,并且这是由错误的配置文件引起的。我们停止了Bot Management配置文件的自动部署
22:24新文件测试完成我们观察到使用旧版本配置文件成功恢复,然后专注于加速全局修复
22:30主要影响解决。下游受影响服务开始观察到错误减少正确的Bot Management配置文件全局部署,大多数服务开始正确运行
01:06所有服务解决。影响结束所有下游服务重启,所有操作完全恢复