5 мин. чтения
5 декабря 2025 г. в 08:47 по UTC (все время в этом блоге указано в формате UTC (всеобщее скоординированное время)), в некоторых сетях Cloudflare начали возникать серьезные сбои. Инцидент был устранен в 09:12 (общее время воздействия составило примерно 25 минут), после чего работа всех сервисов была полностью восстановлена.
Была затронута часть клиентов, на которую приходится около 28 % всего HTTP-трафика, обслуживаемого Cloudflare. Чтобы отдельный клиент оказался затронут, необходимо было сочетание нескольких факторов, приведенных ниже.
Проблема не была вызвана (напрямую или косвенно) кибератакой на системы Cloudflare или какой-либо вредоносной деятельностью. На самом деле причиной стали изменения, внесенные в логику анализа тела запроса при попытке обнаружить и устранить общеотраслевую уязвимость, обнаруженную на этой неделе в серверных компонентах React.
Любой сбой в работе наших систем неприемлем, и мы знаем, что снова подвели пользователей Интернета после инцидента, произошедшего 18 ноября. На следующей неделе мы опубликуем поэтапное описание наших действий по недопущению подобных инцидентов.
На графике ниже показаны ошибки HTTP 500, обработанные нашей сетью в течение инцидента (красная линия внизу), в сравнении с незатронутым общим трафиком Cloudflare (зеленая линия вверху).
Межсетевой экран веб-приложений (WAF), предоставляемый Cloudflare, обеспечивает клиентам защиту от вредоносного трафика, позволяя обнаруживать и блокировать его. Для этого прокси-сервер Cloudflare добавляет содержимое тела HTTP-запроса в буфер памяти для проведения анализа. До настоящего момента размер буфера составлял 128 КБ.
В рамках нашей постоянной работы по защите клиентов, использующих библиотеку React, от критической уязвимости CVE-2025-55182 мы начали увеличивать размер нашего буфера до 1 МБ — это максимальный предел, который по умолчанию допускается приложениями Next.js. Нашей целью было обеспечение защиты максимального количества клиентов.
Это первое изменение внедрялось с использованием нашей системы постепенного развертывания. В ходе развертывания мы заметили, что наш внутренний инструмент тестирования межсетевого экрана WAF не поддерживает увеличенный размер буфера. Поскольку в то время этот инструмент для внутреннего тестирования не требовался и не оказывал влияния на клиентский трафик, мы внесли второе изменение, чтобы отключить его.
Это второе изменение, связанное с отключением нашего инструмента тестирования WAF, было реализовано с использованием нашей глобальной системы конфигурации. Эта система не выполняет постепенное развертывание, а скорее распространяет изменения в течение нескольких секунд по всей сети и находится на стадии проверки после сбоя, имевшего место 18 ноября.
К сожалению, в нашей версии прокси-сервера FL1 при определенных обстоятельствах второе отключение нашего инструмента тестирования правил WAF вызвало состояние ошибки, в результате чего из нашей сети стали поступать коды ошибок HTTP 500.
Как только это изменение было внедрено в нашей сети, выполнение кода на нашем прокси-сервере FL1 привело к ошибке в модуле правил, что привело к следующему исключению 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.
Проблема была выявлена вскоре после применения изменения, внедрение которого было отменено в 09:12, после чего весь трафик обрабатывался корректно.
Это повлияло на клиентов, чьи веб-ресурсы обслуживались нашим старым прокси-сервером FL1 И у которых был развернут управляемый набор правил Cloudflare. Все запросы для веб-сайтов в этом состоянии возвращали ошибку HTTP 500, за небольшим исключением некоторых тестовых конечных точек, таких как /cdn-cgi/trace.
Клиенты, у которых не была развернута указанная выше конфигурация, не пострадали. Трафик клиентов, обслуживаемый нашей сетью China network, также обрабатывался без задержек.
Ошибка времени выполнения
Система наборов правил Cloudflare состоит из наборов правил, которые оцениваются для каждого запроса, поступающего в нашу систему. Правило состоит из фильтра, который выбирает трафик, и действия, применяющего к этому трафику определенный эффект. Типичные действия включают в себя следующие: «блокировать», «записать в журнал» или «пропустить». Другим типом действия является «выполнить», которое используется для запуска оценки другого набора правил.
Наша внутренняя система ведения журналов использует эту функцию для оценки новых правил, прежде чем мы сделаем их общедоступными. Набор правил верхнего уровня задействует другой набор, который содержит правила проверки. Именно эти правила мы пытались отключить.
В системе наборов правил есть подсистема аварийного отключения, которая позволяет быстро отключить то или иное правило, ведущее к сбоям в работе. Эта система аварийного отключения получает информацию из нашей глобальной системы конфигурации, упомянутой в предыдущих разделах. В прошлом мы несколько раз использовали эту систему для смягчения последствий инцидентов и разработали четкую стандартную операционную процедуру, которая была задействована при устранении этого инцидента.
Однако мы еще никогда не применяли систему аварийного отключения к правилу с действием «выполнить». При применении аварийного отключения код корректно пропускал оценку действия «выполнить» и не оценивал поднабор правил, на который он указывал. Однако затем произошла ошибка при обработке общих результатов оценки набора правил:
if rule_result.action == "execute" then
rule_result.execute.results = ruleset_results[tonumber(rule_result.execute.results_index)]
end
Этот код ожидает, что, если в наборе правил задано действие = «выполнить», объект «rule_result.execute» будет существовать. Однако, поскольку правило было пропущено, объект «rule_result.execute» не существовал, и LUA вернул ошибку из-за попытки поиска значения в нулевом значении.
Это очевидная ошибка в коде, которая оставалась незамеченной в течение многих лет. Подобные ошибки в коде предотвращаются языками со строгими системами типов. При замене этого кода в нашем новом прокси-сервере FL2, написанном на Rust, ошибка не возникала.
Какова ситуация с изменениями, вносимыми после инцидента 18 ноября 2025 года?
Мы внесли несвязанное изменение, которое вызвало аналогичный, но более длительный инцидент две недели назад, 18 ноября 2025 года. В обоих случаях развертывание, направленное на устранение проблемы безопасности для клиентов, распространилось на всю нашу сеть и привело к ошибкам почти у всех наших клиентов.
После этого инцидента мы напрямую пообщались с сотнями клиентов и поделились планами по внесению изменений, чтобы предотвратить масштабные последствия, вызванные отдельными обновлениями. Мы считаем, что эти изменения могли бы помочь предотвратить последствия сегодняшнего инцидента, но, к сожалению, мы еще не завершили их развертывание.
Мы осознаем все связанные с этим неприятные последствия. Это остается основной задачей для всех наших специалистов. В частности, проекты, описанные ниже, должны устранить негативное влияние такого рода изменений:
Улучшенные развертывания и управление версиями: как и в случае с постепенным развертыванием программного обеспечения со строгой проверкой работоспособности, данные, используемые для быстрого реагирования на угрозы и общей настройки, должны иметь аналогичные функции безопасности и защиты от сбоев. Это включает в себя, помимо прочего, проверку работоспособности и возможности быстрого отката.
Оптимизированные возможности аварийного восстановления: обеспечение возможности выполнения критически важных операций даже в условиях дополнительных типов сбоев. Это относится к внутренним службам, а также ко всем стандартным методам взаимодействия с плоскостью управления Cloudflare, используемым всеми клиентами Cloudflare.
Обработка ошибок «Fail-Open» (сбой при открытии): в рамках усилий по обеспечению устойчивости систем мы заменяем неправильно примененную логику жесткого отказа во всех критически важных компонентах плоскости данных Cloudflare. Если файл конфигурации поврежден или выходит за рамки допустимых значений (например, превышены лимиты функций), система регистрирует ошибку и по умолчанию переходит в известное рабочее состояние или пропускает трафик без оценки, а не отклоняет запросы. В некоторых сервисах клиентам, вероятно, будет предоставляться возможность выбора между сбоем при открытии или закрытии в определенных ситуациях. Это будет включать в себя функции предотвращения отклонений, чтобы обеспечить постоянное применение.
До конца следующей недели мы опубликуем подробное описание всех текущих проектов по обеспечению устойчивости, включая вышеперечисленные. Пока эта работа продолжается, мы блокируем все изменения в нашей сети, чтобы убедиться, что у нас есть более эффективные системы смягчения последствий и отката, прежде чем мы вернемся к обычному режиму.
Такого рода инциденты и то, как тесно они связаны между собой, неприемлемы для такой сети, как наша. От имени команды Cloudflare мы хотим принести извинения за последствия и ущерб, которые это снова нанесло нашим клиентам и Интернету в целом.
Время (UTC) | Статус | Описание |
08:47 | Начало инцидента | Изменение конфигурации развернуто и распространено в сети |
08:48 | Полное воздействие | Изменение полностью внедрено |
08:50 | Объявление инцидента | Автоматизированные оповещения |
09:11 | Отмена изменения | Изменение конфигурации отменяется и начинается внедрение |
09:12 | Завершение инцидента | Изменение отменено полностью, весь трафик восстановлен |