Pular para conteúdo

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_addr usa o IP de origem como chave. Uma requisição cuja chave resultar vazia é ignorada por completo (útil com um map, 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 :peso para fazer uma resposta consumir mais do mesmo orçamento, por exemplo statuses=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 o nginx -t falhar. O padrão permanece 403,404.
  • interval — a janela sobre a qual a pontuação decai (padrão 300s). 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ão 100). 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ão 60m).
  • inactive — por quanto tempo um cliente inativo permanece na memória antes de ser recuperado (padrão max(1h, interval, block); qualquer valor explícito deve ser pelo menos tão grande quanto interval e block).
  • redison para replicar os banimentos desta zona em uma frota (veja abaixo); off por 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 5xx fica 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. Adicione statuses=403,404,500-599 somente 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 entre 400599 (padrão 429).
  • dry_runon para 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), warn ou error.

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.

© GetPageSpeed LLC. Todos os direitos reservados.