abuse-guard: Banimento automático de clientes abusivos pela taxa de respostas de erro
Instalação
Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:
- RedHat Enterprise Linux 7, 8, 9 e 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 e Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-abuse-guard
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-abuse-guard
Habilite o módulo adicionando o seguinte no topo do /etc/nginx/nginx.conf:
load_module modules/ngx_http_abuse_guard_module.so;
Este documento descreve o nginx-module-abuse-guard v2.1.0 lançado em 03 de setembro de 2026.
Seu log de erros é uma confissão. O Abuse Guard o lê em tempo real e bloqueia os abusadores.
Todo scanner, fuzzer e bot de preenchimento de credenciais deixa a mesma impressão digital:
uma rajada de 404s procurando por caminhos ocultos, 403s testando portas trancadas, falhas
após falhas de requisições. O Abuse Guard observa os códigos de status que seu servidor
realmente retorna, identifica os clientes cujo tráfego é majoritariamente composto por falhas e os
bloqueia — decidido dentro do worker do NGINX, na própria requisição, em poucos
microssegundos. Sem sidecar. Sem shipper de logs. Sem camada de scripting. Apenas C compilado
fazendo um trabalho excepcionalmente bem.
Ficha técnica
| Gatilho | Taxa por cliente de respostas de erro que você escolher (403/404 por padrão) |
| Ação | Bloqueio temporário — um banimento rígido por uma janela fixa, não um throttle |
| Ponto de decisão | Fase de pré-acesso do NGINX, antes de qualquer handler ou upstream ser executado |
| Modelo de memória | Bytes fixos por cliente, independente do limite → escala para botnets |
| Modo de frota | Replicação opcional de banimentos entre nós via Redis / Valkey |
| Durabilidade | Snapshots opcionais de saída preservam banimentos ativos entre reinicializações |
| Pegada | Um módulo autocontido; zero dependências de runtime por padrão |
| Plataformas | RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux |
| ## |
O problema que ele elimina
Visitantes legítimos quase nunca geram uma rajada de erros. Abusadores geram
pouco mais do que isso — essa assimetria é o jogo inteiro. Um scanner de vulnerabilidades percorrendo
sua árvore de diretórios é uma parede de 404s. Um bot testando endpoints de administração é uma parede de 403s.
Uma tentativa de força bruta é uma parede de falhas.
Limitadores de taxa tratam esse tráfego como qualquer outro: eles diminuem a velocidade de todos pelo volume de requisições e deixam o infrator voltar imediatamente assim que ele diminui o ritmo. O Abuse Guard faz o oposto. Ele ignora completamente o tráfego bem-comportado e reserva sua única resposta — um banimento real, com tempo limitado — para clientes definidos por seus erros.
Use um limitador de taxa para modelar a carga. Use o Abuse Guard para expulsar o abuso.
Como um banimento é decidido
Três partes móveis, todas dentro do worker:
1 · Uma pontuação com vazamento, por cliente. Cada identidade de cliente carrega um único número
pequeno na memória compartilhada. Cada erro correspondente adiciona um ponto por padrão, ou o
peso que você atribuir àquele status; a pontuação se dissipa continuamente a
limite ÷ intervalo por segundo. Uma rajada curta e intensa a ultrapassa o limite;
um gotejamento lento nunca o faz. Crucialmente, essa pontuação é um registro de tamanho fixo,
não importa o quão alto você defina o limite, então uma única zona rastreia confortavelmente as
dezenas de milhares de endereços de origem distintos que uma botnet lança contra você.
2 · Um prazo rígido. No momento em que a pontuação cruza seu limite, o cliente
ganha um timestamp blocked_until. Até lá, ele simplesmente desaparece — toda requisição é
recusada na fase de pré-acesso, antes que o NGINX gaste um ciclo com roteamento,
arquivos ou upstreams. A rejeição é o resultado mais barato possível.
3 · Uma recusa correta em termos de privacidade. Clientes banidos recebem 429 Too Many Requests
(o código de sua escolha) marcado para que nenhum cache compartilhado possa armazená-lo e servir a
punição de um cliente para outro, com um Retry-After informando aos clientes honestos quando
retornar.
Identidades são transformadas em um digest de tamanho fixo, então usar algo grande como
$request_uri ou um cabeçalho como chave custa exatamente a mesma memória que usar um IP como chave.
Funcionando em menos de um minuto
O Abuse Guard é distribuído como um módulo pré-compilado e assinado do repositório GetPageSpeed — instale-o, sem necessidade de toolchain de build.
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-abuse-guard
Configure-o:
load_module modules/ngx_http_abuse_guard_module.so;
http {
abuse_guard_zone zone=clients:10m; # uma zona de memória compartilhada
server {
location / {
abuse_guard zone=clients; # aplicar aqui
}
}
}
sudo nginx -t && sudo systemctl reload nginx
Esses padrões banem qualquer IP que retorne 100 respostas 403/404 dentro de uma
janela de 5 minutos, por uma hora. Ajuste cada número abaixo para mais ou para menos.
Configuração
O Abuse Guard tem quatro diretivas. A primeira declara uma política; as demais a aplicam, isentam pessoas dela e (opcionalmente) a compartilham entre máquinas.
Declare uma política — abuse_guard_zone
Uma diretiva de nível http. Ela define uma zona de memória compartilhada e define a
política que a governa. Defina quantos parâmetros quiser — o nome e o tamanho da
zona são as únicas coisas obrigatórias; padrões sensatos preenchem o
restante (os valores mostrados abaixo são exatamente esses padrões).
abuse_guard_zone zone=clients:10m ← nome + tamanho (único obrigatório)
key=$binary_remote_addr ← quem é "um cliente"
statuses=403,404 ← quais respostas adicionam à pontuação
interval=300s ← a janela de pontuação
threshold=100 ← pontuação nessa janela → banimento
block=60m; ← por quanto tempo o banimento dura
zone=clients:10m é a identidade e o orçamento da política: um nome que você referencia
a partir do abuse_guard, e o tamanho da memória compartilhada. Cerca de 10 MB rastreia na ordem de
cem mil clientes ativos.
Todo o resto é ajuste opcional:
key— a expressão que define um único cliente. Qualquer variável NGINX; o padrão$binary_remote_addrusa o IP de origem como chave. Uma requisição cuja chave resultar vazia é ignorada por completo (útil com ummap, abaixo).statuses— as respostas que adicionam à pontuação. Um código simples ou faixa tem peso 1, preservando a sintaxe original:statuses=403,404,500-599. Adicione:pesopara fazer uma resposta consumir mais do mesmo orçamento, por exemplostatuses=404,401:5,500-599:2. Pesos são inteiros de 1 a 1024 e uma faixa aplica seu peso a cada status que cobre. Repetir ou sobrepor um status com o mesmo peso é inofensivo; pesos conflitantes fazem onginx -tfalhar. O padrão permanece403,404.interval— a janela sobre a qual a pontuação decai (padrão300s). Uma rajada dentro dela dispara um banimento; um gotejamento lento distribuído por um período maior nunca se acumula.threshold— quantos pontos de pontuação dentro dessa janela cruzam o limite, até 1024 (padrão100). Uma resposta pesada pode consumir o orçamento restante e disparar um banimento imediatamente.block— por quanto tempo um cliente que disparou o limite permanece bloqueado (padrão60m).inactive— por quanto tempo um cliente inativo permanece na memória antes de ser recuperado (padrãomax(1h, interval, block); qualquer valor explícito deve ser pelo menos tão grande quantointervaleblock).redis—onpara replicar os banimentos desta zona em uma frota (veja abaixo);offpor padrão.persist— um caminho de arquivo onde os banimentos ativos são gravados na saída limpa do worker e carregados na inicialização.persist_secret— em builds com suporte a snapshot assinado, uma chave hex que adiciona autenticação HMAC-SHA256 para que um arquivo adulterado seja rejeitado.
Por que
5xxfica de fora por padrão: um erro de servidor geralmente é causado pelo seu lado, e contá-lo permitiria que um backend instável fizesse visitantes inocentes serem banidos. Adicionestatuses=403,404,500-599somente quando quiser deliberadamente agir contra clientes que disparam erros de servidor.
Aplique-o — abuse_guard
Válido em blocos http, server e location, para que você possa proteger um site inteiro
ou apenas os endpoints que atraem abuso. Nomeie a zona para ativá-lo; escreva
abuse_guard off; em um escopo aninhado para desativá-lo novamente.
location /wp-login.php {
abuse_guard zone=clients status=429 log_level=warn;
}
zone— a zona (declarada acima) cuja política se aplica aqui.status— o código que um cliente banido recebe, em qualquer lugar entre400–599(padrão429).dry_run—onpara observar sem aplicar: o veredito é registrado, mas nenhum banimento é gravado. Desligado por padrão.log_level— o quão alto registrar cada decisão:info,notice(padrão),warnouerror.
Implemente sem medo com dry_run=on. Ele registra cada banimento que aplicaria
sem tocar no estado, para que você possa calibrar os limites contra o tráfego real — até
mesmo ao lado de uma localização que aplica na mesma zona — e então ative-o.
Isente os mocinhos — abuse_guard_allow
Contexto: http · server · location · repetível, herdado para baixo.
abuse_guard_allow 127.0.0.0/8;
abuse_guard_allow 10.0.0.0/8 192.168.0.0/16;
Clientes listados nunca são contados e nunca são banidos. A correspondência é feita no endereço
real da conexão, então coopera com o realip. Esta também é a forma de proteger
crawlers de busca verificados: permita as faixas publicadas do Googlebot / Bingbot para que um
bot percorrendo URLs desatualizadas (e acumulando 404s) nunca seja pego.
Compartilhe banimentos pela frota — abuse_guard_redis
Contexto: http
abuse_guard_redis host=10.0.0.5 password=… ; # tls://host para TLS
abuse_guard_zone zone=clients:10m redis=on;
Aponte cada nó para um Redis ou Valkey, ative redis=on, e um banimento aplicado em qualquer
máquina se propaga para todas elas. Padrões: port=6379, db=0, prefix=ag_,
timeout=100ms. Como isso permanece rápido é a próxima seção.
SELinux: em sistemas com enforcing (RHEL, Rocky, AlmaLinux), o kernel impede o NGINX
de abrir a conexão com o Redis até que você a permita uma vez —
setsebool -P httpd_can_network_connect 1. Pule isso e a replicação silenciosamente
não fará nada enquanto a aplicação local continua normalmente.
Um banimento, cada nó — sem desacelerar uma única requisição
Atrás de um balanceador de carga, um banimento por servidor é teatro: o atacante simplesmente cai em um nó diferente. O Abuse Guard fecha essa lacuna sem nunca colocar o Redis no caminho da requisição.
Cada nó decide localmente e conta localmente. No instante em que aplica um banimento, ele transmite esse único fato para o cluster e registra uma cópia durável. Cada outro nó o importa em milissegundos, e qualquer nó que estava offline reconcilia no momento em que se reconecta. Como a aplicação é sempre servida do estado em memória de cada nó, a requisição de um visitante nunca espera por uma ida e volta de rede — o único custo do clustering é que um atacante recém-banido é bloqueado em toda a frota um heartbeat depois, em vez de instantaneamente.
O Redis aqui é um sino de alarme unidirecional, não um livro-razão compartilhado consultado por requisição — então um Redis lento ou indisponível nunca pode adicionar latência ao seu tráfego. Execute-o em uma rede privada e trate-o como privilegiado: qualquer coisa que possa escrever nele pode aplicar banimentos.
Banimentos que sobrevivem a uma reinicialização
Aponte uma zona para um arquivo e os banimentos ativos são gravados quando o worker sai limpo, e então restaurados na inicialização. Recarregamentos e reinicializações ordenadas mantêm os banimentos atuais sem executar um gravador periódico de zona inteira. Uma falha abrupta de processo ou máquina pode perder banimentos emitidos desde a última saída limpa; a aplicação ainda falha de forma aberta.
abuse_guard_zone zone=clients:10m
persist=/var/lib/nginx/abuse_guard/clients.state
persist_secret=00112233445566778899aabbccddeeff;
O snapshot compacto contém apenas digests de identidade e prazos de banimento. CRC32
detecta corrupção, e uma renomeação atômica mantém gravações parciais fora do caminho
ativo. Builds com suporte a snapshot assinado podem adicionalmente autenticá-lo com
persist_secret. Mantenha o diretório legível apenas pelo usuário do worker.
Veja tudo o que ele decide
Três variáveis expõem o veredito do Abuse Guard aos seus logs e configuração:
| Variável | Valor |
|---|---|
$abuse_guard_status |
BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN |
$abuse_guard_count |
Pontuação ponderada atual, arredondada para um ponto inteiro. |
$abuse_guard_blocked_until |
Tempo Unix em que o banimento termina, ou 0. |
log_format guard '$remote_addr "$request" $status '
'guard=$abuse_guard_status count=$abuse_guard_count';
Usando chave atrás de um CDN ou proxy? Nunca confie em um X-Forwarded-For bruto. Deixe o
realip resolver o cliente real primeiro, e então use $binary_remote_addr como chave:
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Precisa de lógica de isenção por requisição? Qualquer requisição cuja key resolva para uma string
vazia é ignorada — então um map permite que você, por exemplo, rastreie visitantes anônimos por IP enquanto
deixa usuários autenticados intocados.
Projetado para ser confiável em produção
O Abuse Guard é mantido em um padrão muito acima de "ele compila." Cada mudança passa pelo batalhão de AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, análise estática e fuzzing contínuo de seus parsers e formato em disco. Suas dependências opcionais — clustering e snapshots assinados — são best-effort por design: se o Redis ou o disco se comportarem mal, a aplicação continua silenciosamente a partir da memória local. Seu tráfego nunca é refém de uma dependência.
Obtenha o Abuse Guard
O Abuse Guard é um módulo NGINX comercial da GetPageSpeed LLC, entregue com atualizações contínuas e suporte através de uma assinatura GetPageSpeed.
- Navegue pelo catálogo completo de módulos NGINX → https://nginx-extras.getpagespeed.com/modules/
- Licenciamento, implantações em volume ou ajuda para configurar → getpagespeed.com/contact-us
© GetPageSpeed LLC. Todos os direitos reservados.