abuse-guard : Bannissement automatique des clients abusifs selon le taux de réponses d'erreur
Installation
Vous pouvez installer ce module sur toute distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et 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
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_abuse_guard_module.so;
Ce document décrit nginx-module-abuse-guard v2.1.0 publié le 03 septembre 2026.
Votre journal d'erreurs est un aveu. Abuse Guard le lit en temps réel et exclut les auteurs d'abus.
Chaque scanner, fuzzer et bot de bourrage d'identifiants laisse la même empreinte :
une rafale de 404 à la recherche de chemins cachés, des 403 qui secouent des portes verrouillées, des requêtes qui échouent les unes après les autres. Abuse Guard surveille les codes de statut que votre serveur renvoie réellement, identifie les clients dont le trafic est majoritairement constitué d'échecs, et les verrouille — la décision est prise à l'intérieur du worker NGINX, sur la requête elle-même, en quelques microsecondes. Pas de sidecar. Pas d'expéditeur de journaux. Pas de couche de script. Juste du C compilé qui fait un travail exceptionnellement bien.
Fiche technique
| Déclencheur | Taux par client de réponses d'erreur que vous choisissez (403/404 par défaut) |
| Action | Verrouillage temporisé — un bannissement ferme pour une fenêtre fixe, pas une limitation |
| Point de décision | Phase de préaccès NGINX, avant tout handler ou upstream |
| Modèle mémoire | Octets fixes par client, indépendants du seuil → échelle botnet |
| Mode flotte | Réplication facultative des bannissements entre nœuds via Redis / Valkey |
| Durabilité | Instantanés de sortie facultatifs préservant les bannissements actifs entre les redémarrages |
| Empreinte | Un module autonome ; zéro dépendance d'exécution par défaut |
| Plateformes | RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux |
| ## |
Le problème qu'il élimine
Les visiteurs légitimes ne génèrent presque jamais une rafale d'erreurs. Les auteurs d'abus ne génèrent guère que cela — cette asymétrie est tout l'enjeu. Un scanner de vulnérabilités qui parcourt votre arborescence est un mur de 404. Un bot qui sonde des points d'administration est un mur de 403. Une attaque par force brute est un mur d'échecs.
Les limiteurs de débit traitent ce trafic comme n'importe quel autre : ils ralentissent tout le monde par volume de requêtes et laissent l'auteur de l'infraction revenir immédiatement dès qu'il se calme. Abuse Guard fait l'inverse. Il ignore entièrement le trafic bien comporté et réserve sa seule réponse — un bannissement réel et limité dans le temps — aux clients définis par leurs erreurs.
Utilisez un limiteur de débit pour façonner la charge. Utilisez Abuse Guard pour expulser les abus.
Comment un bannissement est décidé
Trois éléments mobiles, tous à l'intérieur du worker :
1 · Un score qui fuit, par client. Chaque identité de client porte un seul petit nombre en mémoire partagée. Chaque erreur correspondante ajoute un point par défaut, ou le poids que vous attribuez à ce statut ; le score s'écoule en continu à seuil ÷ intervalle par seconde. Une rafale courte et brutale le fait passer au-dessus de la ligne ; un filet lent ne le fait jamais. Point crucial, ce score est un enregistrement de taille fixe quel que soit le seuil que vous définissez, de sorte qu'une seule zone suit confortablement les dizaines de milliers d'adresses sources distinctes qu'un botnet vous lance.
2 · Une échéance ferme. Au moment où le score franchit votre seuil, le client obtient un horodatage blocked_until. Jusqu'à cette date, il est simplement absent — chaque requête est refusée à la phase de préaccès, avant que NGINX ne dépense un cycle en routage, fichiers ou upstreams. Le rejet est le résultat le moins coûteux possible.
3 · Un refus respectueux de la vie privée. Les clients bannis reçoivent 429 Too Many Requests (le code de votre choix) étiqueté de sorte qu'aucun cache partagé ne puisse jamais le stocker et servir la punition d'un client à un autre, avec un Retry-After indiquant aux clients honnêtes quand revenir.
Les identités sont réduites à un condensé de taille fixe, donc le ciblage sur quelque chose de volumineux comme $request_uri ou un en-tête coûte exactement autant de mémoire que le ciblage sur une adresse IP.
Opérationnel en moins d'une minute
Abuse Guard est fourni comme module précompilé et signé depuis le dépôt GetPageSpeed — installez-le, aucune chaîne d'outils de compilation requise.
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-abuse-guard
Branchez-le :
load_module modules/ngx_http_abuse_guard_module.so;
http {
abuse_guard_zone zone=clients:10m; # une zone de mémoire partagée
server {
location / {
abuse_guard zone=clients; # appliquez ici
}
}
}
sudo nginx -t && sudo systemctl reload nginx
Ces valeurs par défaut bannissent toute adresse IP qui renvoie 100 réponses 403/404 dans une fenêtre de 5 minutes, pendant une heure. Resserrez ou assouplissez chaque nombre ci-dessous.
Configuration
Abuse Guard se compose de quatre directives. La première déclare une politique ; les autres l'appliquent, exemptent des personnes, et (facultativement) la partagent entre machines.
Déclarer une politique — abuse_guard_zone
Une directive de niveau http. Elle découpe une zone de mémoire partagée et définit la politique qui la régit. Définissez autant ou aussi peu de paramètres que vous le souhaitez — le nom et la taille de la zone sont les seules choses obligatoires ; des valeurs par défaut judicieuses comblent le reste (les valeurs ci-dessous sont exactement ces valeurs par défaut).
abuse_guard_zone zone=clients:10m ← nom + taille (le seul obligatoire)
key=$binary_remote_addr ← qui est « un client »
statuses=403,404 ← quelles réponses ajoutent au score
interval=300s ← la fenêtre de notation
threshold=100 ← score dans cette fenêtre → bannissement
block=60m; ← combien de temps le bannissement tient
zone=clients:10m est l'identité et le budget de la politique : un nom que vous référencez depuis abuse_guard, et la taille de la mémoire partagée. Environ 10 Mo suivent de l'ordre d'une centaine de milliers de clients actifs.
Tout le reste est un réglage facultatif :
key— l'expression qui définit un seul client. Toute variable NGINX ; la valeur par défaut$binary_remote_addrcible l'adresse IP source. Une requête dont la clé sort vide est entièrement ignorée (pratique avec unmap, ci-dessous).statuses— les réponses qui ajoutent au score. Un code nu ou une plage a un poids de 1, préservant la syntaxe d'origine :statuses=403,404,500-599. Ajoutez:weightpour qu'une réponse consomme davantage du même budget, par exemplestatuses=404,401:5,500-599:2. Les poids sont des entiers de 1 à 1024 et une plage applique son poids à chaque statut qu'elle couvre. Répéter ou chevaucher un statut avec le même poids est sans danger ; des poids conflictuels font échouernginx -t. La valeur par défaut reste403,404.interval— la fenêtre sur laquelle le score décroît (par défaut300s). Une rafale à l'intérieur déclenche un bannissement ; un filet lent étalé plus largement ne s'accumule jamais.threshold— combien de points de score dans cette fenêtre franchissent la ligne, jusqu'à 1024 (par défaut100). Une réponse lourde peut consommer le budget restant et déclencher un bannissement immédiatement.block— combien de temps un client déclenché reste verrouillé (par défaut60m).inactive— combien de temps un client dormant reste en mémoire avant d'être récupéré (par défautmax(1h, interval, block); toute valeur explicite doit être au moins aussi grande queintervaletblock).redis—onpour répliquer les bannissements de cette zone à travers une flotte (voir ci-dessous) ;offpar défaut.persist— un chemin de fichier où les bannissements actifs sont déchargés à la sortie propre du worker et chargés au démarrage.persist_secret— sur les builds avec prise en charge des instantanés signés, une clé hexadécimale qui ajoute l'authentification HMAC-SHA256 afin qu'un fichier falsifié soit rejeté.
Pourquoi
5xxest exclu par défaut : une erreur serveur est généralement le fait de votre côté, et la compter permettrait à un backend instable de faire bannir des visiteurs innocents. Ajoutezstatuses=403,404,500-599uniquement lorsque vous voulez délibérément agir sur les clients qui déclenchent des erreurs serveur.
L'appliquer — abuse_guard
Valide dans les blocs http, server et location, afin que vous puissiez protéger tout un site ou seulement les points d'accès qui attirent les abus. Nommez la zone pour l'activer ; écrivez abuse_guard off; dans une portée imbriquée pour la désactiver.
location /wp-login.php {
abuse_guard zone=clients status=429 log_level=warn;
}
zone— la zone (déclarée ci-dessus) dont la politique s'applique ici.status— le code qu'un client banni reçoit, n'importe où dans400–599(par défaut429).dry_run—onpour observer sans appliquer : le verdict est journalisé mais aucun bannissement n'est écrit. Désactivé par défaut.log_level— avec quelle intensité journaliser chaque décision :info,notice(par défaut),warnouerror.
Déployez sans crainte avec dry_run=on. Il enregistre chaque bannissement qu'il aurait émis sans toucher à l'état, afin que vous puissiez calibrer les seuils contre le trafic réel — même à côté d'un emplacement d'application sur la même zone — puis passez-le en direct.
Exempter les bons — abuse_guard_allow
Contexte : http · server · location · répétable, hérité vers le bas.
abuse_guard_allow 127.0.0.0/8;
abuse_guard_allow 10.0.0.0/8 192.168.0.0/16;
Les clients listés ne sont jamais comptés ni bannis. La correspondance se fait sur la véritable adresse de connexion, donc elle coopère avec realip. C'est aussi ainsi que vous protégez les robots d'exploration vérifiés : autorisez les plages publiées Googlebot / Bingbot afin qu'un robot qui parcourt des URL obsolètes (et accumule des 404) ne soit jamais attrapé.
Partager les bannissements à travers la flotte — abuse_guard_redis
Contexte : http
abuse_guard_redis host=10.0.0.5 password=… ; # tls://host pour TLS
abuse_guard_zone zone=clients:10m redis=on;
Pointez chaque nœud vers un Redis ou Valkey, activez redis=on, et un bannissement gagné sur n'importe quelle machine se propage à toutes. Valeurs par défaut : port=6379, db=0, prefix=ag_, timeout=100ms. Comment cela reste rapide est expliqué dans la section suivante.
SELinux : sur les systèmes d'application (RHEL, Rocky, AlmaLinux), le noyau empêche NGINX d'ouvrir la connexion à Redis jusqu'à ce que vous l'autorisiez une fois — setsebool -P httpd_can_network_connect 1. Si vous sautez cette étape, la réplication ne fait silencieusement rien pendant que l'application locale continue normalement.
Un bannissement, chaque nœud — sans ralentir une seule requête
Derrière un équilibreur de charge, un bannissement par serveur est du théâtre : l'attaquant atterrit simplement sur un autre nœud. Abuse Guard comble cette lacune sans jamais mettre Redis dans le chemin des requêtes.
Chaque nœud décide localement et compte localement. Dès qu'il émet un bannissement, il diffuse ce seul fait au cluster et enregistre une copie durable. Chaque autre nœud l'importe en quelques millisecondes, et tout nœud qui était hors ligne se réconcilie au moment de sa reconnexion. Parce que l'application est toujours servie depuis l'état mémoire de chaque nœud, la requête d'un visiteur n'attend jamais un aller-retour réseau — le seul coût du regroupement est qu'un attaquant fraîchement banni est exclu à l'échelle de la flotte un battement de cœur plus tard au lieu d'instantanément.
Redis ici est une cloche d'alarme unidirectionnelle, pas un registre partagé consulté par requête — donc un Redis lent ou manquant ne peut jamais ajouter de latence à votre trafic. Exécutez-le sur un réseau privé et traitez-le comme privilégié : tout ce qui peut y écrire peut émettre des bannissements.
Des bannissements qui survivent à un redémarrage
Pointez une zone vers un fichier et les bannissements actifs sont déchargés lorsque le worker se termine proprement, puis restaurés au démarrage. Les rechargements et les redémarrages ordonnés conservent les bannissements actuels sans exécuter un rédacteur périodique de zone complète. Une panne brutale de processus ou de machine peut perdre les bannissements émis depuis la dernière sortie propre ; l'application échoue toujours ouvertement.
abuse_guard_zone zone=clients:10m
persist=/var/lib/nginx/abuse_guard/clients.state
persist_secret=00112233445566778899aabbccddeeff;
L'instantané compact ne contient que des condensés d'identité et des échéances de bannissement. CRC32 détecte la corruption, et un renommage atomique maintient les écritures partielles hors du chemin actif. Les builds avec prise en charge des instantanés signés peuvent en outre l'authentifier avec persist_secret. Gardez le répertoire lisible uniquement par l'utilisateur du worker.
Voir tout ce qu'il décide
Trois variables exposent le verdict d'Abuse Guard à vos journaux et à votre configuration :
| Variable | Valeur |
|---|---|
$abuse_guard_status |
BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN |
$abuse_guard_count |
Score pondéré actuel, arrondi à un point entier. |
$abuse_guard_blocked_until |
Heure Unix à laquelle le bannissement est levé, ou 0. |
log_format guard '$remote_addr "$request" $status '
'guard=$abuse_guard_status count=$abuse_guard_count';
Ciblage derrière un CDN ou un proxy ? Ne faites jamais confiance à un X-Forwarded-For brut. Laissez realip résoudre le vrai client d'abord, puis ciblez sur $binary_remote_addr :
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Besoin d'une logique d'exemption par requête ? Toute requête dont la key se résout en une chaîne vide est ignorée — donc un map vous permet, par exemple, de suivre les visiteurs anonymes par IP tout en laissant les utilisateurs authentifiés intacts.
Conçu pour être digne de confiance en production
Abuse Guard est tenu à une norme bien supérieure à « ça compile ». Chaque modification passe par le parcours du combattant d'AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, l'analyse statique et le fuzzing continu de ses analyseurs et de son format sur disque. Ses dépendances facultatives — regroupement et instantanés signés — sont au mieux par conception : si Redis ou le disque se comporte mal, l'application continue tranquillement depuis la mémoire locale. Votre trafic n'est jamais pris en otage par une dépendance.
Obtenir Abuse Guard
Abuse Guard est un module NGINX commercial de GetPageSpeed LLC, livré avec des mises à jour continues et un support via un abonnement GetPageSpeed.
- Parcourez le catalogue complet des modules NGINX → https://nginx-extras.getpagespeed.com/modules/
- Licences, déploiements volumineux ou aide à la configuration → getpagespeed.com/contact-us
© GetPageSpeed LLC. Tous droits réservés.