A maioria dos ataques DDoS é óbvia: geram picos imensos de tráfego que saturam links e derrubam servidores em segundos. Ataques low and slow são o oposto. Eles usam dezenas — não milhares — de conexões, cada uma transmitindo dados em ritmo de lesma, prendendo recursos do servidor indefinidamente sem nunca completar a requisição. Ferramentas de detecção volumétrica simplesmente não os veem.
Ataques low and slow são uma categoria de ataques DDoS de camada 7 que esgotam os recursos de um servidor web por meio de um pequeno número de conexões mantidas abertas por longos períodos, transmitindo dados em ritmo mínimo. Em vez de inundar com volume, o atacante prende threads ou descritores de arquivo do servidor esperando por requisições que nunca se completam.
Por que ataques low and slow passam despercebidos
Detecções tradicionais de DDoS monitoram volume: pacotes por segundo, bytes por segundo, requisições por segundo. Ataques low and slow geram pouquíssimo tráfego. A tabela abaixo ilustra a diferença de perfil em relação a um HTTP Flood convencional:
| Característica | HTTP Flood | Low and Slow (Slowloris) |
|---|---|---|
| Volume de requisições | 500.000+ req/s | 1–10 req/s |
| Largura de banda gerada | 50+ Gbps | Menos de 1 Mbps |
| Conexões simultâneas | Milhares (curta duração) | 100–1.000 (longa duração) |
| Dados por conexão/tempo | Alto volume contínuo | 1 byte a cada 10–15 segundos |
| Visibilidade volumétrica | Alta — fácil de detectar | Praticamente nula |
| RPS (Requests Per Second) | Pico abrupto | Estável e baixo |
| Conexões ESTABLISHED | Flutuam rapidamente | Acumulam-se continuamente |
O servidor mantém cada conexão ativa — consumindo uma thread ou um file descriptor — enquanto aguarda o fim da requisição. Com um número suficiente de conexões presas, o pool de threads esgota e conexões legítimas recebem HTTP 408 Request Timeout ou são recusadas com erro de conexão.
Slowloris — exploração da mecânica CRLF do HTTP/1.1
Desenvolvido por Robert “RSnake” Hansen em 2009, o Slowloris explora uma característica fundamental do protocolo HTTP/1.1 (RFC 7230): o servidor deve aguardar a sequência de encerramento de headers CRLF CRLF (\r\n\r\n) antes de processar a requisição. Enquanto essa sequência não chega, o servidor mantém a conexão aberta e os recursos alocados.
O mecanismo funciona em cinco etapas:
- O atacante abre centenas de conexões TCP ao servidor alvo.
- Em cada conexão, envia o início de uma requisição HTTP/1.1 sintaticamente válida — linha de request e alguns headers — mas omite deliberadamente a sequência CRLF CRLF que encerraria o bloco de headers.
- A cada 10–15 segundos, envia um byte adicional (um novo header parcial, como
X-Keep: a) para resetar o idle timeout do servidor, mantendo a conexão viva sem completar a requisição. - O servidor, seguindo a especificação HTTP/1.1, aguarda indefinidamente pelo CRLF CRLF que nunca chega. Cada conexão prende uma thread no Apache (modelo MPM Prefork ou Worker) ou um file descriptor em servidores assíncronos.
- Quando todas as threads ou conexões disponíveis estão presas, novas requisições legítimas são recusadas ou recebem HTTP 408 Request Timeout.
O envio periódico de bytes adicionais é o elemento crítico: ele impede que o servidor encerre a conexão por inatividade, estendendo o ataque indefinidamente com custo mínimo de banda para o atacante.
R.U.D.Y. — fragmentação do body POST e aprisionamento de sockets
R.U.D.Y. (R-U-Dead-Yet?) opera em uma fase diferente do protocolo HTTP: o body da requisição POST, após os headers já terem sido enviados corretamente.
O mecanismo explora o campo Content-Length:
- O atacante envia uma requisição POST completa e sintaticamente válida, com todos os headers, incluindo
Content-Length: 1000000(ou outro valor alto). - O servidor aloca um socket e reserva recursos para receber o body completo de 1 MB declarado.
- O atacante transmite o body em fragmentos de 1 byte a cada 10 segundos, que é tráfego válido do ponto de vista do protocolo TCP — não há timeout de inatividade sendo violado.
- O socket permanece preso na alocação de recebimento. Com dezenas de conexões simultâneas assim, os sockets disponíveis se esgotam.
Alvos preferenciais do R.U.D.Y. são endpoints que processam grandes volumes de dados POST: formulários de autenticação, APIs de upload de arquivos, endpoints de processamento de dados. Esses alvos tipicamente têm Content-Length ilimitado ou com limites altos, maximizando o tempo de aprisionamento de cada socket.
Slow Read Attack — manipulação da Janela de Recepção TCP
O Slow Read Attack opera na camada de transporte (TCP), não na camada de aplicação HTTP. O mecanismo explora a Janela de Recepção TCP (TCP Receive Window) — o parâmetro que sinaliza ao remetente quantos bytes o receptor está pronto para aceitar.
O ataque funciona da seguinte forma:
- O atacante estabelece uma conexão TCP normal e envia uma requisição HTTP legítima.
- Antes de o servidor começar a enviar a resposta, o atacante configura sua Janela de Recepção TCP para um valor muito baixo — próximo de zero (win=1 ou win=64), em vez do padrão de 65 KB–128 KB.
- O servidor, respeitando o controle de fluxo TCP, só pode enviar dados na quantidade que a janela do receptor autoriza. Com uma janela de 1 byte, envia um byte, espera o ACK, envia outro byte, e assim por diante.
- O send buffer do servidor (tipicamente 65 KB–128 KB) fica preenchido, pois os dados não conseguem ser despachados na velocidade normal.
- Quando o send buffer satura, o servidor emite TCP Window Probes — pacotes de sondagem periódicos para verificar se a janela do cliente foi expandida. Cada probe consome CPU e mantém o estado de conexão ativo no kernel.
- Dezenas de conexões com janela reduzida simultaneamente consomem tanto o pool de send buffers quanto CPU de processamento de probes, esgotando recursos do servidor sem gerar tráfego visível.
O Slow Read Attack é particularmente eficaz contra servidores que não têm limite de tempo para o envio completo de respostas — apenas para o recebimento de requisições.
Apache Killer — Range Header e fragmentação de resposta
O Apache Killer envia requisições com um header Range contendo centenas de intervalos de bytes sobrepostos e redundantes. O servidor precisa preparar e serializar cada intervalo individualmente como uma parte de resposta multipart, consumindo CPU e memória por requisição mesmo com um único cliente.
GET / HTTP/1.1Host: alvo.comRange: bytes=0-1,0-2,0-3,0-5,0-10,...,0-65536Esse ataque foi corrigido no Apache 2.2.21 (2011) com a limitação do número de ranges aceitos por requisição, mas variações ainda afetam servidores desatualizados.
Modelos de concorrência e superfície de ataque
A eficácia de ataques low and slow varia conforme o modelo de concorrência do servidor:
| Servidor | Modelo de concorrência | Limite crítico | Vulnerabilidade ao Slowloris | Vulnerabilidade ao Slow Read |
|---|---|---|---|---|
| Apache MPM Prefork | Thread por conexão | MaxRequestWorkers (padrão: 150–256) | Alta — 1 thread por conexão presa | Média |
| Apache MPM Worker | Thread por conexão | MaxRequestWorkers | Alta | Média |
| IIS (Windows) | Thread pool fixo | maxConcurrentRequestsPerCPU | Alta | Média-Alta |
| Nginx | Assíncrono (event loop) | worker_connections × worker_processes | Baixa — não bloqueia thread, mas esgota file descriptors | Média — send buffers se esgotam |
| Node.js | Event loop assíncrono | maxConnections (net.Server) | Baixa | Média |
| LiteSpeed | Assíncrono | Configurável | Baixa | Baixa |
Nota importante sobre o Nginx: embora a arquitetura assíncrona do Nginx seja significativamente mais resistente ao Slowloris clássico — pois não bloqueia uma thread por conexão — o servidor ainda é limitado pela diretiva worker_connections. Cada conexão aberta, mesmo inativa, consome um file descriptor. Um atacante com volume suficiente de conexões pode esgotar o worker_connections total do Nginx (padrão: 1.024 por worker), causando recusa de novas conexões sem qualquer bloqueio de thread.
HTTP/2, multiplexação de streams e novos vetores
O HTTP/2 alterou a dinâmica dos ataques low and slow de forma ambivalente:
Resistência ao Slowloris clássico: como o HTTP/2 usa multiplexação — múltiplos streams lógicos sobre uma única conexão TCP — o Slowloris que abre centenas de conexões TCP é menos eficaz. O servidor precisa de menos conexões para servir o mesmo número de requisições.
Novos vetores de slow attack: a multiplexação cria superfícies de ataque específicas do HTTP/2:
- Streams lentos por manipulação de WINDOW_UPDATE: o HTTP/2 tem controle de fluxo próprio, independente do TCP. Um atacante pode abrir múltiplos streams em uma única conexão TCP e enviar frames
WINDOW_UPDATEcom incrementos mínimos — forçando o servidor a enviar dados de cada stream em fragmentos ínfimos. O efeito é similar ao Slow Read Attack, mas operando na camada de aplicação HTTP/2. - Manipulação de frames SETTINGS: o atacante pode enviar frames
SETTINGScom parâmetros agressivos (comoINITIAL_WINDOW_SIZEpróximo de zero) para todos os streams, reduzindo o throughput de toda a conexão enquanto mantém o canal aberto. - Stream multiplexing exhaustion: abrir dezenas de streams simultâneos em uma única conexão e alimentá-los lentamente consome buffers de estado de stream no servidor sem acionar alertas de conexões TCP.
O Nginx com HTTP/2 ativado ainda é limitado por worker_connections — cada conexão TCP com múltiplos streams HTTP/2 ainda ocupa um file descriptor. A proteção requer configuração de limites de streams por conexão e timeouts de stream além dos timeouts de conexão TCP.
Técnicas de mitigação
Timeouts agressivos por fase de protocolo
A configuração de timeouts por fase — diferenciando o tempo para receber headers, body e enviar resposta — é a defesa mais direta e eficiente:
# Nginx — mitigação de Slowloris e R.U.D.Y.client_header_timeout 10s; # Tempo máximo para receber headers completos (CRLF CRLF)client_body_timeout 10s; # Tempo máximo entre bytes consecutivos do bodykeepalive_timeout 15s; # Tempo máximo de conexão keepalive ociosasend_timeout 10s; # Tempo máximo entre bytes enviados ao cliente# Apache — mod_reqtimeout para Slowloris e R.U.D.Y.# Headers: mínimo de 500 bytes/s, prazo de 10 a 20 segundosRequestReadTimeout header=10-20,minrate=500# Body: mínimo de 500 bytes/s, prazo de 20 segundosRequestReadTimeout body=20,minrate=500A diretiva minrate é especialmente relevante: em vez de um timeout fixo, ela verifica se a taxa de transferência está acima de um limiar mínimo. Uma conexão que envia 1 byte a cada 10 segundos (1 byte/10s = 0,1 bytes/s) viola o minrate=500 imediatamente, sendo encerrada mesmo antes de atingir o prazo máximo.
Limitação de conexões por IP com limit_conn
# Nginx — limitação de conexões simultâneas por IPlimit_conn_zone $binary_remote_addr zone=conn_limit:10m;limit_conn conn_limit 20; # Máximo de conexões por IPlimit_conn_status 429; # Retorna HTTP 429 ao exceder o limiteO limit_conn do Nginx atua no nível de conexões TCP ativas, não de requisições. Isso o torna eficaz contra Slowloris (que abre muitas conexões) mesmo antes de qualquer dado HTTP ser recebido.
Request Buffering no reverse proxy edge
O Request Buffering é um mecanismo defensivo fundamental que opera no reverse proxy edge: o nó de borda monta e valida a requisição HTTP completa — incluindo todos os headers e o body declarado — antes de abrir qualquer conexão upstream com o servidor de origem.
O impacto é decisivo:
- O servidor de origem nunca vê conexões incompletas. Apenas requisições completamente recebidas e validadas pelo edge chegam ao backend.
- Ataques Slowloris e R.U.D.Y. ficam presos no edge, que aplica seus próprios timeouts agressivos.
- O edge suporta ordens de magnitude mais conexões simultâneas do que um servidor Apache típico, diluindo o impacto do ataque.
- O Slow Read Attack também é neutralizado: o edge envia a resposta ao cliente de forma assíncrona, sem manter o estado de send buffer do servidor de origem preso enquanto aguarda o cliente receber os dados lentamente.
Fingerprinting JA3/JA4 e análise comportamental no WAF
Ferramentas de ataque como Slowloris, R.U.D.Y. e suas variantes apresentam padrões identificáveis que diferem de navegadores legítimos:
TLS Fingerprinting (JA3/JA4): o handshake TLS de cada cliente deixa uma “impressão digital” baseada na sequência de cipher suites, extensões TLS e parâmetros de versão. O hash JA3 (e seu sucessor JA4) de ferramentas de ataque como o Slowloris em Python ou Perl difere consistentemente do hash de navegadores como Chrome, Firefox ou Safari. Um WAF com suporte a JA3/JA4 pode bloquear requisições com fingerprints conhecidos de ferramentas de ataque antes mesmo de analisar qualquer dado HTTP.
Análise comportamental complementar:
- Ausência de headers típicos de navegador (
Accept-Language,Accept-Encoding,Accept) - Nenhuma requisição a recursos secundários (CSS, JavaScript, imagens) após a requisição inicial
- Timing mecânico e regular entre bytes — padrão não humano
- Sequências de requisições incompatíveis com navegação real — padrões detectáveis por técnicas de detecção de bots
Configurações de limite de streams HTTP/2
# Nginx — limites para mitigar ataques slow em HTTP/2http2_max_concurrent_streams 64; # Máximo de streams simultâneos por conexãohttp2_idle_timeout 30s; # Timeout para conexões HTTP/2 ociosashttp2_recv_timeout 30s; # Timeout para receber frames HTTP/2Sinais de detecção
| Indicador | O que observar | Ataque provável |
|---|---|---|
| Alto número de conexões ESTABLISHED com baixo RPS | ss -s ou netstat -an com contagem anormalmente alta vs. baixo throughput HTTP | Slowloris |
| Conexões de longa duração sem completar | Logs com conexões abertas por mais de 30s sem requisição finalizada | Slowloris / R.U.D.Y. |
| Poucos IPs com muitas conexões cada | Um pequeno número de IPs com dezenas de conexões abertas simultaneamente | Slowloris |
| CPU normal, threads ou file descriptors esgotados | Servidor sem carga de CPU mas recusando conexões | Todos |
| Erros 503 ou 408 sem pico de RPS | Service Unavailable ou Request Timeout sem aumento visível de tráfego | Todos |
| Send buffer do servidor constantemente cheio | Métricas de rede mostrando backpressure TCP sem tráfego volumétrico | Slow Read Attack |
| TCP Window Probes frequentes nos logs de rede | Capturas de pacotes (tcpdump/Wireshark) mostrando probes periódicos | Slow Read Attack |
Erros comuns e soluções
Erro: Usar apenas detecção volumétrica para monitorar DDoS. Solução: Ataques low and slow são invisíveis para alertas de volume. Monitore também: número de conexões por IP, duração média de conexões, taxa de completude de requisições e utilização de threads/file descriptors.
Erro: Acreditar que Nginx é completamente imune a Slowloris.
Solução: A arquitetura event-driven do Nginx é mais resistente, mas não imune. O limite worker_connections ainda pode ser esgotado com volume suficiente de conexões lentas. Configure limit_conn e timeouts mesmo com Nginx.
Erro: Configurar apenas um timeout global de conexão sem diferenciar fases.
Solução: Separe os timeouts por fase do protocolo (client_header_timeout, client_body_timeout, send_timeout). Um único timeout global não captura conexões que enviam dados continuamente em ritmo mínimo — o minrate do Apache é o mecanismo mais preciso para esse caso.
Erro: Ignorar HTTP/2 como vetor de slow attack por ser mais resistente ao Slowloris clássico.
Solução: O HTTP/2 não elimina os vetores low and slow — apenas os transforma. Configure limites de streams (http2_max_concurrent_streams) e timeouts específicos de HTTP/2 além dos timeouts TCP.
Erro: Não monitorar o pool de threads nem o uso de file descriptors do servidor. Solução: O esgotamento de threads ou file descriptors é o indicador mais direto de um ataque low and slow em progresso. Configure alertas quando a utilização atingir 80%.
Perguntas frequentes
Por que o Slowloris é chamado de “ataque furtivo”? Porque gera volume de tráfego irrisório — menos de 1 Mbps — que não aciona alertas volumétricos. É invisível para IDS/IPS baseados em volume, para provedores de trânsito que monitoram largura de banda e para dashboards de requisições por segundo. A única métrica que o revela é o número de conexões ESTABLISHED acumuladas.
Um único computador pode executar Slowloris? Sim. Ferramentas como o Slowloris original em Perl e versões Python modernas executam o ataque de uma única máquina sem botnet. Isso o torna acessível a atacantes com recursos limitados e dificulta o bloqueio por volume ou diversidade de IPs.
O uso de HTTPS/TLS impede ataques Slowloris ou R.U.D.Y.? Não. O handshake TLS é negociado antes da camada HTTP e ocorre normalmente em ambos os ataques. Após o handshake TLS ser concluído, o Slowloris e o R.U.D.Y. operam na camada HTTP sobre o canal TLS estabelecido — a criptografia não tem visibilidade sobre o ritmo de transmissão do payload HTTP. A mitigação eficaz deve ocorrer após a terminação TLS, em camada 7, com análise de headers, timing e comportamento da requisição.
Quanto tempo leva para Slowloris derrubar um servidor Apache não protegido? Em testes documentados, um servidor Apache com configuração padrão (256 threads) pode ser derrubado por Slowloris em 30 segundos a 2 minutos, dependendo do número de conexões que o atacante abre. Com 256 conexões lentas simultâneas, o pool de threads esgota completamente antes que qualquer timeout padrão atue.
Como identificar se um erro 503 é causado por HTTP Flood ou por um ataque Low and Slow?
A diferença está nas métricas de RPS e conexões ESTABLISHED. Um HTTP Flood provoca um erro 503 acompanhado de um pico abrupto e elevado de requisições por segundo (RPS), com alto consumo de CPU e rede. Um ataque Low and Slow gera erros 503 com RPS estável e baixo — praticamente indistinguível do tráfego normal — mas com um número crescente e anômalo de conexões ESTABLISHED de longa duração, CPU próxima do normal e threads ou file descriptors esgotados. O comando ss -s ou netstat -an | grep ESTABLISHED | wc -l cruzado com o RPS atual é o diagnóstico mais rápido.
R.U.D.Y. é mais perigoso que Slowloris?
Depende do alvo. R.U.D.Y. é mais eficaz contra aplicações que processam grandes volumes de dados POST — uploads, APIs, formulários com limite alto de Content-Length. Slowloris é mais genérico e afeta qualquer servidor HTTP com limite de threads ou conexões. Em servidores com mod_reqtimeout corretamente configurado, o R.U.D.Y. é mitigado pelo minrate, enquanto o Slowloris requer configuração adicional de client_header_timeout.
Como distinguir um usuário com conexão lenta de um ataque low and slow? Usuários com conexão lenta completam a requisição eventualmente, solicitam múltiplos recursos sequencialmente (CSS, JS, imagens após o HTML) e têm timing variável e irregular entre bytes — comportamento humano. Ataques low and slow mantêm conexões abertas indefinidamente sem completar, com timing mecânico e regular entre bytes, nenhuma requisição a recursos secundários e padrões JA3/JA4 de fingerprint consistentes com ferramentas de automação em vez de navegadores reais.
O que é o Request Buffering e por que é eficaz contra low and slow? Request Buffering é o mecanismo pelo qual um reverse proxy edge acumula e valida toda a requisição HTTP — headers e body completos — antes de abrir a conexão com o servidor de origem (upstream). O resultado é que o servidor de origem nunca recebe requisições incompletas: o edge absorve toda a lentidão do cliente, aplica seus timeouts e só encaminha ao backend o que estiver completamente recebido e válido. Isso torna o servidor de origem imune a Slowloris e R.U.D.Y., independentemente de sua configuração interna.
Qual é o impacto do HTTP/2 em ataques low and slow?
O HTTP/2 usa multiplexação de streams, o que reduz a eficácia do Slowloris clássico que abre muitas conexões TCP. Porém, cria novos vetores: um atacante pode abrir múltiplos streams HTTP/2 em uma única conexão TCP e manipular frames WINDOW_UPDATE e SETTINGS para forçar o servidor a transmitir dados em fragmentos mínimos — replicando o efeito do Slow Read Attack na camada de aplicação. Limites de http2_max_concurrent_streams e timeouts de stream são necessários para mitigar esses vetores.
Como implementar na Azion
A Azion neutraliza ataques low and slow antes de alcançar a origem:
- Request Buffering no edge: Os data centers da Azion montam e validam cada requisição HTTP completa antes de abrir a conexão com o servidor de origem. Conexões que não completam headers ou body dentro dos limites configurados são descartadas no edge, sem nunca impactar o backend.
- Timeouts agressivos por fase: O edge aplica timeouts distintos para recebimento de headers, body e envio de resposta, encerrando conexões lentas antes de esgotar recursos downstream.
- Limitação de conexões por IP: O edge aplica limites de conexões simultâneas por IP, impedindo que um único cliente prenda dezenas de recursos no servidor de origem.
- Bot Manager com JA3/JA4 Fingerprinting: Identifica ferramentas de ataque como Slowloris e R.U.D.Y. por meio de TLS fingerprinting (hashes JA3/JA4) e análise comportamental, bloqueando conexões suspeitas antes que completem o handshake HTTP.
- WAF com análise de comportamento: Detecta padrões de transmissão anômalos — timing mecânico, ausência de headers de navegador, sequências de requisições incompatíveis com comportamento humano — complementando o fingerprinting com análise de camada 7.
Saiba mais na documentação do WAF da Azion.