Konfiguration
Der Daemon wird vollständig über Umgebungsvariablen und zwei On-Disk-Dateien konfiguriert. Keine Code-Änderung nötig, um das Verhalten zu justieren.
Umgebungsvariablen
| Variable | Typ | Default | Zweck |
|---|---|---|---|
ABUSIVE_FAMILY | v4 / v6 / any | any | Matching auf eine IP-Familie beschränken. |
ABUSIVE_MIN_HITS | Integer ≥ 1 | 3 | Hits von einer Quelle, bevor die IP in die Blocklist geschrieben wird. |
ABUSIVE_SCOPE | Komma-Liste | request,ua | Welche Log-Felder ausgewertet werden. Gültig: request, ua, referrer. |
ABUSIVE_REFERRER_DOMAINS | Whitespace/Komma-Liste | (leer) | Erlaubte Referrer-Hosts. Nur relevant, wenn referrer in ABUSIVE_SCOPE. |
ABUSIVE_SYSLOG_TAG | String | abusive_http_watch | Syslog-Program-Tag. |
ABUSIVE_SYSLOG_FACILITY | String | daemon | Syslog-Facility. local0–local7 für eigene Routings. |
ABUSIVE_SYSLOG_PRIO | info / notice / warn / err | notice | Syslog-Priorität für added-Events. |
ABUSIVE_DEBUG | 0 / 1 | 0 | Verbose-stderr-Trace jeder Zeile. Nur für Scoping sinnvoll. |
Anmerkungen
ABUSIVE_MIN_HITS— Auf1setzen blockt beim ersten Hit. Aggressiver, aber erhöht das False-Positive-Risiko durch One-Shot-Probes von benign Cloud-IPs, die später regulär aufschlagen. Default3ist ein guter Kompromiss.ABUSIVE_SCOPE—referrerist per Default aus, weil ein bösartiger Referrer per Drive-by die IP eines deiner Besucher in die Blocklist befördern könnte. Nur aktivieren, wenn auchABUSIVE_REFERRER_DOMAINSals strikte Allowlist gesetzt ist.ABUSIVE_FAMILY— Nützlich, wenn man den Daemon über zwei Prozesse spiegeln will: einer für IPv4, einer für IPv6, jeder mit eigener Blocklist-Datei.
Token-Set
Das Erkennungs-Regex-Set ist im Skript fest verdrahtet (@TOKENS)
und deckt acht Angriffsklassen ab — PHP-Exploitation,
WordPress-Probes, Path-Traversal, sensible Pfade, RCE/CGI-Versuche,
SQL-Injection, Login-Loop-Probes und Null-Byte-Injection.
Zum Anpassen des Sets:
- Skript öffnen.
- Das
@TOKENS-Array justieren — Patterns hinzufügen oder entfernen, falls False Positives auftreten. - Daemon neu starten.
Das Set ist absichtlich konservativ. Tokens wie /admin, /login
oder phpmyadmin ohne Scoping hinzuzufügen führt zu False
Positives auf legitimen Traffic.
Whitelist-Datei
Pfad: /etc/abusive_http_whitelist
Ein Eintrag pro Zeile. Drei Formate werden unterstützt:
# Kommentare erlaubt
203.0.113.42 # einzelne IPv4
2001:db8::abcd # einzelne IPv6 (voll oder verkürzt)
203.0.113.0/24 # IPv4 CIDR
2001:db8::/32 # IPv6 CIDRWhitelisted-IPs werden vollständig übersprungen — sie erhöhen keinen Hit-Counter und landen nie in der Blocklist, selbst wenn ihre Requests jedes Token im Set treffen.
Verwende die Whitelist für:
- Öffentliche Office- und VPN-IPs (Operatoren, die versehentlich Scanner auslösen).
- Such-Maschinen-Crawler-IP-Ranges, die dokumentiert legitim sind (Google, Bing). Vorher testen — selten nötig, weil deren Requests keine Angriffs-Token treffen.
- Monitoring-Dienste, die absichtlich
/wp-login.phpabfragen.
Blocklist-Datei
Pfad: /var/www/run/abusive_http_hosts
Format: eine IP pro Zeile, keine Kommentare, keine Header, keine
Duplikate. Der Daemon stellt Deduplizierung über einen
In-Memory-Hash und flock(LOCK_EX) beim Schreiben sicher.
Die Datei ist zur Laufzeit append-only — alte Einträge werden vom Daemon nie entfernt. Zum Aufräumen (z. B. Einträge nach 30 Tagen ablaufen lassen) externe Rotation verwenden:
# In einem Tages-Cron
mv /var/www/run/abusive_http_hosts /var/www/run/abusive_http_hosts.old
touch /var/www/run/abusive_http_hosts
chown _www:_www /var/www/run/abusive_http_hosts
doas rcctl restart abusive_http_watchDas zwingt den Daemon, seinen In-Memory-State aus einer leeren Datei neu aufzubauen. Die Firewall lädt die neue (leere) Blocklist beim nächsten Cron-Tick.
Firewall-Konsumption
Das Blocklist-Dateiformat ist absichtlich flach, damit jede Schicht es konsumieren kann. Gängige Integrationen:
OpenBSD pf
table <abusive> persist file "/var/www/run/abusive_http_hosts"
block in quick on egress from <abusive>Tabelle neu laden:
pfctl -t abusive -T replace -f /var/www/run/abusive_http_hostsLinux nftables
table inet filter {
set abusive_v4 {
type ipv4_addr
elements = { ... }
}
chain input {
ip saddr @abusive_v4 drop
}
}Set per Helper aus Datei neu laden:
nft 'flush set inet filter abusive_v4'
awk '/^[0-9]/ {print}' /var/www/run/abusive_http_hosts | \
xargs -I{} nft 'add element inet filter abusive_v4 { {} }'Apache
<RequireAll>
Require all granted
Require not ip 203.0.113.0/24
# … ein Require not ip pro Blocklist-Eintrag
</RequireAll>Per Templater (m4, sed) aus der Blocklist-Datei auf einem Cron
generiert. Reagiert langsamer als die Firewall-Integration,
funktioniert aber, wenn du die Firewall-Schicht nicht selbst
kontrollierst.
nginx
geo $abusive {
default 0;
include /var/www/run/abusive_http_nginx.conf;
}
server {
if ($abusive) { return 444; }
}abusive_http_nginx.conf wird per Template aus der Blocklist-Datei
generiert.