12 мин. чтения
18 ноября 2025 г. в 11:20 UTC (все время в этом блоге указано в UTC), в сети Cloudflare начались значительные сбои в передаче основного сетевого трафика. Это обнаруживалось у пользователей Интернета, пытавшихся получить доступ к сайтам наших клиентов в виде страницы с ошибкой, указывающей на сбой в сети Cloudflare.
Проблема не была вызвана прямо или косвенно кибератакой или вредоносными действиями любого рода. Это было вызвано изменением разрешений одной из наших систем баз данных, что привело к выводу нескольких записей в «файл функций», используемый нашей системой управления ботами. Этот файл функций, в свою очередь, увеличился вдвое. Файл функции, превышающий ожидания, был затем распространен на все машины, составляющие нашу сеть.
Программное обеспечение, работающее на этих машинах и предназначенное для маршрутизации трафика в нашей сети, считывает этот файл конфигурации, чтобы поддерживать систему управления ботами в актуальном состоянии в условиях постоянно меняющихся угроз. В программном обеспечении существовало ограничение на размер файла компонента, который был меньше его удвоенного размера. Это вызвало сбой в работе программного обеспечения.
После того, как мы сначала ошибочно предположили, что наблюдаемые симптомы вызваны масштабной DDoS-атакой, мы правильно определили основную проблему и смогли остановить распространение файла функций, размер которого превышал ожидаемый, и заменили его более ранней версией. К 14:30 основной трафик в основном восстановился до нормального уровня. В течение следующих нескольких часов мы работали над снижением возросшей нагрузки на различные части нашей сети, поскольку трафик восстанавливался. По состоянию на 17:06 все системы Cloudflare функционировали в штатном режиме.
Приносим извинения за последствия для наших клиентов и для Интернета в целом. Учитывая важность Cloudflare в интернет-экосистеме, любой сбой наших систем недопустим. Тот факт, что в течение некоторого времени наша сеть не могла маршрутизировать трафик, вызывает глубокую боль у каждого члена нашей команды. Мы знаем, что сегодня мы вас подвели.
Эта публикация представляет собой подробное изложение того, что именно произошло, и какие системы и процессы дали сбой. Это также начало, но не конец того, что мы планируем предпринять, чтобы подобный сбой больше не повторился.
На диаграмме ниже показано количество кодов состояния HTTP 5xx, обработанных сетью Cloudflare. Обычно это значение должно быть очень низким, и оно таким и было вплоть до начала сбоя.
Объем до 11:20 — это ожидаемый базовый уровень ошибок 5xx, наблюдаемый в нашей сети. Всплеск и последующие колебания указывают на сбой нашей системы из-за загрузки некорректного файла функций. Примечательно, что затем наша система восстанавливалась в течение некоторого времени. Такое поведение совсем не характерно для внутренней ошибки.
Объяснение заключалось в том, что файл генерировался каждые пять минут запросом, выполняемым в кластере баз данных ClickHouse, который постепенно обновлялся для улучшения управления разрешениями. Недопустимые данные генерировались только в том случае, если запрос выполнялся на части кластера, которая была обновлена. В результате, каждые пять минут существовала вероятность генерации и быстрого распространения по сети как работоспособных, так и вредоносных файлов конфигурации.
Из-за этих колебаний было неясно, что происходит, так как вся система восстанавливалась, а затем снова выходила из строя, поскольку в нашу сеть распространялись то хорошие, то плохие файлы конфигурации. Первоначально это заставило нас предположить, что причиной может быть атака. В конечном итоге каждый узел ClickHouse генерировал некорректный файл конфигурации, и колебания стабилизировались в аварийном состоянии.
Ошибки продолжались до выявления и устранения основной проблемы, что началось с 14:30. Мы решили проблему, остановив генерацию и распространение поврежденного файла компонента и вручную добавив заведомо исправный файл в очередь распространения файлов компонентов. Затем принудительно перезапустив наш основной прокси-сервер.
Оставшийся «длинный хвост» на диаграмме выше — это наша команда, перезапустившая остальные сервисы, которые перешли в аварийное состояние. Объем ошибок 5xx вернулся к норме в 17:06.
Были затронуты следующие сервисы:
Сервис и продукт | Описание воздействия |
|---|
Основные службы CDN и безопасности | Коды состояния HTTP 5xx. На снимке экрана в верхней части этой статьи показана типичная страница ошибки, отображаемая для конечных пользователей. |
Turnstile | Turnstile не удалось выполнить загрузку. |
Workers KV | Workers KV вернул значительно повышенный уровень ошибок HTTP 5xx, поскольку запросы к шлюзу KV «front end» не удалось выполнить из-за сбоя основного прокси-сервера. |
Информационная панель | Хотя панель управления в основном работала, большинство пользователей не могли войти в систему, так как Turnstile был недоступен на странице входа. |
Защита электронной почты | Несмотря на то, что обработка и доставка электронной почты не были затронуты, мы наблюдали временную потерю доступа к источнику IP-репутации, что снизило точность обнаружения спама и препятствовало срабатыванию некоторых обнаружений возраста новых доменов, при этом не было отмечено критического воздействия на клиентов. Мы также наблюдали сбои в некоторых операциях автоматического перемещения. Все затронутые сообщения были просмотрены и исправлены. |
Access | Сбои аутентификации были широко распространены среди большинства пользователей с начала инцидента и до момента запуска отката в 13:05. Существующие сеансы Access не были затронуты.
Все неудачные попытки аутентификации приводили к появлению страницы ошибки. Это означает, что ни один из этих пользователей не получил доступ к целевому приложению во время сбоя аутентификации. Успешные входы в систему за этот период были корректно зарегистрированы во время инцидента.
Любые попытки обновления конфигурации Access в то время либо сразу потерпели бы неудачу, либо распространялись бы очень медленно. Все обновления конфигураций восстановлены. |
Помимо возврата ошибок HTTP 5xx, мы наблюдали значительное увеличение задержки ответов от нашей CDN в период воздействия. Это произошло из-за того, что наши системы отладки и мониторинга используют большое количество ЦП, которые автоматически сопоставляют неперехваченные ошибки с помощью дополнительной отладочной информации.
Как Cloudflare обрабатывает запросы и что сегодня пошло не так
Каждый запрос к Cloudflare проходит по четко определенному пути в нашей сети. Это может быть браузер, загружающий веб-страницу, мобильное приложение, вызывающее API, или автоматизированный трафик из другого сервиса. Эти запросы сначала завершаются на нашем уровне HTTP и TLS, затем поступают в нашу основную прокси-сервер систему (которую мы называем FL — «Frontline»), и, наконец, в Pingora, которая выполняет поиск в кэше или, при необходимости, извлекает данные из исходного сервера.
Ранее мы поделились более подробной информацией о том, как работает базовый прокси-сервер, здесь.
Когда запрос проходит через основной прокси-сервер, мы запускаем различные продукты для обеспечения безопасности и повышения производительности, доступные в нашей сети. Прокси-сервер применяет уникальную конфигурацию и настройки каждого клиента, от применения правил WAF и Защиты от DDoS-атак до маршрутизации трафика на платформу разработчиков и R2. Это достигается посредством набора специализированных модулей, которые применяют правила конфигурации и политики к трафику, проходящему через наш прокси-сервер.
Один из этих модулей, Управление ботами, и стал источником сегодняшнего сбоя.
Управление ботами от Cloudflare включает в себя, помимо прочего, модель машинного обучения, которую мы используем для генерации оценок ботов для каждого запроса, проходящего через нашу сеть. Наши клиенты используют баллы ботов, чтобы контролировать доступ ботов к своим сайтам, разрешая или запрещая его.
Модель использует в качестве входных данных файл конфигурации «функции». В данном контексте признак — это отдельная характеристика, используемая моделью машинного обучения для прогнозирования, был ли запрос автоматизированным. Файл конфигурации функций представляет собой набор отдельных функций.
Этот файл с данными об особенностях работы сети обновляется каждые несколько минут и публикуется во всей нашей сети, что позволяет нам реагировать на изменения в потоках трафика в Интернете. Это позволяет нам реагировать на новые типы ботов и новые бот-атаки. Поэтому крайне важно, чтобы развертывание выполнялось часто и быстро, так как злоумышленники оперативно меняют тактику.
Изменение в нашем базовом поведении запросов ClickHouse (описано ниже), которое привело к созданию этого файла, вызвало появление большого количества дублирующихся строк «feature». Изменение размера файла конфигурации функции с ранее фиксированным размером привело к ошибке в модуле ботов.
В результате, основная прокси-сервер система, обрабатывающая трафик наших клиентов, возвращала коды ошибок HTTP 5xx для трафика, зависящего от модуля ботов. Это также затронуло Workers KV и Access, которые используют основной прокси-сервер.
Вне связи с этим инцидентом, мы переносили и в настоящее время переносим трафик наших клиентов на новую версию нашего прокси-сервера, внутренне известную как FL2. Обе версии были затронуты этой проблемой, хотя наблюдаемое воздействие отличалось.
Клиенты, использующие новый прокси-сервер FL2, наблюдали ошибки HTTP 5xx. Клиенты, использующие наши старые прокси-серверы FL, не наблюдали ошибок, но оценки ботов генерировались некорректно, в результате чего весь трафик получал нулевой балл бота. Клиенты, у которых были развернуты правила для блокировки ботов, могли наблюдать большое количество ложноположительных результатов. Клиенты, которые не использовали нашу оценку бота в своих правилах, не заметили какого-либо влияния.
Сбить нас с толку и заставить полагать, что это могла быть атака, было еще одним очевидным симптомом, который мы наблюдали: страница статуса Cloudflare не работала. Страница статуса размещена полностью за пределами инфраструктуры Cloudflare и не имеет зависимостей от Cloudflare. Хотя это оказалось совпадением, это привело некоторых сотрудников, занимавшихся диагностикой проблемы, к мнению, что злоумышленник мог нацелиться как на наши системы, так и на страницу статуса. Посетители страницы статуса в это время встречались сообщением об ошибке:
Во внутреннем чате по инцидентам мы забеспокоились, что это может быть продолжением недавней серии DDoS-атак большой мощности на Aisuru:
Изменение в поведении запроса
Выше я упоминал, что изменение в базовом поведении запроса привело к тому, что файл компонента содержит большое количество повторяющихся строк. Рассматриваемая система баз данных использует программное обеспечение ClickHouse.
Для контекста полезно знать, как работают распределенные запросы ClickHouse. Кластер ClickHouse состоит из множества сегментов. Для запроса данных из всех сегментов у нас есть так называемые распределённые таблицы (на базе табличного движка Distributed) в базе данных под названием default. Распределенный механизм запрашивает базовые таблицы в базе данных r0. Базовые таблицы — это место, где данные хранятся на каждом сегменте кластера ClickHouse.
Запросы к распределенным таблицам выполняются через общую системную учетную запись. В рамках усилий по повышению безопасности и надежности наших распределенных запросов, ведется работа по их запуску от имени первоначальных учетных записей пользователей.
До настоящего времени пользователи CheckHouse могли видеть таблицы в базе данных по умолчанию только при запросе метаданных таблиц из системных таблиц clickHouse, таких как системные.tables или системные.columns.
Поскольку у пользователей уже есть неявный доступ к базовым таблицам в r0, мы внесли изменение в 11:05, чтобы сделать этот доступ явным. Теперь пользователи также могут видеть метаданные этих таблиц. Убедившись, что все распределенные подзапросы выполняются от имени исходного пользователя, можно более точно оценить ограничения запросов и права доступа, что позволит избежать влияния одного неудачного подзапроса от пользователя на других.
В результате описанного выше изменения все пользователи получили доступ к точным метаданным таблиц, к которым у них есть доступ. К сожалению, в прошлом делались предположения, что список столбцов, возвращаемый подобным запросом, будет включать только базу данных «по умолчанию»:
ВЫБЕРИТЕ
имя,
тип
ИЗ system.columns ГДЕ
table = 'http_requests_features'
сортировать по имени;
Обратите внимание, что запрос не фильтрует по имени базы данных. По мере постепенного развертывания явных разрешений для пользователей определенного кластера ClickHouse, после изменения в 11:05 вышеуказанный запрос начал возвращать «дубликаты» столбцов, поскольку они относились к базовым таблицам, хранящимся в базе данных r0.
К сожалению, именно такой тип запроса выполнялся логикой генерации файла признаков управление ботами для создания каждого входного «признака» для файла, упомянутого в начале этого раздела.
Приведенный выше запрос возвращает таблицу столбцов, аналогичную показанной (упрощенный пример):
Однако в рамках дополнительных разрешений, предоставленных пользователю, ответ теперь содержал все метаданные схемы r0, что фактически более чем вдвое увеличило количество строк в ответе, в конечном итоге повлияв на количество строк (т. е. функции) в конечном выходном файле.
Предварительное выделение памяти
Каждый модуль, работающий в нашем прокси-сервере, имеет ряд ограничений для предотвращения неограниченного потребления памяти и предварительного выделения памяти в целях оптимизации производительности. В данном конкретном случае, система управления ботами имеет ограничение на количество функций машинного обучения, используемых во время выполнения. В настоящее время это ограничение установлено на 200, что значительно превышает текущее использование ~60 функций. Опять же, ограничение существует, поскольку для повышения производительности мы предварительно выделяем память для функций.
Когда вредоносный файл, содержащий более 200 функций, был распространен на наши серверы, это привело к превышению лимита и системной панике. Ниже представлен код Rust FL2, который выполняет проверку и является источником необработанной ошибки:
Это вызвало следующую панику, что, в свою очередь, привело к ошибке 5xx:
поток fl2_worker_thread запаниковал: вызван Result::unwrap() для значения Err
Другое воздействие во время инцидента
Во время инцидента были затронуты другие системы, использующие наш основной прокси-сервер. Сюда входили Workers KV и Cloudflare Access. Команде удалось снизить воздействие на эти системы в 13:04, когда в Workers KV было применено исправление безопасности, обходящее основной прокси-сервер. Впоследствии во всех подчиненных системах, использующих Workers KV (например, Access), наблюдалось снижение частоты ошибок.
Информационная панель Cloudflare также была затронута, поскольку как для внутреннего использования использовалось Workers KV, так и для внутреннего использования Cloudflare Turnstile, который был развернут при входе в систему.
Этот сбой затронул компанию Turnstile, в результате чего клиенты, не имевшие активного сеанса работы с панелью управления, не могли войти в систему. Это отображалось как снижение доступности в течение двух периодов времени: с 11:30 до 13:10 и с 14:40 до 15:30, как показано на графике ниже.
Первый период с 11:30 до 13:10 был вызван воздействием на Workers KV, от которого зависят некоторые функции панели управления и мониторинга. Это было восстановлено в 13:10, когда Workers KV обошёл основную систему прокси-серверов.
Второй период воздействия на панель мониторинга произошел после восстановления данных конфигурации функции. Накопление попыток входа в систему начало перегружать панель управления. Этот бэклог в сочетании с повторными попытками привел к увеличению задержки и снижению доступности панели управления. Масштабирование параллельной плоскости управления восстановило доступность приблизительно в 15:30.
Действия по исправлению и последующие шаги
Теперь, когда наши системы снова в сети и функционируют нормально, уже началась работа над тем, как мы будем укреплять их для защиты от подобных сбоев в будущем. В частности, мы:
Усиление приема файлов конфигурации, созданных Cloudflare, аналогично усилению приема пользовательского ввода
Включение большего количества глобальных выключателей для функций
Устранение возможности перегрузки системных ресурсов дампами памяти или другими отчётами об ошибках
Анализ режимов отказов на предмет ошибочных ситуаций во всех основных прокси-сервер модулях
Сегодня был самый серьезный сбой в работе Cloudflare с 2019 года. У нас случались сбои, из-за которых наша информационная панель была недоступна. Некоторые из них привели к тому, что новые функции не будут доступны в течение определенного периода времени. Но за последние шесть с лишним лет у нас не было ни одного другого сбоя, который привел бы к прекращению большей части основного трафика, проходящего через нашу сеть.
Сегодняшний сбой недопустим. Мы разработали высокую устойчивость наших систем к сбоям, чтобы гарантировать бесперебойную работу трафика. Сбои в работе у нас всегда приводили к созданию новых, более устойчивых систем.
От имени всей команды 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 | Работа была сосредоточена на восстановлении файла конфигурации управления ботами до последней работоспособной версии. | Мы были уверены, что файл конфигурации управления ботами стал причиной инцидента. Команды работали над способами восстановления сервиса, используя несколько рабочих потоков. Самым быстрым способом было восстановление предыдущей версии файла. |
14:24 | Создание и распространение новых файлов конфигурации управление ботами прекращено. | Мы определили, что модуль управления ботами был источником ошибок 500, и это было вызвано некорректным файлом конфигурации. Мы остановили автоматическое развертывание новых файлов конфигурации управление ботами. |
14:24 | Тестирование нового файла завершено. | Мы наблюдали успешное восстановление, используя старую версию файла конфигурации, а затем сосредоточились на ускорении исправления в глобальном масштабе. |
14:30 | Основное воздействие устранено. Сервисы для нейтрализации DDoS-атак начали отмечать снижение ошибок. | Правильный файл конфигурации Управление ботами был развернут глобально, и большинство сервисов начали работать правильно. |
17:06 | Работа всех сервисов восстановлена. Воздействие прекращается. | Все подчиненные службы перезапущены, и все операции полностью восстановлены. |