abuse-guard: Auto-banir clientes abusivos pela taxa de resposta de erro
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 nginx-module-abuse-guard v2.0.0 lançado em 19 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 caçando caminhos ocultos, 403s batendo em portas trancadas, solicitação falhada após solicitação falhada. Abuse Guard observa os códigos de status que seu servidor realmente retorna, identifica os clientes cujo tráfego é principalmente falhas e os bloqueia — decidido dentro do trabalhador NGINX, na própria solicitação, em poucos microssegundos. Sem sidecar. Sem log shipper. 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 um período fixo, não um throttle |
| Ponto de decisão | Fase de pré-acesso do NGINX, antes de qualquer manipulador ou upstream ser 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 saída opcionais preservam proibições ativas entre reinicializações |
| Pegada | Um módulo autossuficiente; 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 é o jogo todo. Um scanner de vulnerabilidades percorrendo sua árvore é uma parede de 404s. Um bot cutucando endpoints de administrador é 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 solicitações e deixam o infrator entrar novamente no instante em 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, 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. Uma explosão curta e aguda a empurra para o limite; um gotejamento lento nunca o faz. Crucialmente, essa pontuação é um registro de tamanho fixo não importa quão alto você defina o limite — assim, 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 solicitaçã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) marcado para que nenhum cache compartilhado possa armazená-lo e servir a punição de um cliente a outro, com um Retry-After informando os clientes honestos quando retornar.
Identidades são incorporadas em um digest de tamanho fixo, então chavear em algo grande como $request_uri ou um cabeçalho custa exatamente a mesma quantidade de memória que chavear em 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; # aplique aqui
}
}
}
sudo nginx -t && sudo systemctl reload nginx
Esses padrões banem qualquer IP que retorna 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 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 estabelece a política que a governa. Defina quantos ou quantos ajustes 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 de abuse_guard, e o tamanho da memória compartilhada. Cerca de 10 MB rastreiam da ordem 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_addrchaveia no IP de origem. Uma solicitação cujo chave resulta em vazio é 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). Uma explosão dentro dela ativa uma proibição; um gotejamento lento espalhado nunca acumula.threshold— quantos erros dentro dessa janela ultrapassam o limite, até 1024 (padrão100).block— quanto tempo um cliente acionado permanece bloqueado (padrão60m).inactive— quanto tempo um cliente dormente 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 as proibições dessa zona entre uma frota (veja abaixo);offpor padrão.persist— um caminho de arquivo onde as proibições ativas são despejadas na saída limpa do trabalhador e carregadas 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
5xxé deixado de fora por padrão: um erro de servidor é geralmente culpa 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, para que você possa proteger todo um site ou apenas os endpoints que atraem abusos. Nomeie a zona para ativá-la; escreva abuse_guard off; em um escopo aninhado para desativá-la.
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 impor: o veredicto é registrado, mas nenhuma proibição é escrita. Desligado 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 em relação ao 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;
Os clientes listados nunca são contados e nunca são banidos. A correspondência é no verdadeiro endereço de conexão, então ele 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 que percorre URLs obsoletos (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 atrasar uma única solicitação
Atrás de um balanceador de carga, uma proibição por servidor é teatro: o atacante simplesmente aterrissa em um nó diferente. Abuse Guard fecha essa lacuna sem nunca colocar o Redis no caminho da solicitaçã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 solicitação de um visitante nunca espera por uma viagem de ida e volta na rede — o único custo de clustering é que um atacante recém-banido é excluído em toda a frota um batimento cardíaco depois, em vez de instantaneamente.
O Redis aqui é um sino de alarme unidirecional, não um livro-razão compartilhado consultado por solicitaçã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 as proibições ativas são despejadas quando o trabalhador sai limpo, depois restauradas na inicialização. Recargas e reinicializações ordenadas mantêm as proibições atuais sem executar um escritor de zona completo periódico. Uma falha abrupta de processo ou máquina pode perder proibições emitidas 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 proibição. CRC32 detecta corrupção, e um renomear atômico mantém gravações parciais fora do caminho ativo. Builds com suporte a snapshot assinado podem autenticar adicionalmente com persist_secret. 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, então 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 solicitação? Qualquer solicitação cuja key resulte em 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 "compila." Cada mudança passa pelo teste do 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 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 NGINX comercial 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.