¿Qué es un ataque Slowloris? | Agotamiento de headers vía CRLF CRLF explicado

Aprende cómo Slowloris abre miles de conexiones HTTP parciales para agotar el pool de threads de un servidor. Cubre la mecánica de CRLF CRLF, su origen en 2009, la vulnerabilidad por servidor, y mitigación detallada con RequestReadTimeout y limit_conn.

Slowloris es una técnica de denegación de servicio low-and-slow que abre muchas conexiones HTTP a un servidor web y mantiene cada una abierta indefinidamente enviando headers de request parciales a intervalos justo por debajo del timeout del servidor, sin nunca transmitir la secuencia CRLF CRLF que marca el fin de un bloque de headers HTTP. Agota el pool de threads o conexiones del servidor usando ancho de banda mínimo, y una sola máquina sin refuerzo puede derribar un servidor Apache por defecto en menos de dos minutos.

Resumen rápido — Slowloris abre cientos de conexiones TCP a un servidor web y envía a cada una un request HTTP incompleto —headers sin CRLF CRLF de cierre— y luego gotea un byte extra de header cada 10-15 segundos para reiniciar el timeout de inactividad del servidor sin nunca terminar el request. Los servidores tipo thread-por-conexión como el MPM prefork de Apache se quedan sin worker threads en segundos a minutos porque cada conexión estancada ocupa un thread hasta que se dispara el timeout de conexión o lectura. La mitigación combina timeouts agresivos por fase (RequestReadTimeout, client_header_timeout), límites de conexión por IP, arquitecturas de servidor orientadas a eventos o asíncronas, y buffering de request del lado del edge que nunca reenvía un request incompleto al origen.

Última actualización: 2026-08-08

Origen: Robert “RSnake” Hansen, 2009

Slowloris fue liberado en junio de 2009 por el investigador de seguridad Robert “RSnake” Hansen como un script en Perl (slowloris.pl). Hansen había estado documentando técnicas de denegación de servicio a nivel HTTP durante años, pero Slowloris fue la primera herramienta ampliamente distribuida en demostrar que una sola máquina de consumidor, sin botnet y con ancho de banda insignificante, podía derribar un servidor web de producción explotando cómo los servidores HTTP/1.1 esperan la finalización de headers.

La técnica ganó atención pública un año después, cuando reportadamente se usó durante las protestas de las elecciones iraníes de 2009 para interrumpir la infraestructura web gubernamental, y de nuevo en disputas que involucraban sitios activistas y políticos, cementando su reputación como una herramienta de denegación de servicio de bajo costo y alto apalancamiento. OWASP posteriormente adoptó a Slowloris como un caso de referencia en su Denial of Service Cheat Sheet y mantiene una página comunitaria describiendo la técnica y las contramedidas conocidas.

La vulnerabilidad que explota Slowloris no es un bug en ningún servidor web específico; es una consecuencia directa de cómo HTTP/1.1 (RFC 9112, antes RFC 7230) define el framing de requests: un servidor no tiene forma de saber que un request está “terminado” hasta que recibe la secuencia de terminación de headers o la conexión hace timeout. Slowloris convierte esa ambigüedad en arma.

Cómo funciona Slowloris: el mecanismo CRLF CRLF

HTTP/1.1 delimita el fin del bloque de headers de un request con dos secuencias CRLF (\r\n) consecutivas, comúnmente escritas como CRLF CRLF o \r\n\r\n. Un request completo y bien formado se ve así en la red:

GET / HTTP/1.1\r\n
Host: example.com\r\n
User-Agent: Mozilla/5.0\r\n
\r\n ← línea vacía = CRLF CRLF = "los headers terminaron"

El servidor no tiene forma de comenzar a procesar el request hasta que ve esa línea vacía final. Slowloris abusa de esto enviando un request que nunca la alcanza:

Paso 1 — Abrir la conexión y enviar una línea de request + headers parciales, válidos:
GET / HTTP/1.1\r\n
Host: target.com\r\n
User-Agent: Mozilla/5.0\r\n
X-a: b\r\n
← todavía no se envía el CRLF CRLF de terminación
Paso 2 — Esperar justo por debajo del timeout de lectura/inactividad del servidor
(comúnmente 10-15 segundos)
Paso 3 — Enviar un header parcial más, inofensivo, para reiniciar el reloj de timeout:
X-a: c\r\n
Paso 4 — Repetir los pasos 2-3 indefinidamente, para cientos de conexiones en paralelo

Cada byte individual enviado es una línea de header HTTP sintácticamente válida. No hay paquete malformado, ninguna violación de protocolo, y ninguna firma que un filtro de paquetes sin estado pueda coincidir; por eso Slowloris pasa directamente a través de dispositivos que solo inspeccionan tráfico malformado.

Por qué esto agota al servidor. Muchos servidores web asignan un worker thread, proceso, o un slot en una tabla de conexiones de tamaño fijo en el momento en que se acepta una conexión TCP y comienza a llegar un request HTTP. Ese recurso permanece reservado hasta que el request se completa, falla, o hace timeout. Con suficientes requests medio-enviados en paralelo, cada worker disponible queda fijo esperando un CRLF CRLF que nunca llega. Las conexiones legítimas nuevas entonces se encolan detrás de un pool de conexiones lleno y eventualmente reciben un rechazo de conexión o un HTTP 408 Request Timeout.

Línea de tiempo de ataque contra una instalación Apache por defecto (MaxRequestWorkers ≈ 150-256):
t=0s El atacante abre 300 sockets, envía headers parciales en cada uno
t=1-10s Los sockets llenan el pool de workers de Apache (150-256 workers ocupados)
t=10s+ Los requests legítimos se encolan; las conexiones nuevas se rechazan o hacen timeout
t=10-15s El atacante envía 1 byte de keep-alive por socket estancado, reinicia los timers
t=∞ El ciclo se repite — el servidor permanece saturado hasta que el ataque se detiene

Slowloris vs. HTTP Flood vs. HTTP Slow Read

Slowloris se confunde frecuentemente con otros ataques de Capa 7 que también apuntan a recursos de aplicación en lugar de ancho de banda. La siguiente tabla aísla lo que lo distingue.

CaracterísticaSlowlorisHTTP FloodHTTP Slow Read
Fase HTTP explotadaHeaders del request (nunca completados)Ninguna — los requests son completos y válidosEntrega de la respuesta (el cliente lee lentamente)
Recurso agotadoWorker threads / slots de conexiónCPU, base de datos, lógica de aplicaciónBuffer de envío del servidor + slots de conexión
Volumen de requests1 request por conexión, incompletoMuy alto — miles de req/s completos1 request completo por conexión
Firma de ancho de bandaCercana a cero, planaAlta y a menudo con ráfagasCercana a cero, plana
Manipulación de ventana TCPNo se usaNo se usaCentral al mecanismo
Detectable por rate limitingNo — no hay tasa de request que limitarSí — funciona el rate limiting de requests/segundoNo — no hay tasa de request que limitar
Conexiones necesarias para tener éxitoCientos (servidores thread-por-conexión)Miles (varía según el costo de la app)Cientos
Defensa típica del origenTimeouts, limit_conn, servidor asíncronoRate limiting de WAF, CAPTCHA, reglasLímites de buffer de envío, timeouts de respuesta

Slowloris y HTTP Slow Read son hermanos dentro de la categoría más amplia de ataque low-and-slow: ambos mantienen conexiones abiertas con datos y ancho de banda mínimos, pero Slowloris estanca el lado del request del intercambio mientras Slow Read estanca el lado de la respuesta manipulando la ventana de recepción TCP. Consulta ¿Qué es un ataque HTTP Slow Read? para el mecanismo de ventana de recepción en detalle.

Vulnerabilidad por software de servidor

El impacto real de Slowloris depende casi por completo de si el servidor objetivo dedica un thread o proceso a cada conexión abierta, o si multiplexa muchas conexiones a través de un event loop.

Servidor / modelo de concurrenciaManejo de conexión por defectoExposición a SlowlorisNotas
Apache MPM Prefork1 proceso por conexiónAltaMaxRequestWorkers (por defecto 150-256) se agota rápido; históricamente el objetivo vulnerable de referencia
Apache MPM Worker1 thread por conexiónAltaLos threads son más baratos que los procesos pero siguen siendo finitos y bloqueables
Apache MPM EventManejo asíncrono del tiempo de inactividad de keep-aliveMediaReduce, pero no elimina, la exposición frente a Prefork/Worker
Microsoft IIS (thread pool clásico)1 thread por conexiónAltamaxConcurrentRequestsPerCPU se vuelve el factor limitante
nginxOrientado a eventos, E/S asíncronaBajaNo bloquea un thread por conexión, pero worker_connections (por defecto 1,024/worker) sigue siendo un techo finito
Node.js (módulo net/http)Event loop asíncronoBajaVulnerable principalmente a través de maxConnections y agotamiento de descriptores de archivo, no agotamiento de threads
LiteSpeedAsíncrono, orientado a eventosBajaLógica anti-Slowloris integrada desde versiones tempranas
CaddyAsíncrono (Go net/http)BajaEl servidor HTTP de Go aplica timeouts de lectura/headers más agresivamente por defecto

Matiz importante sobre nginx: la arquitectura orientada a eventos de nginx es más resistente al Slowloris clásico porque las conexiones inactivas no bloquean un worker thread. No es inmune. Cada conexión abierta —incluso una que no envía nada— sigue consumiendo un descriptor de archivo y un slot contado contra worker_connections. Un atacante con suficientes conexiones paralelas todavía puede agotar el techo total de conexiones de nginx y causar rechazos de nuevas conexiones, solo que a un conteo de conexión más alto del que se necesitaría contra Apache Prefork.

Señales de detección y telemetría

Slowloris produce casi ninguna señal volumétrica. La detección depende de métricas de estado de conexión y tasa de completitud en lugar de gráficas de tráfico.

Terminal window
# Cuenta las conexiones ESTABLISHED actuales — compara contra la línea base histórica
ss -o state established '( dport = :80 or dport = :443 )' | wc -l
# Lista las conexiones por IP de origen — Slowloris concentra muchas conexiones por IP atacante
ss -tn state established | awk '{print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
# Apache: verifica el estado de worker/thread por estados altos de "reading" o "keepalive"
apachectl status # o: mod_status vía /server-status
# nginx: verifica las conexiones activas vs. worker_connections configurado
nginx -T | grep worker_connections
IndicadorNormalBajo Slowloris
Conexiones ESTABLISHEDProporcional al tráfico realElevado y creciendo, desproporcionado a la tasa de request
Tasa de completitud de headers95%+ dentro de la ventana de timeoutPor debajo de 10-20%
Tiempo promedio al primer byte por conexiónMilisegundos a segundos bajosMinutos, o nunca se completa
Requests por segundoSigue la actividad del usuarioPlano o cercano a cero a pesar del alto conteo de conexiones
Utilización del pool de workers/threadsMuy por debajo de la capacidadCerca del 100% con bajo uso de CPU
Uso de CPU durante el eventoCorrelaciona con el tráficoBajo — el servidor está inactivo, solo esperando

La combinación de alto conteo de conexiones ESTABLISHED + baja CPU + bajo RPS es la firma más clara de Slowloris. Un ataque volumétrico muestra lo opuesto: alta CPU, alto RPS, alto ancho de banda.

Técnicas de mitigación

1. Timeouts agresivos y específicos por fase

Un único timeout de conexión global no es lo suficientemente preciso; no detecta una conexión que técnicamente está progresando (un byte cada 10 segundos). Los timeouts deben delimitarse específicamente a la fase de recepción de headers, idealmente combinados con una tasa mínima de datos.

# Apache — mod_reqtimeout
# Los headers deben completarse en 10-20s, a una tasa mínima de 500 bytes/seg
RequestReadTimeout header=10-20,MinRate=500
# El cuerpo debe completarse en 30s a la misma tasa mínima
RequestReadTimeout body=30,MinRate=500
# nginx
client_header_timeout 10s;
client_body_timeout 10s;
keepalive_timeout 15s;
send_timeout 10s;

El parámetro MinRate en mod_reqtimeout es el ajuste decisivo contra Slowloris específicamente: una conexión que envía 1 byte cada 10-15 segundos calcula muy por debajo de 1 byte/seg, lo que falla una verificación MinRate=500 casi de inmediato, mucho antes de que se disparara cualquier timeout fijo.

2. Límites de conexión concurrente por IP

limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn perip 20;
limit_conn_status 429;

Esto limita cuántos sockets puede mantener abiertos un solo origen sin importar qué datos —si acaso— se envíen en ellos, lo que bloquea la mecánica central de Slowloris (muchas conexiones estancadas en paralelo desde pocas IP) incluso antes de que se evalúe cualquier header HTTP.

3. Preferir arquitecturas de servidor orientadas a eventos o asíncronas

Donde sea arquitectónicamente posible, corre nginx, LiteSpeed, o el MPM Event de Apache en lugar de Prefork/Worker frente a la aplicación. Las arquitecturas asíncronas no eliminan el problema del techo finito de conexiones, pero eliminan el modo de falla por agotamiento de threads que hace tan efectivo al Slowloris clásico contra Prefork.

4. Buffering de request en proxy reverso / edge

Coloca un proxy reverso o red edge frente al origen que ensamble y valide por completo cada request HTTP —headers y cuerpo— antes de abrir cualquier conexión al servidor de origen. Los requests incompletos se mantienen y eventualmente se descartan en la capa de proxy, que está construida para absorber grandes cantidades de conexiones lentas concurrentes; el origen solo ve requests completos y válidos. Esta es la defensa estructuralmente más robusta porque elimina por completo el techo de threads/conexiones del origen de la superficie de ataque.

5. Fingerprinting JA3/JA4 y reglas conductuales en el WAF

Las herramientas de Slowloris (el script original en Perl y sus muchos derivados) producen una huella digital de handshake TLS que difiere de los navegadores principales, y omiten headers que un navegador real siempre envía (Accept-Language, Accept-Encoding) y nunca solicitan recursos secundarios de página. Un WAF que hace fingerprinting de handshakes TLS y puntúa el comportamiento de request puede marcar y descartar estas sesiones antes de que se evalúe siquiera la capa HTTP.

Errores comunes

ErrorPor qué fallaMejor enfoque
Establecer solo una directiva Timeout globalNo detecta una conexión que técnicamente envía datos por debajo de cualquier tasa significativaUsa timeouts específicos por fase con una verificación de MinRate/throughput mínimo
Asumir que nginx es inmune porque es “asíncrono”worker_connections sigue siendo un techo rígido; los descriptores de archivo todavía se agotanConfigura limit_conn y timeouts de headers incluso en nginx
Depender solo de un firewall de redSlowloris usa conexiones TCP completamente válidas en 80/443; no hay ningún paquete que bloquearUsa controles a nivel de aplicación: WAF, timeouts de proxy reverso, detección conductual
Bloquear por IP de origen después del hechoSlowloris puede correr desde una sola máquina, y las variantes distribuidas rotan IPCombina límites de conexión por IP con buffering de request del lado del edge
Monitorear solo dashboards de ancho de banda/RPSSlowloris no genera anomalía volumétricaAgrega el conteo de conexiones ESTABLISHED y la tasa de completitud de headers al alertamiento

Cómo implementarlo con Azion

Azion termina las conexiones HTTP en el edge, antes del origen, lo que cambia dónde aterrizan realmente las conexiones estancadas de un ataque Slowloris.

  • Firewall puede aplicar reglas de tasa de conexión y concurrencia por IP antes de que el tráfico llegue a la capa de aplicación
  • WAF puede ayudar a detectar y bloquear patrones de request de headers lentos y firmas de herramientas de ataque conocidas, dependiendo de los conjuntos de reglas configurados
  • DDoS Protection brinda detección siempre activa orientada a patrones de ataque de Capa 7, incluyendo agotamiento de conexión low-and-slow
  • WAAP combina WAF, protección DDoS, y controles relacionados con bots para equipos que quieren estos en capas

Como los nodos edge ensamblan y validan los requests antes de abrir cualquier conexión al origen, un request Slowloris incompleto generalmente nunca llega a la infraestructura de origen en absoluto; se mantiene y expira en el edge, que está construido para absorber muchas más conexiones lentas concurrentes que un servidor web de origen típico.

Recursos relacionados

Preguntas frecuentes

¿Qué es un ataque Slowloris? Slowloris es una técnica de denegación de servicio que abre muchas conexiones HTTP a un servidor y las mantiene vivas enviando headers de request incompletos a intervalos justo por debajo del timeout del servidor. Nunca envía la secuencia CRLF CRLF que termina un request, así que el servidor mantiene el thread o slot de cada conexión abierto indefinidamente esperando un request que nunca se completa.

¿Quién creó Slowloris y cuándo? El investigador de seguridad Robert “RSnake” Hansen liberó Slowloris como un script en Perl en junio de 2009. Se hizo ampliamente conocido después de reportes de su uso interrumpiendo infraestructura web gubernamental durante las protestas de las elecciones iraníes de 2009, y sigue siendo un caso de referencia en la documentación de Denial of Service de OWASP.

¿Qué significa CRLF CRLF y por qué importa? CRLF CRLF (\r\n\r\n) es la secuencia de dos saltos de línea consecutivos que HTTP/1.1 usa para marcar el fin del bloque de headers de un request. Un servidor no puede comenzar a procesar un request hasta que ve esta secuencia. Slowloris deliberadamente la retiene, manteniendo el request permanentemente “en progreso” desde el punto de vista del servidor.

¿Slowloris puede ejecutarse desde una sola computadora? Sí. Slowloris no requiere una botnet. Una sola máquina con una conexión de internet normal puede abrir suficientes conexiones paralelas —a menudo solo unos pocos cientos— para agotar el pool de workers de un servidor Apache por defecto, porque el costo de recursos del ataque es un puñado de sockets abiertos, no alto ancho de banda o CPU.

¿HTTPS/TLS detiene Slowloris? No. El handshake TLS se completa normalmente antes de que comience la capa HTTP, y Slowloris opera enteramente dentro del intercambio HTTP ya cifrado. La detección y mitigación efectivas tienen que ocurrir después de la terminación TLS, en el load balancer, proxy reverso, o WAF, donde el contenido del request es visible.

¿Qué servidores web son más vulnerables a Slowloris? Los servidores que asignan un thread o proceso por conexión están más expuestos: los MPM Prefork y Worker de Apache, configuraciones más antiguas de thread pool de IIS, y algunos servidores de aplicación tradicionales de Python/Ruby. Los servidores asíncronos orientados a eventos como nginx, LiteSpeed, Node.js, y Caddy son más resistentes porque no dedican un thread por conexión inactiva, aunque siguen limitados por sus techos de conexión configurados.

¿nginx es completamente inmune a Slowloris? No. La arquitectura asíncrona de nginx evita el modo de falla por agotamiento de threads, pero cada conexión abierta —incluso una que no envía nada— sigue consumiendo un descriptor de archivo contado contra worker_connections (por defecto 1,024 por worker). Un atacante con suficientes conexiones concurrentes todavía puede agotar ese techo. limit_conn y timeouts de headers deberían configurarse en nginx también.

¿En qué se diferencia Slowloris de un SYN flood? Un SYN flood explota el handshake TCP y deja las conexiones en un estado semi-abierto que nunca llega a la capa de aplicación. Slowloris establece conexiones TCP completamente válidas y opera a nivel HTTP, enviando datos de aplicación reales, solo que incompletos. Consulta ¿Qué es un ataque SYN Flood? para el mecanismo a nivel de transporte.

¿En qué se diferencia Slowloris de un ataque HTTP Slow Read? Slowloris estanca el lado del request de un intercambio HTTP al nunca completar los headers que envía un cliente. HTTP Slow Read en cambio envía un request completo y válido y luego estanca la respuesta manipulando la ventana de recepción TCP de modo que el servidor solo pueda enviar datos unos pocos bytes a la vez. Ambos agotan recursos del servidor con ancho de banda mínimo, pero atacan mitades opuestas del ciclo request/response. Consulta ¿Qué es un ataque HTTP Slow Read?.

¿Un firewall de red estándar puede bloquear Slowloris? Generalmente no. Un firewall sin estado o puramente a nivel de red ve conexiones TCP válidas y bien formadas en el puerto 80 o 443 sin ningún paquete malformado que coincidir. Bloquear Slowloris requiere visibilidad a nivel de aplicación: un WAF, un proxy reverso con timeouts específicos por fase, o detección conductual/basada en fingerprint.

¿Cuántas conexiones necesita típicamente un ataque Slowloris? Necesita aproximadamente tantas conexiones como el tamaño del pool de workers o conexiones del objetivo. Apache con configuración por defecto acepta alrededor de 150-256 workers simultáneos, así que unos pocos cientos de conexiones lentas a menudo son suficientes; bien dentro de lo que una sola máquina de consumidor puede mantener.

¿Cuál es la mitigación del lado del servidor más efectiva? No hay una bala de plata única, pero combinar un timeout de tasa mínima de datos (RequestReadTimeout ... MinRate=500 en Apache, o equivalente) con un límite de conexión por IP (limit_conn en nginx) cierra simultáneamente tanto la mecánica de “gotear datos para siempre” como la de “abrir cientos de conexiones desde un origen”.

Fuentes

  • Hansen, Robert (“RSnake”). “Slowloris HTTP DoS.” 2009.
  • OWASP. “Slowloris.” Páginas comunitarias de OWASP.
  • OWASP. “Denial of Service Cheat Sheet.”
  • IETF. “HTTP/1.1 Message Syntax and Routing.” RFC 9112 (obsoleta a RFC 7230).
  • Apache Software Foundation. “mod_reqtimeout.” Documentación del servidor HTTP Apache.
  • nginx. “Module ngx_http_limit_conn_module.” Documentación oficial.
  • NIST. “Guide to Intrusion Detection and Prevention Systems.” SP 800-94.
mantente actualizado

Suscríbete a nuestro boletín informativo

Recibe las últimas actualizaciones de productos, destacados de eventos y conocimientos de la industria tecnológica directamente en tu bandeja de entrada.