abuse-guard: Auto-banir clientes abusivos pela taxa de resposta de erro (404/403/5xx)
Requer o plano Pro (ou superior) da assinatura GetPageSpeed NGINX Extras.
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
Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:
load_module modules/ngx_http_abuse_guard_module.so;
Este documento descreve o nginx-module-abuse-guard v1.1.0 lançado em 09 de julho de 2026.
Seu log de erros é uma confissão. Abuse Guard o lê em tempo real e bloqueia abusadores.
Todo scanner, fuzzer e bot de preenchimento de credenciais deixa a mesma impressão digital:
um spray de 404s procurando por caminhos ocultos, 403s batendo em portas trancadas, falhas
de requisição após falha de requisição. Abuse Guard observa os códigos de status que seu servidor
realmente retorna, identifica os clientes cujo tráfego é principalmente de falhas e
os bloqueia — decidido dentro do trabalhador NGINX, na própria requisição, em poucos
microsegundos. Sem sidecar. Sem transportador de logs. Sem camada de script. Apenas C
compilado fazendo um trabalho excepcionalmente bem.
Ficha técnica
| Gatilho | Taxa de respostas de erro por cliente que você escolher (403/404 por padrão) |
| Ação | Bloqueio temporário — uma proibição rígida por uma janela fixa, não um limite |
| Ponto de decisão | Fase de pré-acesso do NGINX, antes que qualquer manipulador ou upstream seja executado |
| Modelo de memória | Bytes fixos por cliente, independente do limite → escala de botnet |
| Modo de frota | Replicação de proibição opcional entre nós via Redis / Valkey |
| Durabilidade | Capturas de proibição em disco opcionais que sobrevivem a recargas e reinicializações |
| Pegada | Um módulo autônomo; zero dependências em tempo de execução por padrão |
| Plataformas | RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux |
O problema que remove
Visitantes legítimos quase nunca geram uma explosão de erros. Abusadores geram
pouco mais — essa assimetria é todo o jogo. Um scanner de vulnerabilidades percorrendo
sua árvore é uma parede de 404s. Um bot cutucando endpoints de administração é uma parede de 403s.
Uma execução de força bruta é uma parede de falhas.
Limitadores de taxa tratam esse tráfego como qualquer outro: eles desaceleram todos pelo volume de requisições e deixam o infrator voltar assim que a pressão diminui. Abuse Guard faz o oposto. Ele ignora completamente o tráfego bem-comportado e reserva sua única resposta — uma proibição real e com tempo limitado — para clientes definidos por seus erros.
Use um limitador de taxa para moldar a carga. Use Abuse Guard para expulsar abusos.
Como uma proibição é decidida
Três partes móveis, todas dentro do trabalhador:
1 · Uma pontuação vazada, por cliente. Cada identidade de cliente carrega um único número pequeno
na memória compartilhada. Cada erro correspondente adiciona a ele; a pontuação vaza
continuamente a uma taxa de threshold ÷ interval por segundo. Um curto e intenso surto o empurra
para além do limite; um fluxo lento nunca o faz. Crucialmente, essa pontuação é um registro de tamanho fixo
não importa 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 joga em você.
2 · Um prazo rígido. No momento em que a pontuação ultrapassa seu limite, o cliente
ganha um timestamp blocked_until. Até então, ele simplesmente desaparece — cada requisição
rejeitada na fase de pré-acesso, antes que o NGINX gaste um ciclo em 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
(seu código de escolha) marcados para que nenhum cache compartilhado possa armazená-lo e servir a punição de um
cliente a outro, com um Retry-After informando clientes honestos quando retornar.
Identidades são agrupadas em um digest de tamanho fixo, então usar algo grande como
$request_uri ou um cabeçalho custa exatamente tanto quanto usar um IP.
Ao vivo em menos de um minuto
Abuse Guard é enviado como um módulo pré-compilado e assinado do repositório GetPageSpeed — basta colocá-lo, sem necessidade de ferramenta de construção.
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-abuse-guard
Conecte-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 403/404 respostas dentro de uma
janela de 5 minutos, por uma hora. Aperte ou afrouxe cada número abaixo.
Configuração
Abuse Guard é composto por quatro diretivas. A primeira declara uma política; as outras a aplicam, isentam pessoas dela e (opcionalmente) a compartilham entre máquinas.
Declare uma política — abuse_guard_zone
Uma diretiva em nível http. Ela cria uma zona de memória compartilhada e define a
política que a governa. Defina quantos ou quantos menos controles você quiser — o nome e o tamanho da zona são a única coisa que você deve fornecer; valores padrão sensatos preenchem o resto (os valores mostrados abaixo são exatamente esses padrões).
abuse_guard_zone zone=clients:10m ← nome + tamanho (o único obrigatório)
key=$binary_remote_addr ← quem é "um cliente"
statuses=403,404 ← quais respostas contam como erros
interval=300s ← a janela de pontuação
threshold=100 ← erros nessa janela → banir
block=60m; ← quanto tempo a proibição dura
zone=clients:10m é a identidade e o orçamento da política: um nome que você referencia
do abuse_guard, e o tamanho da memória compartilhada. Cerca de 10 MB rastreia em torno de
cem mil clientes ativos.
Tudo o mais é 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. Uma requisição cuja chave retorna vazia é completamente ignorada (útil com ummap, abaixo).statuses— os códigos de resposta que contam como erros: códigos individuais, intervalos ou uma mistura, por exemplo,statuses=401,403,404,500-599. O padrão é403,404.interval— a janela em que a pontuação decai (padrão300s). Um surto dentro dela ativa uma proibição; um fluxo lento espalhado mais amplamente nunca acumula.threshold— quantos erros dentro dessa janela cruzam a linha, até 1024 (padrão100).block— quanto tempo um cliente bloqueado permanece fora (padrão60m).inactive— quanto tempo um cliente inativo permanece na memória antes de ser reclamado (padrãomax(1h, interval, block); qualquer valor explícito deve ser pelo menos tão grande quantointervaleblock).redis—onpara replicar as proibições dessa zona entre uma frota (veja abaixo);offpor padrão.persist— um caminho de arquivo para capturar proibições para que sobrevivam a uma reinicialização.persist_interval— com que frequência essa captura é reescrita (padrão5s).persist_secret— uma chave hexadecimal que assina a captura com HMAC-SHA256, para que um arquivo adulterado seja rejeitado em vez de carregado.
Por que
5xxé deixado de fora por padrão: um erro de servidor é geralmente uma falha do seu lado, e contá-lo permitiria que um backend instável banisse visitantes inocentes. Adicionestatuses=403,404,500-599apenas quando você quiser deliberadamente agir sobre clientes que acionam erros de servidor.
Aplique-a — abuse_guard
*Válido em blocos http, server e location, então você pode proteger um site inteiro
ou apenas os endpoints que atraem abusos. Nomeie a zona para ativá-la; escreva
abuse_guard off; em um escopo aninhado para desativá-la 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 de400–599(padrão429).dry_run—onpara observar sem aplicar: o veredicto é registrado, mas nenhuma proibição é escrita. Desativado por padrão.log_level— quão alto registrar cada decisão:info,notice(padrão),warnouerror.
Implemente sem medo com dry_run=on. Ele registra cada proibição que emitiria
sem tocar no estado, para que você possa calibrar limites contra tráfego ao vivo — mesmo
ao lado de uma localização que aplica a proibição na mesma zona — e depois ativá-la ao vivo.
Isente os bons — 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 é no verdadeiro
endereço de conexão, então coopera com realip. Esta também é a forma como você protege
crawlers de busca verificados: permita os intervalos publicados do Googlebot / Bingbot para que um
bot percorrendo URLs obsoletas (e acumulando 404s) nunca seja pego.
Compartilhe proibições entre a 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 uma proibição obtida 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 de aplicação (RHEL, Rocky, AlmaLinux) o kernel impede que o NGINX
abra a conexão com o Redis até que você permita uma vez —
setsebool -P httpd_can_network_connect 1. Pule isso e a replicação silenciosamente
não faz nada enquanto a aplicação local continua normalmente.
Uma proibição, cada nó — sem desacelerar uma única requisição
Atrás de um balanceador de carga, uma proibição por servidor é teatro: o atacante simplesmente cai em um nó diferente. 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 emite uma proibição, ele transmite esse único fato para o cluster e registra uma cópia durável. Cada outro nó a importa em milissegundos, e qualquer nó que estava offline reconcilia no momento em que se reconecta. Como a aplicação é sempre servida a partir do estado em memória de cada nó, a requisição de um visitante nunca espera por uma viagem de rede — o único custo do agrupamento é que um atacante recém-banido é bloqueado em toda a frota um batedor 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 ausente 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 emitir proibições.
Proibições que sobrevivem a uma reinicialização
Aponte uma zona para um arquivo e proibições ativas são capturadas em um intervalo e restauradas na inicialização, para que uma recarga ou reinicialização não dê a cada atacante uma nova chance.
abuse_guard_zone zone=clients:10m
persist=/var/lib/nginx/abuse_guard/clients.state
persist_secret=00112233445566778899aabbccddeeff;
A captura é verificada quanto à integridade, escrita de forma que uma falha nunca possa deixar um arquivo corrompido,
e — com persist_secret — assinada criptograficamente para que um arquivo adulterado seja
rejeitado em vez de confiável. Mantenha o diretório legível apenas pelo usuário do trabalhador.
Veja tudo o que decide
Três variáveis expõem o veredicto do Abuse Guard aos seus logs e configuração:
| Variável | Valor |
|---|---|
$abuse_guard_status |
BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN |
$abuse_guard_count |
Erros atualmente atribuídos a este cliente. |
$abuse_guard_blocked_until |
Tempo Unix em que a proibição é levantada, ou 0. |
log_format guard '$remote_addr "$request" $status '
'guard=$abuse_guard_status count=$abuse_guard_count';
Chaveando atrás de um CDN ou proxy? Nunca confie em um X-Forwarded-For bruto. Deixe
realip resolver o verdadeiro cliente primeiro, depois chaveie em $binary_remote_addr:
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
Abuse Guard é mantido a um padrão muito acima de "ele compila." Cada mudança passa pelo filtro do AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, análise estática e fuzzing contínuo de seus analisadores e formato em disco. Suas dependências opcionais — agrupamento e capturas assinadas — são de melhor esforço 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 é mantido refém de uma dependência.
Obtenha o Abuse Guard
Abuse Guard é um módulo comercial do NGINX da GetPageSpeed LLC, entregue com atualizações e suporte contínuos 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 configuração → getpagespeed.com/contact-us
© GetPageSpeed LLC. Todos os direitos reservados.