Lecture: 12 min.
Le 18 novembre 2025 à 11 h 20 UTC (toutes les heures mentionnées dans cet article sont au format UTC), le réseau Cloudflare a commencé à connaître des défaillances significatives de sa capacité à transmettre le trafic réseau principal. Pour les utilisateurs d'Internet tentant d'accéder aux sites de nos clients, ces défaillances se sont présentées sous la forme d'une page d'erreur indiquant un problème au sein du réseau Cloudflare.
Le dysfonctionnement ne résultait, directement ou indirectement, ni d'une cyberattaque ni d'une activité malveillante. L'événement était en réalité dû à une modification des permissions au sein d'un de nos systèmes de base de données. Cette opération a contraint la base de données à sortir plusieurs entrées au sein d'un « fichier de fonctionnalité » utilisé par notre système de gestion des bots Bot Management. Ce fichier a doublé de taille en retour. Plus volumineux que prévu, le fichier de fonctionnalité a ensuite été propagé à toutes les machines qui composent notre réseau.
Le logiciel exécuté sur ces machines lit ce fichier de fonctionnalités afin d'acheminer le trafic sur notre réseau et de maintenir le système de notre service Bot Management à jour face à un panorama des menaces en constante évolution. La limite définie pour ce fichier de fonctionnalité au sein du logiciel était inférieure à la taille réelle du fichier ce jour-là, qui représentait le double de la normale. Ce problème a entraîné une défaillance du logiciel.
Après avoir initialement soupçonné (à tort) que les symptômes observés résultaient d'une attaque DDoS hypervolumétrique, nous avons correctement identifié le problème principal. Nous avons ainsi pu mettre un terme à la propagation de ce fichier de fonctionnalité plus volumineux que prévu et le remplacer par une version antérieure. Le trafic principal était, dans sa plus grande part, revenu à la normale à 14 h 30. Au cours des heures qui ont suivi, nous nous sommes efforcés d'atténuer la charge accrue pesant sur diverses parties de notre réseau à mesure que le trafic revenait en ligne. Tous les systèmes Cloudflare fonctionnaient à nouveau normalement à 17 h 06.
Nous sommes navrés des répercussions de cet événement sur nos clients et sur Internet en général. Compte tenu de l'importance de Cloudflare au sein de l'écosystème Internet, toute forme d'interruption de nos systèmes se révèle inacceptable. Chaque membre de notre équipe est profondément peiné que notre réseau n'ait pas été en mesure de router le trafic pendant un certain temps. Nous savons que nous vous avons déçus aujourd'hui.
Cet article présente un compte rendu détaillé des événements, tels qu'ils se sont produits exactement, ainsi que des systèmes et des processus qui ont été pris en défaut. Il marque également le début (mais pas la fin) des mesures que nous prévoyons de déployer afin de nous assurer qu'une défaillance de ce genre ne se reproduise plus.
Le graphique ci-dessous montre le volume de codes d'erreur HTTP 5xx renvoyés par le réseau Cloudflare. Cette valeur devrait normalement être très faible. Il l'était d'ailleurs jusqu'au début de la défaillance.
Le volume avant 11 h 20 correspond au niveau de base attendu en termes d'erreurs 5xx observées sur notre réseau. Le pic et les fluctuations ultérieures montrent la défaillance de notre système en raison d'un chargement incorrect du fichier de fonctionnalité. Fait notable, nous pouvons remarquer que notre système a ensuite connu des moments de rétablissement pendant un certain temps. Ce comportement était très inhabituel pour une erreur interne.
L'explication de ces moments de rétablissement réside dans le fait que le fichier était généré toutes les cinq minutes par une requête exécutée sur un cluster de base de données ClickHouse, qui faisait l'objet d'une mise à jour progressive destinée à améliorer la gestion des autorisations. Les données incorrectes n'étaient générées que si la requête était exécutée sur une partie du cluster en cours de mise à jour. Il y avait par conséquent une chance pour que le fichier de configuration généré et rapidement propagé sur le réseau toutes les cinq minutes se révèle fonctionnel ou dysfonctionnel.
Ces fluctuations compliquaient fortement nos efforts visant à comprendre ce qui se passait, car du fait de la distribution de fichiers de configuration tantôt valides, tantôt dysfonctionnels sur notre réseau, le système dans son ensemble se rétablissait avant de connaître une nouvelle défaillance. C'est ce comportement qui nous a fait croire au départ que l'événement pouvait être dû à une attaque. Au bout du compte, chaque nœud ClickHouse s'est mis à générer le mauvais fichier de configuration et la fluctuation s'est stabilisée dans un état de défaillance.
Les erreurs se sont poursuivies jusqu'à identification et résolution du problème sous-jacent, soit à partir de 14 h 30. Nous avons résolu le problème en arrêtant la génération/propagation du fichier de fonctionnalité erroné, puis en insérant manuellement un fichier fonctionnel connu au sein de la file d'attente de distribution du fichier de fonctionnalité. Nous avons ensuite forcé le redémarrage de notre proxy principal.
La longue traîne subsistante dans le graphique ci-dessus représente les efforts de redémarrage, par notre équipe, des services restants qui commençaient eux aussi à se dégrader. Le nombre de codes d'erreur 5xx a retrouvé son volume normal à 17 h 06.
Voici la liste des services affectés par l'événement :
Service/produit | Description de l'effet |
|---|
CDN et services de sécurité de base | Codes d'état HTTP 5xx. La capture d'écran figurant au début de l'article montre la page d'erreur typique que les utilisateurs finaux ont vu s'afficher. |
Turnstile | Turnstile n'a pas pu se charger. |
Workers KV | Workers KV a renvoyé un niveau considérablement élevé d'erreurs HTTP 5xx du fait de l'échec des requêtes adressées à la passerelle « front-end » de KV résultant de la défaillance du proxy principal. |
Tableau de bord | Le tableau de bord est resté majoritairement opérationnel, mais la plupart des utilisateurs ne parvenaient pas à se connecter, car Turnstile était indisponible sur la page de connexion. |
Email Security | Le traitement et la distribution du courrier électronique n'ont pas été affectés, mais nous avons constaté une perte temporaire d'accès à une source de réputation d'IP. Cette perte a réduit la précision de nos fonctionnalités de détection du spam et empêché le déclenchement de certaines mesures de détection liées à l'ancienneté des nouveaux domaines. Aucune répercussion critique n'a cependant été observée pour nos clients. Nous avons également constaté des dysfonctionnements au niveau de certaines actions de déplacement automatique (Auto Move). Tous les messages concernés ont été examinés et corrigés. |
Access | La défaillance du processus d'authentification s'est généralisée pour la plupart des utilisateurs dès le début de l'incident et s'est poursuivie jusqu'au lancement de la restauration à 13 h 05. Les sessions Access existantes n'ont pas été touchées.
Toutes les tentatives d'authentification en situation d'échec ont entraîné la présentation d'une page d'erreur. Aucun de ces utilisateurs n'a donc jamais pu accéder à l'application cible pendant cet épisode de défaillance. Les connexions qui ont réussi à être établies pendant l'incident ont été correctement journalisées.
Les éventuelles tentatives de mise à jour de la configuration d'Access pendant cette période auraient soit complètement échoué, soit fait l'objet d'une propagation très lente. Toutes les mises à jour des configurations sont désormais restaurées. |
Outre le renvoi d'erreurs HTTP 5xx, nous avons constaté une forte hausse de la latence des réponses de notre CDN pendant l'événement. Ce phénomène résultait d'une consommation importante de ressources CPU par nos systèmes de débogage et d'observabilité, qui améliorent automatiquement le processus de détection des erreurs non interceptées à l'aide d'informations de débogage supplémentaires.
Chaque requête adressée à Cloudflare suit un chemin bien défini à travers notre réseau. Une requête donnée peut, par exemple, provenir d'un navigateur en train de charger une page web, d'une application mobile effectuant un appel d'API ou d'une quelconque forme de trafic automatisé issu d'un autre service. Ces requêtes arrivent d'abord sur notre couche HTTP et TLS. Elles pénètrent ensuite dans notre système de proxy principal (que nous nommons FL, pour « Frontline »), pour finir par atteindre Pingora, qui recherche les données dans le cache ou les récupère depuis le serveur d'origine, selon les besoins.
Nous avons déjà partagé plus de détails sur le fonctionnement de notre proxy principal dans un article précédent, que vous trouverez ici.
Lorsqu'une requête transite par notre proxy principal, nous exécutons les divers produits d'amélioration de la sécurité et des performances disponibles sur notre réseau. Le proxy applique la configuration et les paramètres propres à chaque client, de l'application des règles WAF à la protection contre les attaques DDoS, en passant par le routage du trafic vers la plateforme pour développeurs et le service R2. Ces opérations s'effectuent à l'aide d'un ensemble de modules spécifiques au domaine qui appliquent les règles de configuration et les politiques au trafic circulant au sein de notre proxy.
L'un de ces modules, celui du service Bot Management, s'est révélé à l'origine de la panne d'aujourd'hui.
Entre autres systèmes, le service de gestion des bots de Cloudflare intègre un modèle d'apprentissage automatique (Machine Learning) servant à générer un score de bot pour chaque requête qui circule à travers notre réseau. Nos clients s'appuient sur ce score de bot pour contrôler quels bots sont autorisés à accéder à leurs sites, ou non.
Le modèle ingère un fichier de configuration des « fonctionnalités » en guise de données entrantes. Dans ce contexte, la fonctionnalité désigne une caractéristique individuelle utilisée par le modèle d'apprentissage automatique afin de prédire si la requête a été automatisée ou non. Le fichier de configuration des fonctionnalités regroupe un ensemble de fonctionnalités individuelles.
Actualisé toutes les quelques minutes, ce fichier de fonctionnalité est publié sur l'ensemble de notre réseau afin de nous permettre de réagir aux variations des flux de trafic circulant sur Internet. Il nous permet également de réagir aux nouveaux types de bots et aux nouvelles attaques de bots. Comme les acteurs malveillants modifient rapidement les tactiques qu'ils utilisent, il est primordial que ce fichier soit déployé fréquemment et à grande vitesse.
Un changement (expliqué ci-dessous) de comportement de notre système de requêtes ClickHouse sous-jacent (qui génère ce fichier) a entraîné la production d'un grand nombre de lignes de « fonctionnalité » en double. Cet incident a modifié la taille du fichier de configuration des fonctionnalités (auparavant de taille fixe) et l'événement a entraîné l'apparition d'une erreur au sein du module dédié aux bots.
Le système de proxy principal qui gère le traitement du trafic de nos clients a par conséquent renvoyé des codes d'erreur HTTP 5xx pour l'ensemble du trafic dépendant de ce module. Le problème a également affecté Workers KV et Access, qui reposent sur le proxy principal.
Indépendamment de cet incident, nous étions (et sommes toujours) en train de procéder à la migration du trafic de nos clients vers une nouvelle version de notre service de proxy, connu en interne sous le nom de FL2. Les deux versions ont été affectées par le problème, mais les impacts observés se sont montrés différents.
Les clients déployés sur le nouveau moteur de proxy FL2 ont constaté l'apparition d'erreurs HTTP 5xx. Les clients qui utilisaient notre ancien moteur de proxy (FL) ne rencontraient pas d'erreurs, mais les scores de bot n'étaient pas générés correctement. L'ensemble du trafic se retrouvait ainsi doté d'un score de zéro. Les clients qui avaient déployé des règles de blocage des bots constataient un grand nombre de faux positifs. Ceux qui n'utilisaient pas nos scores de bot dans leurs règles n'observaient aucun impact.
Un autre symptôme apparent nous a induits en erreur et nous a fait croire que le problème pourrait être dû à une attaque : la page d'état des systèmes de Cloudflare est devenue inaccessible. Cette page d'état est intégralement hébergée hors de l'infrastructure de Cloudflare, sans aucune dépendance vis-à-vis de Cloudflare. Bien qu'il se soit avéré qu'il s'agissait uniquement d'une coïncidence, cet événement a amené certains membres de l'équipe chargée de diagnostiquer l'incident à penser qu'un acteur pouvait être en train de cibler à la fois nos systèmes et notre page d'état. Les utilisateurs qui tentaient d'accéder à la page d'état à ce moment ont été accueillis par le message d'erreur suivant :
Dans notre espace de discussion interne consacré aux incidents, nous craignions que l'incident ne soit la continuation d'Aisuru, une récente vague d'attaques DDoS à volume élevé :
Le changement de comportement de notre système de requêtes
J'ai mentionné plus haut qu'un changement survenu au niveau du comportement de notre système de requête sous-jacent a entraîné la production d'un fichier de fonctionnalité contenant un grand nombre de lignes en double. La base de données en question utilise le logiciel ClickHouse.
Afin de vous donner davantage de contexte, il peut être utile d'expliquer comment le système de requêtes distribuées de ClickHouse fonctionne. Un cluster ClickHouse se compose de nombreux fragments (shards). Pour interroger les données de l'ensemble de ces fragments, nous disposons de tables dites distribuées (à l'aide du moteur de table Distributed) contenues au sein d'une base de données nommée default. Le moteur Distributed interroge les tables sous-jacentes d'une base de données r0. Ce sont dans ces tables sous-jacentes que les données sont stockées sur chaque shard d'un cluster ClickHouse.
Les requêtes adressées aux tables distribuées s'exécutent par l'intermédiaire d'un compte système partagé. Dans le cadre de nos efforts visant à améliorer la sécurité et la fiabilité de nos requêtes distribuées, nous avons lancé une vague de travaux destinés à ce que ces requêtes soient plutôt exécutées sous le compte des utilisateurs initiaux.
Avant aujourd'hui, les utilisateurs de ClickHouse ne pouvaient voir les tables de la base de données default que lorsqu'ils interrogeaient les métadonnées des tables système de ClickHouse, comme system.tables ou system.columns.
Comme les utilisateurs disposent déjà d'un accès implicite aux tables sous-jacentes de r0, nous avons modifié nos paramètres à 11 h 05 afin de rendre cet accès explicite et que les utilisateurs puissent également consulter les métadonnées de ces tables. En nous assurant que l'ensemble des sous-requêtes distribuées puissent s'exécuter sous le compte de l'utilisateur initial, les limites de requête et les autorisations d'accès peuvent être évaluées de manière plus précise afin d'éviter qu'une sous-requête défaillante envoyée par un utilisateur n'affecte les autres.
Suite à la modification expliquée ci-dessus, tous les utilisateurs ont pu accéder aux métadonnées exactes concernant les tables auxquelles ils avaient accès. Malheureusement, selon certaines hypothèses déjà émises par le passé, la liste des colonnes renvoyées par une requête de ce type n'inclurait que la base de données « default » :
SELECT
name,
type
FROM system.columns
WHERE
table = 'http_requests_features'
order by name;
Vous remarquerez que la requête ne filtre pas selon le nom de la base de données. Alors que nous déployions progressivement les autorisations explicites aux utilisateurs d'un cluster ClickHouse donné, après cette modification effectuée à 11 h 05, la requête ci-dessus a commencé à renvoyer des « doublons » de colonnes, car celles-ci concernaient des tables sous-jacentes stockées au sein de la base de données r0.
Il s'agissait malheureusement du type de requête que la logique de génération de fichier de fonctionnalité du service Bot Management était justement en train d'exécuter afin de construire chaque « fonctionnalité » d'entrée pour le fichier mentionné au début de cette section.
La requête ci-dessus renverrait dès lors une table de colonnes du type suivant (exemple simplifié) :
Toutefois, grâce aux autorisations supplémentaires accordées à l'utilisateur, la réponse contenait également l'ensemble des métadonnées du schéma r0. Le nombre de lignes contenues dans la réponse s'en retrouvait effectivement plus que doublé. Cette inflation allait ensuite, à son tour, affecter le nombre de lignes (c.-à-d. les fonctionnalités) présentes dans le fichier final.
Pré-allocation de mémoire
Chaque module qui s'exécute sur notre service de proxy dispose d'un certain nombre de limites conçues pour éviter une consommation de mémoire illimitée, mais aussi pour pré-allouer de la mémoire afin d'optimiser les performances. Dans ce cas précis, le système du service Bot Management limite le nombre de fonctionnalités d'apprentissage automatique utilisables pendant l'exécution. Cette limite est actuellement fixée à 200, un chiffre bien supérieur au nombre de fonctionnalités que nous utilisons actuellement (près de 60). Encore une fois, cette limite existe, car nous pré-allouons de la mémoire à ces fonctionnalités pour des raisons de performances.
Lorsqu'un fichier dysfonctionnel contenant plus de 200 fonctionnalités a été propagé à nos serveurs, cette limite a été atteinte et a entraîné une panique au sein du système. Le code Rust de FL2 que nous vous présentons ci-dessous est chargé de la vérification. C'est lui qui se tient à l'origine de cette erreur non gérée :
L'application de ce code a engendré la panique suivante, qui a ensuite conduit à l'émission d'une erreur 5xx :
thread fl2_worker_thread panicked: called Result::unwrap() on an Err value
Autres effets survenus pendant l'incident
L'incident a également touché d'autres systèmes reposant sur notre proxy principal, notamment Workers KV et Cloudflare Access. Notre équipe a réussi à réduire l'impact sur ces systèmes à 13 h 04, suite à l'application d'un correctif à Workers KV afin de contourner le proxy principal. En conséquence, tous les systèmes en aval qui reposent sur Workers KV (comme le service Access lui-même) ont constaté une réduction du taux d'erreur.
Le tableau de bord Cloudflare a également été affecté du fait de l'utilisation en interne de Workers KV, mais aussi de notre processus de connexion, qui fait appel à Cloudflare Turnstile.
Le service Turnstile a été impacté par la défaillance. Nos clients sans session de tableau de bord active ne pouvaient ainsi plus se connecter. Comme le montre le graphique ci-dessous, le problème s'est manifesté par une disponibilité réduite pendant deux périodes précises : 11 h 30 – 13 h 10 et 14 h 40 – 15 h 30.
La première période, de 11 h 30 à 13 h 10, était due aux effets de la défaillance au niveau du service Workers KV, sur lequel reposent certaines fonctions de l'interface et du tableau de bord. La situation a été rétablie à 13 h 10, lorsque Workers KV a pu contourner le système de proxy principal.
La deuxième période de répercussions sur le tableau de bord s'est produite après la restauration des données de configuration des fonctionnalités, lorsque le backlog de tentatives de connexion non traitées a commencé à submerger le tableau de bord. L'association de nouvelles tentatives de connexion à l'ensemble des tentatives antérieures qui s'étaient soldées par un échec a entraîné une latence élevée et réduit la disponibilité du tableau de bord. La mise à l'échelle de la concurrence de l'interface a rétabli la disponibilité vers environ 15 h 30.
Mesures de correction et de suivi
Maintenant que nos systèmes sont de nouveau en ligne et fonctionnent normalement, nous avons commencé à travailler sur les solutions que nous allons devoir déployer afin de les prémunir contre des défaillances de ce type à l'avenir. Nous sommes plus spécifiquement en train :
de renforcer le processus d'ingestion des fichiers de configuration générés par Cloudflare afin qu'il se comporte de la même manière qu'avec les entrées générées par l'utilisateur ;
d'activer davantage de « kill switchs » (boutons d'arrêt d'urgence) mondiaux pour les fonctionnalités ;
d'éliminer la possibilité que des opérations de vidage de la mémoire ou d'autres rapports d'erreurs submergent les ressources système ;
d'examiner les modes de défaillance à la recherche de conditions d'erreur dans tous les modules de proxy principaux.
La panne survenue aujourd'hui est la pire que Cloudflare ait vécu depuis 2019. Nous avons déjà connu des défaillances qui ont entraîné l'indisponibilité de notre tableau de bord. D'autres ont conduit à l'indisponibilité de nouvelles fonctionnalités pendant un certain temps. Toutefois, ces six dernières années, nous n'avons pas connu d'autre épisode d'interruption de nos services ayant entraîné l'arrêt de la majorité du trafic principal sur notre réseau.
Un épisode d'interruption comme celui que nous avons subi aujourd'hui est inacceptable. Nous avons bâti l'architecture de nos systèmes afin qu'ils se montrent exceptionnellement résilients en cas de défaillance, mais aussi de garantir la circulation continue du trafic. Les pannes que nous avons connues par le passé nous ont toujours amenés à développer de nouveaux systèmes, plus solides et résilients.
Au nom de toute l'équipe Cloudflare, je tiens à vous présenter nos excuses pour les désagréments que nous avons causés à l'ensemble d'Internet aujourd'hui.
Heure (UTC) | État | Description |
|---|
11 h 05 | Normal. | Déploiement de la modification du système de contrôle des accès à la base de données. |
11 h 28 | Début de l'incident. | Le déploiement atteint les environnements des clients. Premières erreurs observées sur le trafic HTTP des clients. |
11 h 32 – 13 h 05 | L'équipe enquête sur les niveaux de trafic élevés et les erreurs du service Workers KV.
| Le symptôme initial semble se présenter sous la forme d'une dégradation du taux de réponse de Workers KV, qui entraîne des répercussions en aval sur d'autres services Cloudflare.
Diverses mesures d'atténuation, comme la manipulation du trafic et le contrôle du volume au niveau des comptes, sont mises en œuvre afin de rétablir le service Workers KV à ses niveaux d'exploitation habituels.
Le premier test automatisé a détecté le problème à 11 h 31 et les investigations manuelles ont commencé à 11 h 32. L'appel relatif à l'incident est envoyé à 11 h 35. |
13 h 05 | Déploiement des mesures de contournement de Workers KV et de Cloudflare Access. Réduction de l'impact de l'incident. | Au cours de notre enquête, nous avons déployé plusieurs mesures de contournement des systèmes internes sur Workers KV et Cloudflare Access afin de leur permettre de revenir à une version antérieure de notre proxy principal. Le problème était également présent dans les versions antérieures de notre proxy, mais ses effets étaient moindres, comme décrit ci-dessous. |
13 h 37 | Concentration des travaux sur la restauration du fichier de configuration du service Bot Management à la dernière version fonctionnelle connue. | Nous étions désormais convaincus que le fichier de configuration du service Bot Management était à l'origine de l'incident. Nos équipes ont travaillé sur divers moyens de réparer le service selon plusieurs procédures de travail, la plus rapide étant la restauration d'une version antérieure du fichier. |
14 h 24 | Arrêt de la production et de la propagation de nouveaux fichiers de configuration du service Bot Management. | Nous avons identifié à ce moment que le module Bot Management était à l'origine des erreurs 500, qui découlaient elles-mêmes d'un fichier de configuration dysfonctionnel. Nous avons ensuite mis fin au déploiement automatique des nouveaux fichiers de configuration du service Bot Management. |
14 h 24 | Test du nouveau fichier terminé. | Nous avons constaté une restauration réussie suite à l'utilisation de l'ancienne version du fichier de configuration. Nous nous sommes ensuite concentrés sur l'accélération du déploiement du correctif à l'échelle mondiale. |
14 h 30 | Impacts principaux réglés. Les services impactés en aval commencent à constater une réduction du nombre d'erreurs. | La plupart des services ont commencé à refonctionner correctement suite au déploiement d'un fichier fonctionnel de configuration du service Bot Management à l'échelle mondiale. |
17 h 06 | Rétablissement de l'ensemble des services. Fin de l'incident. | Tous les services en aval ont repris et toutes les opérations ont été intégralement rétablies. |