Zum Inhalt

abuse-guard: Automatisches Sperren missbräuchlicher Clients anhand der Fehlerantwortrate

Installation

Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:

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

Aktivieren Sie das Modul, indem Sie Folgendes am Anfang von /etc/nginx/nginx.conf hinzufügen:

load_module modules/ngx_http_abuse_guard_module.so;

Dieses Dokument beschreibt nginx-module-abuse-guard v2.1.0, veröffentlicht am 03. September 2026.


Ihr Fehlerprotokoll ist ein Geständnis. Abuse Guard liest es in Echtzeit und sperrt Missbraucher aus.

Jeder Scanner, Fuzzer und Credential-Stuffing-Bot hinterlässt denselben Fingerabdruck: eine Salve von 404s auf der Suche nach versteckten Pfaden, 403s, die an verschlossenen Türen rütteln, fehlgeschlagene Anfrage um fehlgeschlagene Anfrage. Abuse Guard beobachtet die Statuscodes, die Ihr Server tatsächlich zurückgibt, identifiziert die Clients, deren Datenverkehr überwiegend aus Fehlern besteht, und sperrt sie aus — entschieden innerhalb des NGINX-Workers, bei der Anfrage selbst, in wenigen Mikrosekunden. Kein Sidecar. Kein Log-Shipper. Keine Skriptebene. Nur kompiliertes C, das eine Aufgabe außergewöhnlich gut erledigt.

Technische Daten

Auslöser Fehlerantwortrate pro Client Ihrer Wahl (standardmäßig 403/404)
Aktion Zeitlich begrenzte Sperre — ein harter Bann für ein festes Zeitfenster, keine Drosselung
Entscheidungspunkt NGINX-Preaccess-Phase, bevor ein Handler oder Upstream ausgeführt wird
Speichermodell Feste Bytes pro Client, unabhängig vom Schwellenwert → Botnetz-tauglich
Fleet-Modus Optionale Bann-Replikation über Knoten hinweg via Redis / Valkey
Dauerhaftigkeit Optionale Exit-Snapshots erhalten aktive Sperren über Neustarts hinweg
Ressourcenverbrauch Ein eigenständiges Modul; standardmäßig null Laufzeitabhängigkeiten
Plattformen RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux
##

Das Problem, das es beseitigt

Legitime Besucher erzeugen fast nie einen Ausbruch von Fehlern. Missbraucher erzeugen kaum etwas anderes — diese Asymmetrie ist das ganze Spiel. Ein Schwachstellenscanner, der Ihren Verzeichnisbaum durchläuft, ist eine Wand aus 404s. Ein Bot, der Admin-Endpunkte abklopft, ist eine Wand aus 403s. Ein Brute-Force-Lauf ist eine Wand aus Fehlern.

Ratenbegrenzer behandeln diesen Datenverkehr wie jeden anderen: Sie verlangsamen alle nach Anfragevolumen und lassen den Übeltäter sofort wieder herein, sobald er nachlässt. Abuse Guard macht das Gegenteil. Es ignoriert wohlverhaltenen Datenverkehr vollständig und reserviert seine eine Antwort — einen echten, zeitlich begrenzten Bann — für Clients, die durch ihre Fehler definiert sind.

Verwenden Sie einen Ratenbegrenzer, um Last zu formen. Verwenden Sie Abuse Guard, um Missbrauch zu entfernen.

Wie eine Sperre entschieden wird

Drei bewegliche Teile, alle innerhalb des Workers:

1 · Ein Leaky-Bucket-Score pro Client. Jede Client-Identität trägt eine einzelne kleine Zahl im gemeinsamen Speicher. Jeder passende Fehler fügt standardmäßig einen Punkt hinzu, oder das Gewicht, das Sie diesem Status zuweisen; der Score sickert kontinuierlich mit threshold ÷ interval pro Sekunde ab. Ein kurzer, scharfer Ausbruch treibt ihn über die Grenze; ein langsames Tröpfeln niemals. Entscheidend ist, dass dieser Score ein Datensatz fester Größe ist, egal wie hoch Sie den Schwellenwert setzen, sodass eine einzelne Zone die Zehntausende verschiedener Quelladressen, die ein Botnetz auf Sie wirft, problemlos verfolgt.

2 · Eine harte Frist. In dem Moment, in dem der Score Ihren Schwellenwert überschreitet, erhält der Client einen blocked_until-Zeitstempel. Bis dahin ist er einfach weg — jede Anfrage wird in der Preaccess-Phase abgewiesen, bevor NGINX einen Zyklus für Routing, Dateien oder Upstreams aufwendet. Die Ablehnung ist das billigste mögliche Ergebnis.

3 · Eine datenschutzkorrekte Verweigerung. Gebannte Clients erhalten 429 Too Many Requests (Code Ihrer Wahl), gekennzeichnet, sodass kein gemeinsamer Cache es speichern und die Bestrafung eines Clients einem anderen ausliefern kann, mit einem Retry-After, der ehrlichen Clients mitteilt, wann sie zurückkehren sollen.

Identitäten werden in einen Digest fester Größe gefaltet, sodass die Schlüsselung auf etwas Großem wie $request_uri oder einem Header genau so viel Speicher kostet wie die Schlüsselung auf einer IP.

In unter einer Minute live

Abuse Guard wird als vorkompiliertes, signiertes Modul aus dem GetPageSpeed-Repository geliefert — einfügen, keine Build-Toolchain erforderlich.

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

Verdrahten Sie es:

load_module modules/ngx_http_abuse_guard_module.so;

http {
    abuse_guard_zone zone=clients:10m;     # eine Shared-Memory-Zone

    server {
        location / {
            abuse_guard zone=clients;      # hier durchsetzen
        }
    }
}
sudo nginx -t && sudo systemctl reload nginx

Diese Standardeinstellungen sperren jede IP, die 100 403/404-Antworten innerhalb eines 5-Minuten-Fensters zurückgibt, für eine Stunde. Sie können jede der folgenden Zahlen anpassen oder lockern.

Konfiguration

Abuse Guard besteht aus vier Direktiven. Die erste deklariert eine Richtlinie; die übrigen wenden sie an, befreien Personen von ihr und teilen sie (optional) maschinenübergreifend.

Eine Richtlinie deklarieren — abuse_guard_zone

Eine Direktive auf http-Ebene. Sie grenzt eine Shared-Memory-Zone ab und legt die Richtlinie fest, die sie regiert. Stellen Sie so viele oder wenige Regler ein, wie Sie möchten — Name und Größe der Zone sind das Einzige, was Sie angeben müssen; sinnvolle Standardwerte füllen den Rest aus (die unten gezeigten Werte sind genau diese Standardwerte).

abuse_guard_zone  zone=clients:10m             Name + Größe (das einzige Muss)
                  key=$binary_remote_addr      wer ist "ein Client"
                  statuses=403,404             welche Antworten zum Score beitragen
                  interval=300s                das Bewertungsfenster
                  threshold=100                Score in diesem Fenster  Bann
                  block=60m;                   wie lange der Bann gilt

zone=clients:10m ist die Identität und das Budget der Richtlinie: ein Name, auf den Sie von abuse_guard verweisen, und die Shared-Memory-Größe. Etwa 10 MB verfolgen in der Größenordnung von hunderttausend aktiven Clients.

Alles andere ist optionale Feinabstimmung:

  • key — der Ausdruck, der einen einzelnen Client definiert. Jede NGINX-Variable; der Standardwert $binary_remote_addr schlüsselt auf der Quell-IP auf. Eine Anfrage, deren Schlüssel leer ausgegeben wird, wird vollständig übersprungen (praktisch mit einer map, weiter unten).
  • statuses — die Antworten, die zum Score beitragen. Ein bloßer Code oder Bereich hat Gewicht 1, wobei die ursprüngliche Syntax erhalten bleibt: statuses=403,404,500-599. Fügen Sie :weight hinzu, um eine Antwort mehr von demselben Budget verbrauchen zu lassen, z. B. statuses=404,401:5,500-599:2. Gewichte sind ganze Zahlen von 1 bis 1024, und ein Bereich wendet sein Gewicht auf jeden Status an, den er abdeckt. Das Wiederholen oder Überlappen eines Status mit demselben Gewicht ist harmlos; widersprüchliche Gewichte führen zu einem Fehler bei nginx -t. Der Standardwert bleibt 403,404.
  • interval — das Fenster, über das der Score abklingt (Standardwert 300s). Ein Ausbruch innerhalb davon löst einen Bann aus; ein langsames Tröpfchen, das sich weiter verteilt, akkumuliert nie.
  • threshold — wie viele Score-Punkte innerhalb dieses Fensters die Grenze überschreiten, bis zu 1024 (Standardwert 100). Eine schwere Antwort kann das verbleibende Budget verbrauchen und sofort einen Bann auslösen.
  • block — wie lange ein ausgelöster Client gesperrt bleibt (Standardwert 60m).
  • inactive — wie lange ein ruhender Client im Speicher verbleibt, bevor er freigegeben wird (Standardwert max(1h, interval, block); jeder explizite Wert muss mindestens so groß sein wie sowohl interval als auch block).
  • redison, um die Sperren dieser Zone über einen Fleet hinweg zu replizieren (siehe unten); standardmäßig off.
  • persist — ein Dateipfad, in den aktive Sperren beim sauberen Worker-Exit geschrieben und beim Start geladen werden.
  • persist_secret — bei Builds mit Unterstützung für signierte Snapshots ein Hex-Schlüssel, der HMAC-SHA256-Authentifizierung hinzufügt, sodass eine manipulierte Datei abgelehnt wird.

Warum 5xx standardmäßig weggelassen wird: Ein Serverfehler ist normalerweise Ihre Seite, und das Zählen würde es einem fehlerhaften Backend ermöglichen, unschuldige Besucher sperren zu lassen. Fügen Sie statuses=403,404,500-599 nur hinzu, wenn Sie bewusst auf Clients reagieren möchten, die Serverfehler auslösen.

Anwenden — abuse_guard

Gültig in http-, server- und location-Blöcken, sodass Sie eine ganze Website oder nur die Endpunkte schützen können, die Missbrauch anziehen. Benennen Sie die Zone, um sie zu aktivieren; schreiben Sie abuse_guard off; in einen verschachtelten Gültigkeitsbereich, um sie wieder zu deaktivieren.

location /wp-login.php {
    abuse_guard zone=clients status=429 log_level=warn;
}
  • zone — die Zone (oben deklariert), deren Richtlinie hier gilt.
  • status — der Code, den ein gebannter Client erhält, irgendwo in 400599 (Standardwert 429).
  • dry_runon zum Beobachten ohne Durchsetzung: Das Urteil wird protokolliert, aber kein Bann geschrieben. Standardmäßig aus.
  • log_level — wie laut jede Entscheidung protokolliert wird: info, notice (Standardwert), warn oder error.

Furchtlos mit dry_run=on ausrollen. Es zeichnet jeden Bann auf, den es aussprechen würde, ohne den Zustand zu verändern, sodass Sie Schwellenwerte gegen Live-Datenverkehr kalibrieren können — sogar neben einem durchsetzenden Standort in derselben Zone — und dann live schalten.

Die Guten ausnehmen — abuse_guard_allow

Kontext: http · server · location · wiederholbar, nach unten vererbt.

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

Aufgeführte Clients werden nie gezählt und nie gesperrt. Der Abgleich erfolgt auf der tatsächlichen Verbindungsadresse, sodass es mit realip zusammenarbeitet. So schützen Sie auch verifizierte Such-Crawler: Erlauben Sie die veröffentlichten Googlebot-/Bingbot-Bereiche, damit ein Bot, der sich durch veraltete URLs arbeitet (und 404s anhäuft), nie erwischt wird.

Sperren über den Fleet teilen — abuse_guard_redis

Kontext: http

abuse_guard_redis host=10.0.0.5 password=… ;   # tls://host für TLS
abuse_guard_zone  zone=clients:10m redis=on;

Richten Sie jeden Knoten auf eine Redis- oder Valkey-Instanz aus, schalten Sie redis=on um, und ein auf einer Maschine verdienter Bann verbreitet sich auf alle. Standardwerte: port=6379, db=0, prefix=ag_, timeout=100ms. Wie es schnell bleibt, wird im nächsten Abschnitt erklärt.

SELinux: Auf Systemen mit erzwungenem SELinux (RHEL, Rocky, AlmaLinux) blockiert der Kernel NGINX daran, die Verbindung zu Redis zu öffnen, bis Sie es einmal erlauben — setsebool -P httpd_can_network_connect 1. Überspringen Sie dies, und die Replikation tut stillschweigend nichts, während die lokale Durchsetzung normal weiterläuft.

Eine Sperre, jeder Knoten — ohne einen einzigen Request zu verlangsamen

Hinter einem Load-Balancer ist eine Pro-Server-Sperre Theater: Der Angreifer landet einfach auf einem anderen Knoten. Abuse Guard schließt diese Lücke, ohne Redis jemals in den Request-Pfad zu legen.

Jeder Knoten entscheidet lokal und zählt lokal. In dem Moment, in dem er eine Sperre ausgibt, sendet er diese eine Tatsache an den Cluster und zeichnet eine dauerhafte Kopie auf. Jeder andere Knoten importiert sie innerhalb von Millisekunden, und jeder Knoten, der offline war, gleicht sich in dem Moment ab, in dem er sich wieder verbindet. Da die Durchsetzung immer aus dem eigenen In-Memory-Zustand jedes Knotens bedient wird, wartet die Anfrage eines Besuchers nie auf eine Netzwerk-Round-Trip — die einzigen Kosten der Clusterung bestehen darin, dass ein frisch gebannter Angreifer einen Herzschlag später statt sofort fleetweit ausgesperrt wird.

Redis ist hier eine Einbahn-Alarmglocke, kein gemeinsames Hauptbuch, das pro Anfrage konsultiert wird — ein langsames oder fehlendes Redis kann Ihrem Datenverkehr also niemals Latenz hinzufügen. Betreiben Sie es in einem privaten Netzwerk und behandeln Sie es als privilegiert: Alles, was hineinschreiben kann, kann Sperren ausgeben.

Sperren, die einen Neustart überleben

Zeigen Sie mit einer Zone auf eine Datei, und aktive Sperren werden beim sauberen Worker-Exit gespeichert und beim Start wiederhergestellt. Reloads und geordnete Neustarts behalten aktuelle Sperren, ohne einen periodischen Ganzzonen-Schreiber auszuführen. Ein abruptes Prozess- oder Maschinenversagen kann seit dem letzten sauberen Exit ausgegebene Sperren verlieren; die Durchsetzung schlägt weiterhin offen fehl.

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

Der kompakte Snapshot enthält nur Identitäts-Digests und Sperrfristen. CRC32 erkennt Beschädigungen, und eine atomare Umbenennung hält partielle Schreibvorgänge aus dem Live-Pfad heraus. Builds mit Unterstützung für signierte Snapshots können es zusätzlich mit persist_secret authentifizieren. Halten Sie das Verzeichnis nur für den Worker-Benutzer lesbar.

Alles sehen, was es entscheidet

Drei Variablen legen das Urteil von Abuse Guard für Ihre Protokolle und Konfiguration offen:

Variable Wert
$abuse_guard_status BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN
$abuse_guard_count Aktueller gewichteter Score, auf einen ganzen Punkt gerundet.
$abuse_guard_blocked_until Unix-Zeit, zu der die Sperre aufgehoben wird, oder 0.
log_format guard '$remote_addr "$request" $status '
                 'guard=$abuse_guard_status count=$abuse_guard_count';

Schlüsselung hinter einem CDN oder Proxy? Vertrauen Sie niemals einem rohen X-Forwarded-For. Lassen Sie realip zuerst den echten Client auflösen und schlüsseln Sie dann auf $binary_remote_addr:

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

Benötigen Sie eine Pro-Request-Ausnahmelogik? Jede Anfrage, deren key zu einer leeren Zeichenfolge aufgelöst wird, wird ignoriert — eine map ermöglicht es Ihnen also beispielsweise, anonyme Besucher per IP zu verfolgen, während authentifizierte Benutzer unberührt bleiben.

Entwickelt, um in der Produktion vertrauenswürdig zu sein

Abuse Guard wird an einem Standard gemessen, der weit über „es kompiliert" hinausgeht. Jede Änderung durchläuft das Spießrutenlaufen von AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, statischer Analyse und kontinuierlichem Fuzzing seiner Parser und des On-Disk-Formats. Seine optionalen Abhängigkeiten — Clusterung und signierte Snapshots — sind bewusst Best-Effort: Wenn Redis oder die Festplatte sich fehlverhalten, führt die Durchsetzung ruhig aus dem lokalen Speicher fort. Ihr Datenverkehr wird nie von einer Abhängigkeit als Geisel gehalten.

Abuse Guard erhalten

Abuse Guard ist ein kommerzielles NGINX-Modul von GetPageSpeed LLC, geliefert mit fortlaufenden Updates und Support durch ein GetPageSpeed-Abonnement.

© GetPageSpeed LLC. Alle Rechte vorbehalten.