← Últimos Posts del Blog

🎵 Podcast en Spotify

El 18 de noviembre de 2025, la infraestructura global de telecomunicaciones experimentó una severa contracción en la conectividad, precipitada por una falla catastrófica dentro de Cloudflare. La interrupción, que se extendió más allá de cuatro horas a partir de las 11:20 UTC, efectivamente particionó un porcentaje significativo de la economía digital de su base de usuarios. Servicios críticos, desde grandes plataformas de comercio electrónico (como Amazon y Shopify) hasta portales bancarios e infraestructura esencial de IA, quedaron inaccesibles, devolviendo errores generalizados de la serie HTTP 500. Si bien los síntomas externos se asemejaban a un ataque de Denegación de Servicio Distribuido (DDoS) a hiperescala –una teoría inicialmente favorecida debido a las recientes campañas del botnet "Aisuru"– el evento precipitante fue estrictamente interno.

Para comprender completamente la magnitud de esta falla, es crucial reconocer la arquitectura actual de internet. La noción de una web descentralizada ha sido en gran medida reemplazada por una topología altamente concentrada que depende de unos pocos proveedores de "Edge Cloud". Cloudflare funciona como una membrana inteligente y programable, siendo el proxy el plano de control decisivo para el tráfico. El proxy es responsable de operaciones complejas como la Terminación Criptográfica, la Verificación de Identidad Zero Trust y la Mitigación de Amenazas, incluido el Gerenciamiento de Bots en tiempo real. Cuando esta membrana se rompe, la disponibilidad del servidor de origen es irrelevante, ya que la ruta de ingreso está comprometida.

La raíz de la falla técnica residió en una paradoja de permisos de base de datos que condujo a una Desajuste de Datos de Configuración. Cloudflare utiliza ClickHouse, un sistema de gestión de bases de datos orientado a columnas de código abierto, para generar inteligencia operativa y análisis en tiempo real. El sistema de Gerenciamiento de Bots dependía de una consulta SQL en vivo contra el clúster analítico para generar archivos de configuración. El disparador ocurrió a las 11:05 UTC, cuando el equipo de ingeniería inició una implementación de cambio de permiso de base de datos de rutina.

La falla fatal no fue un error de código, sino una consulta SQL implícitamente amplia. El sistema de Gerenciamiento de Bots ejecutaba un trabajo ETL programado cada cinco minutos para obtener metadatos de características utilizando la consulta SELECT name, type FROM system.columns WHERE table = 'http_requests_features'. Fundamentalmente, esta consulta carecía de una cláusula DISTINCT y de un filtro de base de datos (WHERE database = 'default'). Antes del cambio de permiso, la cuenta de servicio solo tenía visibilidad de la base de datos default. Después de la actualización de las 11:05 UTC, el servicio obtuvo acceso explícito o inadvertido al esquema r0 subyacente (shards físicos). El resultado fue que la consulta ahora veía dos tablas con el mismo esquema exacto (default.http_requests_features y r0.http_requests_features), duplicando efectivamente la lista de características de aproximadamente 60 a más de 120.

Este resultado de consulta inflado se serializó en un artefacto de configuración crítico, el "Feature File" (Archivo de Características), que actúa como el conjunto de instrucciones para el módulo de Gerenciamiento de Bots en el borde. La propagación de esta configuración corrupta fue el vector de la falla global. El impacto fue divergente según la infraestructura: la arquitectura legacy (basada en NGINX/Lua) probablemente manejó el archivo de configuración de manera más flexible, lo que resultó en "puntuaciones de bot aplicadas incorrectamente" (seguridad degradada). Sin embargo, los proxies modernos FL2 (probablemente basados en Rust y diseñados para seguridad estricta y rendimiento) aplicaron verificaciones rigurosas de límites de memoria. Cuando el archivo de características duplicado violó el límite de memoria hard-coded (el límite era 200, pero el recuento esperado era $\sim 60$), el proceso sufrió un panic—un mecanismo de "falla cerrada" (fail-closed) que resultó en una Denegación Total de Servicio para el tráfico legítimo.

La naturaleza intermitente de la falla ("flapping") complicó la respuesta, ya que el generador de Archivos de Características alternaba entre alcanzar nodos de base de datos actualizados (generando archivos venenosos) y nodos no actualizados (generando archivos válidos), oscureciendo la correlación entre el cambio de las 11:05 UTC y la interrupción global. El equipo de respuesta a incidentes enfrentó un sesgo cognitivo, enfocándose en la hipótesis de ataque externo (Aisuru), retrasando la investigación interna. La mitigación requirió una intervención manual de alto riesgo para inyectar un archivo de configuración "conocido como bueno".

La lección fundamental radica en tratar la configuración dinámica como infraestructura. El incidente validó el riesgo sistémico de la centralización. Las recomendaciones futuras incluyen la aplicación estricta del Principio de Mínimo Privilegio al imponer la visibilidad del esquema (r0 debe ser invisible), la adopción de consultas SQL defensivas y estrictamente limitadas (WHERE database = 'default'), y la obligación de una etapa de "Compilador" o "Validador" de Configuración con pruebas de aserción de límites (assert(feature_count <= 200)) antes de la distribución. El incidente también reabrió el debate sobre Disponibilidad versus Seguridad: el diseño "Fail-Closed" de FL2 priorizó la seguridad (prevenir la corrupción de memoria) pero causó indisponibilidad global, sugiriendo la necesidad de opciones de "Degradación Elegante" o "Fail-Open" para módulos no esenciales.