Saltar a contenido

abuse-guard: Auto-prohibir clientes abusivos por tasa de respuesta de error

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

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 v2.0.0 lanzado el 19 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 elijas (403/404 por defecto)
Acción Bloqueo temporal — una prohibición dura por un período fijo, no un límite
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 salida opcionales preservan prohibiciones activas entre 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 ráfaga de errores. Los abusadores generan poco más — esa asimetría es todo el juego. Un escáner de vulnerabilidades recorriendo tu árbol es una pared de 404s. Un bot tocando puntos finales de administración 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 solicitudes y dejan entrar al infractor en el instante en que se alivia. 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 los 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 · Un puntaje filtrante, por cliente. Cada identidad de cliente lleva un solo número pequeño en memoria compartida. Cada error coincidente suma a él; el puntaje se desvanece continuamente a umbral ÷ intervalo por segundo. Una ráfaga corta y aguda lo empuja más allá de la línea; un goteo lento nunca lo hace. Crucialmente, ese puntaje 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 · Una fecha límite estricta. En el momento en que el puntaje cruza tu umbral, el cliente gana un timestamp blocked_until. 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 (tu elección de código) 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 utilizar algo grande como $request_uri o un encabezado cuesta exactamente la misma cantidad de memoria que utilizar una IP.

Vive en menos de un minuto

Abuse Guard se envía como un módulo precompilado y firmado desde el repositorio GetPageSpeed — 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 período de 5 minutos, durante una hora. Ajusta o afloja cada número a continuación.

Configuración

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

Declarar 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 tantas o tan pocas configuraciones como desees; el nombre y tamaño de la zona son lo único que debes proporcionar; valores predeterminados sensatos completan el resto (los valores mostrados a continuación son exactamente esos predeterminados).

abuse_guard_zone  zone=clients:10m             nombre + tamaño (lo único que es obligatorio)
                  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 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 se basa en la IP de origen. Una solicitud cuyo clave resulte vacía se omite completamente (ú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 el puntaje se degrada (por defecto 300s). Una ráfaga dentro de ella activa una prohibición; un goteo lento que se extiende nunca acumula.
  • threshold — cuántos errores dentro de esa ventana cruzan la línea, hasta 1024 (por defecto 100).
  • block — cuánto tiempo permanece bloqueado un cliente activado (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 donde se vuelcan las prohibiciones activas al salir limpiamente del trabajador y se cargan al inicio.
  • persist_secret — en compilaciones con soporte de instantáneas firmadas, una clave hex que añade autenticación HMAC-SHA256 para que un archivo manipulado sea rechazado.

Por qué 5xx se deja fuera por defecto: un error del servidor es generalmente obra 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.

Aplicarlo — abuse_guard

Válido en bloques http, server y location, así 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 — qué tan 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 los umbrales contra el tráfico en vivo — incluso junto a una ubicación que esté haciendo cumplir en la misma zona — luego actívalo en vivo.

Exemptar 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 basa en la verdadera dirección de conexión, por lo que coopera con realip. Esta es también la forma en que proteges crawlers de búsqueda verificados: permite los rangos publicados de Googlebot / Bingbot para que un bot que recorre URLs obsoletas (y acumulando 404s) nunca sea atrapado.

Compartir 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. 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. Omite esto y la replicación simplemente no hará nada mientras la aplicación local continúe 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 la ruta 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 lo 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 toda la flota un latido más tarde 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 vuelcan cuando el trabajador sale limpiamente, y luego se restauran al inicio. Recargas y reinicios ordenados mantienen las prohibiciones actuales sin ejecutar un escritor de zona completa periódicamente. Un fallo abrupto del proceso o de la máquina puede perder las prohibiciones emitidas desde la última salida limpia; la aplicación aún falla abierta.

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

La instantánea compacta contiene solo resúmenes de identidad y plazos de prohibición. CRC32 detecta corrupción, y un cambio atómico mantiene las escrituras parciales fuera de la ruta activa. Las compilaciones con soporte de instantáneas firmadas pueden además autenticarlo con persist_secret. Mantén el directorio legible solo por el usuario del trabajador.

Ver 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';

¿Teclando detrás de un CDN o proxy? Nunca confíes en un X-Forwarded-For sin procesar. Deja que realip resuelva primero el verdadero cliente, luego utiliza $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 cuya key resuelva a una cadena vacía se ignora — 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 "se compila." Cada cambio pasa por el filtro de AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, análisis estático y fuzzing continuo de sus analizadores y formato en disco. Sus dependencias opcionales — agrupación e 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 a GetPageSpeed.

© GetPageSpeed LLC. Todos los derechos reservados.