文章总结: Cloudflare于2025年11月18日11:20(UTC)发生严重宕机事故,原因是数据库权限变更导致BotManagement系统特征文件体积翻倍,超出流量路由软件处理上限,引发全球网络服务中断。故障影响了CoreCDN、Turnstile、WorkersKV等多项服务,团队在14:30找到根本问题并修复,17:06全面恢复。Cloudflare承诺将强化配置文件校验、启用更多紧急停用开关、消除核心转储挤占系统资源、审查核心代理模块失效模式,确保类似故障不再发生。 综合评分: 90 文章分类: 应急响应,漏洞分析,网络安全
Cloudflare 11·18 宕机事故解析
原创
喜吾安璇
攻防SRC
2025年11月19日 14:49 日本
本文为 Cloudflare 官方于 2025 年 11 月 18 日宕机事件发布的技术复盘文章的完整中文翻译。原文详细记录了此次事故的发生经过、原因分析、受影响的系统、修复过程以及 Cloudflare 后续的改进措施。为便于中文读者更好理解这次全球互联网基础设施级故障的技术细节与经验教训,我们对全文进行了忠实、完整的翻译与适度本地化处理。以下正文均基于 Cloudflare 官方原文编译整理,部分术语为保持准确性而保留英文。
2025 年 11 月 18 日 11:20(UTC)起(本文所有时间均为 UTC),Cloudflare 的网络开始出现严重故障,导致核心网络流量无法正常传输。对于尝试访问我们客户网站的用户而言,这一问题表现为无法访问页面,并看到一张提示 Cloudflare 网络内部发生错误的报错页面。
这一问题并非由任何形式的网络攻击或恶意活动直接或间接引起。真正的原因,是我们某个数据库系统的权限变更触发了异常行为,使数据库向我们的 Bot Management(机器人管理)系统所使用的“特征文件”中输出了多条额外记录。结果,这个特征文件的体积直接翻了一倍。随后,这个超过预期大小的特征文件被同步到了构成我们全球网络的所有机器上。
运行在这些机器上的流量路由软件会读取这一特征文件,以便让我们的 Bot Management(机器人管理)系统能够及时更新、应对不断变化的威胁。然而,该软件对特征文件的大小有一个上限,而这个上限低于文件翻倍后的实际大小。结果就是,软件在读取该文件时发生了故障。
在最初阶段,我们曾一度误以为所观察到的现象是由一场超大规模 DDoS 攻击引起的。随后,我们成功定位到了真正的核心问题,并及时阻止了那个超出预期大小的特征文件继续传播,同时将其替换为较早的正常版本。到 14:30 左右,核心流量已基本恢复正常。接下来的数小时里,我们持续处理网络各部分因流量迅速回归而出现的负载升高问题。到 17:06,Cloudflare 的所有系统均已恢复正常运行。
对于此次事件给我们的客户以及整个互联网带来的影响,我们深表歉意。鉴于 Cloudflare 在互联网生态中的重要性,我们深知:任何系统的宕机都是不可接受的。我们的网络在一段时间内无法正常路由流量,这对我们整个团队而言都是极其痛苦的事情。我们明白,今天我们让大家失望了。
这篇文章将深入回顾事故发生的全过程,并详细说明哪些系统和流程出现了失效。同时,这也是我们为确保类似宕机不再发生而采取改进措施的起点,而绝非终点。
本次故障概述
下图展示了 Cloudflare 网络在此次事件期间返回的 5xx 错误状态码 的数量。通常,这个数值应当保持在非常低的水平,而在宕机开始之前,它一直处于正常范围内。
11:20 之前的错误量是我们网络中常见的、符合预期的 5xx 错误基线。随后的尖峰和波动,则显示系统因加载了错误的特征文件而发生故障。值得注意的是,系统在出现异常后还会短暂自行恢复一段时间,这种行为对于内部错误而言相当不寻常。
原因在于,该特征文件是由一个运行在 ClickHouse 数据库集群上的查询任务每 5 分钟生成一次。而该集群当时正在逐步更新,用于改进权限管理。只有当查询在已更新的集群节点上运行时,才会生成错误数据。因此,每隔五分钟,系统都有可能生成一份正常或异常的配置文件,并被迅速同步到整个网络中。
这种反复波动让问题的真实成因变得难以判断,系统一会儿恢复、一会儿再次失败,因为有时下发的是正常配置文件,有时下发的则是异常配置文件。最初,这种表现让我们误以为可能遭受了攻击。最终,随着所有 ClickHouse 节点都开始生成错误的配置文件,系统的波动消失,彻底稳定在了失败状态。
错误一直持续到我们在 14:30 找到并解决根本问题为止。我们的解决方案是:先停止错误特征文件的生成与分发,然后将一份已知正常的特征文件手动插入到分发队列中,最后强制重启核心代理系统。
图表中后段较长的“尾巴”,对应的是我们团队在依次重启那些已进入异常状态的服务。到 17:06,5xx 错误数量完全恢复至正常水平。
以下服务受到了影响:
| 服务 / 产品 | 影响描述 | | — | — | | Core CDN 与安全服务 | 返回大量 HTTP 5xx 状态码。本文顶部截图展示了用户所见的典型错误页面。 | | Turnstile | Turnstile 无法加载。 | | Workers KV | Workers KV 返回的 HTTP 5xx 错误数量显著增加,因为 KV 的“前端”网关在核心代理出现故障后无法正常工作。 | | Dashboard(控制台) | 虽然控制台大部分时间可正常访问,但由于登录页依赖的 Turnstile 无法加载,大多数用户无法登录。 | | Email Security(邮件安全) | 尽管邮件处理与投递未受影响,但我们一度失去对某个 IP 信誉源的访问,这降低了垃圾邮件检测准确性,并导致部分基于域名年龄的新检测规则未能触发,但未造成关键客户影响。我们还观察到部分 Auto Move(自动移动规则)操作失败;所有受影响的消息均已审核并修复。 | | Access | 大多数用户在事件开始后出现广泛的身份验证失败,这种情况一直持续到 13:05 开始执行回滚为止。已有的 Access 会话不受影响。 所有失败的身份验证都会显示错误信息,意味着这些用户的请求在认证失败期间从未到达目标应用。但在此期间成功的登录记录均已正确写入日志。 事件期间进行的任何 Access 配置更新操作,要么完全失败,要么极为缓慢。目前所有配置更新均已恢复正常。 |
除了返回大量 HTTP 5xx 错误外,我们还观察到在故障影响期间,CDN 的响应延迟显著上升。其原因在于:我们用于调试与可观测性的系统会在发生未捕获错误时自动附加额外的调试信息,而这些操作消耗了大量 CPU 资源,从而导致延迟增加。
Cloudflare 如何处理请求,以及本次故障是如何发生的
每一条发送到 Cloudflare 的请求都会沿着我们网络中一条明确的路径进行处理。无论是浏览器加载网页、移动应用调用 API,还是其他服务发来的自动化流量,这些请求都会首先到达我们的 HTTP 与 TLS 层,随后进入核心代理系统(我们称之为 FL,Frontline 的缩写),最后通过 Pingora 处理,Pingora 会执行缓存查找,或在必要时向源站获取数据。
我们此前已经在另一篇文章中更详细地介绍了核心代理的工作原理,链接如下。
https://blog.cloudflare.com/zh-cn/20-percent-internet-upgrade/
当请求经过核心代理时,Cloudflare 会在该路径上运行网络中的各类安全与性能产品。代理会根据每位客户的独特配置与规则进行处理,从执行 WAF 规则、启用 DDoS 防护,到将流量路由至 Developer Platform 或 R2。核心代理通过一组领域专用的模块来完成这些任务,这些模块负责将配置与策略规则应用到所有经由代理转发的流量上。
在这些模块中,Bot Management(机器人管理)正是本次宕机的源头。
Cloudflare 的 Bot Management 系统包含多个子组件,其中之一是一个用于为所有经过我们网络的请求生成 bot 分数 的机器学习模型。我们的客户会根据这些 bot 分数来决定哪些爬虫或自动化流量可以访问他们的网站、哪些不可以。
该模型需要读取一个“特征”配置文件作为输入。在这里,“特征”指的是机器学习模型用来判断一个请求是否为自动化流量的单个属性或指标。而特征配置文件则由这些单个特征组合而成。
这个特征文件会每隔几分钟刷新一次,并同步到我们整个全球网络,使我们能够及时应对互联网上不断变化的流量模式。它帮助我们快速识别新的爬虫类型以及新出现的机器人攻击。因此,在攻击者不断改变策略的情况下,保持这种高频、快速的特征文件更新至关重要。
我们用于生成该特征文件的 ClickHouse 查询(原因将在下文解释)发生了行为变化,导致生成的文件中出现大量重复的“特征”行。这使得原本固定大小的特征配置文件突然变得更大,从而触发了 Bot Management 模块的错误。
因此,凡是依赖 Bot Management 模块的流量,其在经过为客户处理流量的核心代理系统时都会返回 HTTP 5xx 错误。这也连带影响到了 Workers KV 和 Access,因为它们同样依赖核心代理来处理请求。
与此次事件无关的是,我们当时正在(并仍在)将客户流量迁移到新版的代理服务,内部称为 FL2。此次问题对旧版与新版代理都造成了影响,只是两者受到的影响表现有所不同。
使用新版 FL2 代理引擎 的客户,会看到大量 HTTP 5xx 错误。而使用旧版代理引擎(称为 FL)的客户虽然没有出现错误页面,但由于无法正确生成 bot 分数,所有流量都被赋予了 0 分 的 bot score。对于那些基于 bot 分数设置了“阻止机器人”规则的客户来说,这会导致大量误判。而未在规则中使用 bot 分数的客户则不会受到影响。
让我们一度误判为可能遭受攻击的另一个“表象”症状是:Cloudflare 的状态页也同时宕了。状态页完全托管在 Cloudflare 体系之外,与 Cloudflare 的任何基础设施都没有依赖关系。虽然后来证明这只是巧合,但当时却让部分负责排查问题的团队成员认为,攻击者可能同时针对我们的系统与状态页发动攻击。当时访问状态页的用户会看到如下错误提示:
在内部的事故应急聊天频道中,我们一度担心,这可能是近期一系列 Aisuru 超大规模 DDoS 攻击的延续:
查询行为的变化
前文提到,底层查询行为的变化导致特征文件中出现了大量重复行。此次涉及的数据库系统使用的是 ClickHouse 软件。
为了理解问题的背景,先简单介绍一下 ClickHouse 的分布式查询是如何工作的。一个 ClickHouse 集群由多个 分片(shards) 组成。为了能够从所有分片读取数据,我们会在名为 default 的数据库中创建所谓的 分布式表(Distributed 引擎驱动)。Distributed 表会去查询底层位于 r0 数据库中的真实表,而这些底层表才是 ClickHouse 集群中每个分片实际存储数据的地方。
对分布式表的查询会通过一个共享的系统账户来执行。为了提高分布式查询的安全性和可靠性,我们正在进行一项改造工作:让这些查询改为在发起查询的原始用户账户下运行,而不再依赖共享系统账户。
在此之前,当 ClickHouse 用户从系统表(例如 system.tables 或 system.columns)查询表元数据时,他们只能看到 default 数据库中的那些表。
由于用户本身就对 r0 中的底层表拥有隐式访问权限,我们在 11:05 对系统进行了修改,使这种访问变为显式,从而让用户也能够看到这些底层表的元数据。通过确保所有分布式子查询都能够在发起查询的原始用户权限下执行,系统可以以更细粒度的方式评估查询限额与访问授权,从而避免某个用户的异常子查询影响到其他用户。
上述变更使所有用户都能够访问到其权限范围内表的准确元数据。然而,不幸的是,过去系统中存在一个长期的假设:类似下面这种查询返回的列列表只会包含来自 “default” 数据库的内容:
SELECT
name,
type
FROM system.columns
WHERE
table = 'http_requests_features'
order by name;
这条 SQL 查询用于从 ClickHouse 的 system.columns 系统表中,获取名为 http_requests_features 的表的所有列名 (name) 及其数据类型 (type),并按列名排序。
请注意,这条查询语句并没有按数据库名称进行过滤。随着我们逐步为 ClickHouse 集群中的用户启用显式授权,从 11:05 的改动开始,上述查询就开始返回“重复”的列,因为这些列来自存储在 r0 数据库中的底层表。
不幸的是,正是 Bot Management 特征文件生成逻辑在构建每个输入“特征”时,会执行类似上面的这类查询(即不按数据库过滤的查询)。
因此,上述查询会返回一个包含列信息的结果表,大致如下(示例已简化):
然而,由于我们为该用户授予了额外的访问权限,查询返回结果中开始包含 r0 模式(schema)下的全部元数据。这导致返回的行数直接增加了一倍以上,并最终使得输出的特征文件行数(即“特征”数量)也随之增多,超出了预期。
内存预分配
在我们的代理服务上运行的每个模块都会设定若干限制,用来防止无限制的内存占用,并通过预分配内存来提升性能。在这个具体案例中,Bot Management 系统对运行时可使用的机器学习特征数量设置了上限。目前这一上限为 200 个特征,而我们实际使用的特征大约只有 60 个。之所以设置这个限制,是因为系统会提前为这些特征预分配内存,以优化性能表现。
当包含 超过 200 个特征 的异常文件被分发到我们的服务器时,系统触发了该上限检查,从而导致系统 panic。下面展示的是 FL2 Rust 代码中负责执行该检查、并最终引发未捕获错误的部分:
这导致系统触发了如下 panic,从而返回了 5xx 错误:
thread fl2_worker_thread panicked: called Result::unwrap() on an Err value
事件期间的其他影响
在此次事件中,其他依赖核心代理的系统也受到了影响,其中包括 Workers KV 和 Cloudflare Access。在 13:04,团队通过为 Workers KV 发布补丁,使其能够绕过核心代理,从而降低了这些系统受到的影响。随后,所有依赖 Workers KV 的下游系统(包括 Access 自身)也随之观察到错误率下降。
Cloudflare Dashboard(控制台)也受到了影响,原因有两点:一是内部依赖 Workers KV,二是我们的登录流程中使用了 Cloudflare Turnstile。
由于此次故障,Turnstile 也受到了影响,导致没有有效 Dashboard 会话的客户无法登录。其可用性在两个时间段出现下降:11:30–13:10 和 14:40–15:30,如下图所示。
第一个影响时段(11:30–13:10)源于 Workers KV 的故障,因为部分控制平面与 Dashboard 功能依赖它。在 13:10,Workers KV 通过绕过核心代理系统恢复了正常,因此这一阶段的影响结束。第二个影响时段则发生在恢复特征配置数据之后。此前积压的大量登录请求开始涌入 Dashboard,造成系统压力过大。积压请求叠加重试流量,使 Dashboard 的延迟显著上升,从而导致可用性下降。通过提升控制平面的并发能力后,Dashboard 的可用性在大约 15:30 得到恢复。
修复措施与后续改进步骤
随着系统已全面恢复正常运行,我们已开始着手推进各项改进工作,以确保未来不会再出现类似故障。具体包括:
- 强化对 Cloudflare 自生成配置文件的校验与处理机制,使其具备与用户输入相同级别的安全防护能力
- 为各类功能启用更多全局级别的“紧急停用开关”(kill switches)
- 消除核心转储(core dump)或其他错误报告在异常情况下挤占系统资源的可能性
- 全面审查核心代理各模块在错误条件下的失效模式
今天的事件是 Cloudflare 自 2019 年以来最严重的一次宕机。过去,我们也经历过使 Dashboard 无法访问的故障,或让部分新功能在一段时间内不可用的情况。但在过去 6 年多的时间里,从未再发生过像今天这样,导致核心流量大范围中断、无法正常通过我们网络的宕机。
像今天这样的宕机是不可接受的。我们一直以高度弹性的体系结构设计系统,确保无论发生什么情况,流量都能持续流动。过去每一次故障,都会促使我们构建更可靠、更具韧性的系统。
我谨代表 Cloudflare 全体团队,对今天给整个互联网带来的影响致以诚挚的歉意。
Cloudflare 宕机事件时间线
| 时间(UTC) | 状态 | 描述 | | — | — | — | | 11:05 | 正常 | 部署数据库访问控制变更。 | | 11:28 | 影响开始 | 部署传播到客户环境,首次在客户 HTTP 流量中观察到错误。 | | 11:32–13:05 | 团队调查 Workers KV 服务的流量升高与错误 | 初始症状表现为 Workers KV 响应变慢,进而影响其他 Cloudflare 服务。 团队尝试通过调整流量、限制账户等措施使 Workers KV 恢复正常。 自动化测试于 11:31 首次检测到问题,人工调查于 11:32 开始,事故电话会议于 11:35 建立。 | | 13:05 | Workers KV 与 Cloudflare Access 启用绕过机制 — 影响减轻 | 在调查期间,我们为 Workers KV 和 Cloudflare Access 启用内部绕过机制,使其回退到旧版本的核心代理。虽然旧版本同样存在问题,但影响较小。 | | 13:37 | 开始将 Bot Management 配置文件回滚到上一次正常版本 | 我们确认 Bot Management 配置文件是事件触发点。多个团队开始探索修复方案,其中最快的方案是回滚至上一版本的配置文件。 | | 14:24 | 停止生成和分发新的 Bot Management 配置文件 | 我们确认 Bot Management 模块是 500 错误的根源,且原因是错误的配置文件,因此停止自动生成与分发新的配置文件。 | | 14:24 | 新文件测试完成 | 使用旧版本配置文件后,系统成功恢复;随后团队开始加速推动全球范围内的修复。 | | 14:30 | 主要影响解除,下游服务开始观察到错误减少 | 正常的 Bot Management 配置文件已在全球部署,大多数服务开始恢复正常运行。 | | 17:06 | 所有服务恢复,影响结束 | 所有下游服务重新启动,全部业务完全恢复。 |
Cloudflare outage on November 18, 2025 https://blog.cloudflare.com/18-november-2025-outage/
Defending the cloud: Azure neutralized a record-breaking 15 Tbps DDoS attack https://techcommunity.microsoft.com/blog/azureinfrastructureblog/defending-the-cloud-azure-neutralized-a-record-breaking-15-tbps-ddos-attack/4470422
Defending the Internet: how Cloudflare blocked a monumental 7.3 Tbps DDoS attack https://blog.cloudflare.com/defending-the-internet-how-cloudflare-blocked-a-monumental-7-3-tbps-ddos/
查看原文:《Cloudflare 11·18 宕机事故解析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论