Pular para conteúdo

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_addr usa o IP de origem. Uma requisição cuja chave retorna vazia é completamente ignorada (útil com um map, 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ão 300s). 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ão 100).
  • block — quanto tempo um cliente bloqueado permanece fora (padrão 60m).
  • inactive — quanto tempo um cliente inativo permanece na memória antes de ser reclamado (padrão max(1h, interval, block); qualquer valor explícito deve ser pelo menos tão grande quanto interval e block).
  • redison para replicar as proibições dessa zona entre uma frota (veja abaixo); off por 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ão 5s).
  • 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. Adicione statuses=403,404,500-599 apenas 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 de 400599 (padrão 429).
  • dry_runon para 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), warn ou error.

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.

© GetPageSpeed LLC. Todos os direitos reservados.