Saltar a contenido

abuse-guard: Auto-prohibir clientes abusivos por tasa de respuestas de error (404/403/5xx)

Requiere el plan Pro (o superior) de la suscripción de NGINX Extras de GetPageSpeed.

Instalación

Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:

  • RedHat Enterprise Linux 7, 8, 9 y 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 y 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

Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:

load_module modules/ngx_http_abuse_guard_module.so;

Este documento describe nginx-module-abuse-guard v1.1.0 lanzado el 09 de julio de 2026.


Tu registro de errores es una confesión. Abuse Guard lo lee en tiempo real y cierra la puerta a los abusadores.

Cada escáner, fuzzer y bot de relleno de credenciales deja la misma huella: una lluvia de 404s buscando rutas ocultas, 403s golpeando puertas cerradas, solicitud fallida tras solicitud fallida. Abuse Guard observa los códigos de estado que tu servidor realmente devuelve, identifica a los clientes cuyo tráfico es mayormente fallido y los bloquea — decidido dentro del trabajador de NGINX, en la solicitud misma, en unos pocos microsegundos. Sin sidecar. Sin transportador de registros. Sin capa de scripting. Solo C compilado haciendo un trabajo excepcionalmente bien.

Hoja de especificaciones

Disparador Tasa de respuestas de error por cliente que eliges (403/404 por defecto)
Acción Bloqueo temporal — una prohibición dura por un tiempo fijo, no una limitación
Punto de decisión Fase de preacceso de NGINX, antes de que se ejecute cualquier manejador o upstream
Modelo de memoria Bytes fijos por cliente, independiente del umbral → escala de botnet
Modo de flota Replicación de prohibiciones opcional entre nodos a través de Redis / Valkey
Durabilidad Instantáneas de prohibición opcionales en disco que sobreviven a recargas y reinicios
Huella Un módulo autónomo; cero dependencias en tiempo de ejecución por defecto
Plataformas RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux

El problema que elimina

Los visitantes legítimos casi nunca generan una explosión de errores. Los abusadores generan poco más — esa asimetría es todo el juego. Un escáner de vulnerabilidades caminando por tu árbol es una pared de 404s. Un bot sondeando puntos finales de administrador es una pared de 403s. Una ejecución de fuerza bruta es una pared de fallos.

Los limitadores de tasa tratan ese tráfico como cualquier otro: ralentizan a todos por volumen de solicitud y dejan que el infractor vuelva a entrar en el instante en que se afloja. Abuse Guard hace lo contrario. Ignora completamente el tráfico bien comportado y reserva su única respuesta — una prohibición real y limitada en el tiempo — para clientes definidos por sus errores.

Usa un limitador de tasa para dar forma a la carga. Usa Abuse Guard para desalojar abusos.

Cómo se decide una prohibición

Tres partes móviles, todas dentro del trabajador:

1 · Una puntuación filtrante, por cliente. Cada identidad de cliente lleva un solo número pequeño en memoria compartida. Cada error que coincide añade a ella; la puntuación se desangra continuamente a umbral ÷ intervalo por segundo. Un estallido corto y agudo la empuja más allá de la línea; un goteo lento nunca lo hace. Crucialmente, esa puntuación es un registro de tamaño fijo sin importar cuán alto establezcas el umbral — así que una sola zona rastrea cómodamente las decenas de miles de direcciones de origen distintas que una botnet te lanza.

2 · Un plazo duro. En el momento en que la puntuación cruza tu umbral, el cliente gana un timestamp bloqueado_hasta. Hasta entonces simplemente está ausente — cada solicitud es rechazada en la fase de preacceso, antes de que NGINX gaste un ciclo en enrutamiento, archivos o upstreams. El rechazo es el resultado más barato posible.

3 · Un rechazo correcto en términos de privacidad. Los clientes prohibidos reciben 429 Too Many Requests (código de tu elección) etiquetado para que ninguna caché compartida pueda almacenarlo y servir la penalización de un cliente a otro, con un Retry-After indicando a los clientes honestos cuándo regresar.

Las identidades se pliegan en un resumen de tamaño fijo, por lo que clavear algo voluminoso como $request_uri o un encabezado cuesta exactamente la misma cantidad de memoria que clavear una IP.

Vive en menos de un minuto

Abuse Guard se envía como un módulo precompilado y firmado desde el repositorio de GetPageSpeed — simplemente colócalo, no se requiere herramienta de construcción.

sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-abuse-guard

Conéctalo:

load_module modules/ngx_http_abuse_guard_module.so;

http {
    abuse_guard_zone zone=clients:10m;     # una zona de memoria compartida

    server {
        location / {
            abuse_guard zone=clients;      # hacer cumplir aquí
        }
    }
}
sudo nginx -t && sudo systemctl reload nginx

Esos valores predeterminados prohíben cualquier IP que devuelva 100 403/404 respuestas dentro de un intervalo de 5 minutos, durante una hora. Ajusta o relaja cada número a continuación.

Configuración

Abuse Guard tiene cuatro directivas. La primera declara una política; las demás la aplican, eximen a personas de ella y (opcionalmente) la comparten entre máquinas.

Declara una política — abuse_guard_zone

Una directiva a nivel http. Crea una zona de memoria compartida y establece la política que la rige. Establece tantos o tan pocos controles como desees: el nombre y el tamaño de la zona son lo único que debes proporcionar; valores predeterminados sensatos completan el resto (los valores que se muestran a continuación son exactamente esos valores predeterminados).

abuse_guard_zone  zone=clients:10m             nombre + tamaño (lo único imprescindible)
                  key=$binary_remote_addr      quién es "un cliente"
                  statuses=403,404             qué respuestas cuentan como errores
                  interval=300s                la ventana de puntuación
                  threshold=100                errores en esa ventana  prohibir
                  block=60m;                   cuánto tiempo dura la prohibición

zone=clients:10m es la identidad y el presupuesto de la política: un nombre que referencias desde abuse_guard, y el tamaño de la memoria compartida. Aproximadamente 10 MB rastrean del orden de cien mil clientes activos.

Todo lo demás es ajuste opcional:

  • key — la expresión que define un solo cliente. Cualquier variable de NGINX; el valor predeterminado $binary_remote_addr clavea en la IP de origen. Una solicitud cuyo clave salga vacía se omite por completo (útil con un map, a continuación).
  • statuses — los códigos de respuesta que cuentan como errores: códigos individuales, rangos, o una mezcla, por ejemplo statuses=401,403,404,500-599. Por defecto es 403,404.
  • interval — la ventana en la que la puntuación se descompone (por defecto 300s). Un estallido dentro de ella activa una prohibición; un goteo lento extendido nunca acumula.
  • threshold — cuántos errores dentro de esa ventana cruzan la línea, hasta 1024 (por defecto 100).
  • block — cuánto tiempo un cliente activado permanece bloqueado (por defecto 60m).
  • inactive — cuánto tiempo un cliente inactivo permanece en memoria antes de ser reclamado (por defecto max(1h, interval, block); cualquier valor explícito debe ser al menos tan grande como interval y block).
  • redison para replicar las prohibiciones de esta zona a través de una flota (ver abajo); off por defecto.
  • persist — una ruta de archivo para almacenar instantáneas de prohibiciones para que sobrevivan a un reinicio.
  • persist_interval — con qué frecuencia se reescribe esa instantánea (por defecto 5s).
  • persist_secret — una clave hexadecimal que firma la instantánea con HMAC-SHA256, de modo que un archivo manipulado sea rechazado en lugar de cargado.

Por qué se omite 5xx por defecto: un error del servidor es generalmente culpa de tu lado, y contarlo permitiría que un backend inestable hiciera que visitantes inocentes fueran prohibidos. Añade statuses=403,404,500-599 solo cuando desees actuar deliberadamente sobre clientes que desencadenan errores del servidor.

Aplícalo — abuse_guard

Válido en bloques http, server y location, por lo que puedes proteger todo un sitio o solo los puntos finales que atraen abusos. Nombra la zona para activarla; escribe abuse_guard off; en un ámbito anidado para desactivarla nuevamente.

location /wp-login.php {
    abuse_guard zone=clients status=429 log_level=warn;
}
  • zone — la zona (declarada arriba) cuya política se aplica aquí.
  • status — el código que recibe un cliente prohibido, en cualquier lugar de 400599 (por defecto 429).
  • dry_runon para observar sin hacer cumplir: el veredicto se registra pero no se escribe ninguna prohibición. Apagado por defecto.
  • log_level — cuán ruidosamente registrar cada decisión: info, notice (por defecto), warn o error.

Despliega sin miedo con dry_run=on. Registra cada prohibición que emitiría sin tocar el estado, para que puedas calibrar umbrales contra tráfico en vivo — incluso junto a una ubicación que esté haciendo cumplir en la misma zona — y luego activarlo en vivo.

Exime a los buenos — abuse_guard_allow

Contexto: http · server · location · repetible, heredado hacia abajo.

abuse_guard_allow 127.0.0.0/8;
abuse_guard_allow 10.0.0.0/8 192.168.0.0/16;

Los clientes listados nunca son contados y nunca son prohibidos. La coincidencia se realiza en la verdadera dirección de conexión, por lo que coopera con realip. Así es como proteges a raspadores de búsqueda verificados: permite los rangos publicados de Googlebot / Bingbot para que un bot que atraviesa URLs obsoletas (y acumulando 404s) nunca sea atrapado.

Comparte prohibiciones a través de la flota — 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;

Apunta cada nodo a un Redis o Valkey, activa redis=on, y una prohibición ganada en cualquier máquina se propaga a todas ellas. Valores predeterminados: port=6379, db=0, prefix=ag_, timeout=100ms. Cómo se mantiene rápido es la siguiente sección.

SELinux: en sistemas de aplicación (RHEL, Rocky, AlmaLinux) el kernel impide que NGINX abra la conexión a Redis hasta que lo permitas una vez — setsebool -P httpd_can_network_connect 1. Si omites esto, la replicación no hará nada silenciosamente mientras la aplicación local continúa como de costumbre.

Una prohibición, cada nodo — sin ralentizar una sola solicitud

Detrás de un balanceador de carga, una prohibición por servidor es teatro: el atacante simplemente aterriza en un nodo diferente. Abuse Guard cierra esa brecha sin poner nunca a Redis en el camino de la solicitud.

Cada nodo decide localmente y cuenta localmente. En el instante en que emite una prohibición, difunde ese único hecho al clúster y registra una copia duradera. Cada otro nodo lo importa en milisegundos, y cualquier nodo que estuvo fuera de línea se reconcilia en el momento en que se reconecta. Debido a que la aplicación siempre se sirve desde el estado en memoria de cada nodo, la solicitud de un visitante nunca espera un viaje de red — el único costo de la agrupación es que un atacante recién prohibido se queda fuera de la flota un latido después en lugar de instantáneamente.

Redis aquí es una campana de alarma unidireccional, no un libro mayor compartido consultado por cada solicitud — así que un Redis lento o ausente nunca puede añadir latencia a tu tráfico. Ejecútalo en una red privada y trátalo como privilegiado: cualquier cosa que pueda escribir en él puede emitir prohibiciones.

Prohibiciones que sobreviven a un reinicio

Apunta una zona a un archivo y las prohibiciones activas se almacenan en instantáneas en un intervalo y se restauran al inicio, de modo que una recarga o un reinicio no le dé a cada atacante una pizarra fresca.

abuse_guard_zone zone=clients:10m
                 persist=/var/lib/nginx/abuse_guard/clients.state
                 persist_secret=00112233445566778899aabbccddeeff;

La instantánea se verifica en integridad, se escribe para que un fallo nunca deje un archivo roto, y — con persist_secret — se firma criptográficamente para que un archivo manipulado sea rechazado en lugar de confiado. Mantén el directorio legible solo por el usuario del trabajador.

Ve todo lo que decide

Tres variables exponen el veredicto de Abuse Guard a tus registros y configuración:

Variable Valor
$abuse_guard_status BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN
$abuse_guard_count Errores actualmente atribuidos a este cliente.
$abuse_guard_blocked_until Tiempo Unix en que se levanta la prohibición, o 0.
log_format guard '$remote_addr "$request" $status '
                 'guard=$abuse_guard_status count=$abuse_guard_count';

¿Claveando detrás de un CDN o proxy? Nunca confíes en un X-Forwarded-For crudo. Deja que realip resuelva primero el cliente real, luego clavea en $binary_remote_addr:

set_real_ip_from 10.0.0.0/8;
real_ip_header   X-Forwarded-For;
real_ip_recursive on;

¿Necesitas lógica de exención por solicitud? Cualquier solicitud cuyo key resuelva a una cadena vacía es ignorada — así que un map te permite, por ejemplo, rastrear visitantes anónimos por IP mientras dejas a los usuarios autenticados sin tocar.

Diseñado para ser confiable en producción

Abuse Guard se mantiene a un estándar muy por encima de "compila." Cada cambio pasa por el gauntlet de AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, análisis estático y fuzzing continuo de sus analizadores y formato en disco. Sus dependencias opcionales — agrupación y instantáneas firmadas — son de mejor esfuerzo por diseño: si Redis o el disco se comportan mal, la aplicación continúa silenciosamente desde la memoria local. Tu tráfico nunca se mantiene como rehén de una dependencia.

Obtén Abuse Guard

Abuse Guard es un módulo comercial de NGINX de GetPageSpeed LLC, entregado con actualizaciones y soporte continuos a través de una suscripción de GetPageSpeed.

© GetPageSpeed LLC. Todos los derechos reservados.