Le daemon se configure entièrement via des variables d’environnement et deux fichiers sur disque. Aucune modification de code requise pour ajuster le comportement.

Variables d’environnement

VariableTypeDéfautBut
ABUSIVE_FAMILYv4 / v6 / anyanyRestreindre le matching à une famille d’IP.
ABUSIVE_MIN_HITSentier ≥ 13Hits d’une source avant que l’IP ne soit écrite dans la blocklist.
ABUSIVE_SCOPEliste virguléerequest,uaChamps de log à évaluer. Valides : request, ua, referrer.
ABUSIVE_REFERRER_DOMAINSliste virgulée / espaces(vide)Hosts referrer autorisés. Pertinent seulement si referrer est dans ABUSIVE_SCOPE.
ABUSIVE_SYSLOG_TAGstringabusive_http_watchTag programme syslog.
ABUSIVE_SYSLOG_FACILITYstringdaemonFacility syslog. local0local7 pour des routings personnalisés.
ABUSIVE_SYSLOG_PRIOinfo / notice / warn / errnoticePriorité syslog pour les événements added.
ABUSIVE_DEBUG0 / 10Trace stderr verbeuse de chaque ligne. Utile uniquement au scoping.

Notes

  • ABUSIVE_MIN_HITS — Mettre à 1 bloque au premier hit. Plus agressif mais augmente le risque de faux positifs depuis des probes one-shot venant ensuite d’une IP cloud bénigne. Le défaut 3 est un bon compromis.
  • ABUSIVE_SCOPEreferrer est désactivé par défaut car un referrer malveillant peut, par drive-by, faire entrer l’IP d’un visiteur dans la blocklist. À n’activer que si ABUSIVE_REFERRER_DOMAINS est aussi en allowlist stricte.
  • ABUSIVE_FAMILY — Utile si on veut faire tourner deux daemons en parallèle : un pour IPv4, un pour IPv6, chacun avec sa propre blocklist.

Jeu de tokens

Le jeu de regex de détection est codé en dur dans le script (@TOKENS) et couvre huit classes d’attaque — exploitation PHP, probes WordPress, path traversal, chemins sensibles, tentatives RCE/CGI, injection SQL, probes de boucle de login, injection null-byte.

Pour ajuster :

  1. Ouvrir le script.
  2. Ajuster le tableau @TOKENS — ajouter des patterns, retirer ceux qui font des faux positifs dans votre environnement.
  3. Redémarrer le daemon.

Le jeu est délibérément conservateur. Ajouter des tokens comme /admin, /login ou phpmyadmin sans scoping cause des faux positifs sur du trafic légitime.

Fichier whitelist

Chemin : /etc/abusive_http_whitelist

Une entrée par ligne. Trois formats supportés :

# Commentaires autorisés
203.0.113.42                    # IPv4 unique
2001:db8::abcd                  # IPv6 unique (complet ou compact)
203.0.113.0/24                  # CIDR IPv4
2001:db8::/32                   # CIDR IPv6

Les IP whitelistées sont totalement ignorées — elles n’incrémentent aucun compteur et n’entrent jamais dans la blocklist, même si leur requête correspond à tous les tokens.

Utiliser la whitelist pour :

  • IP publiques du bureau et du VPN (opérateurs déclenchant des scanners par accident).
  • Plages d’IP de crawlers de moteurs de recherche documentées comme légitimes (Google, Bing). Tester avant — rarement nécessaire car leurs requêtes ne déclenchent pas les tokens.
  • Services de monitoring qui sondent volontairement /wp-login.php.

Fichier blocklist

Chemin : /var/www/run/abusive_http_hosts

Format : une IP par ligne, pas de commentaire, pas d’en-tête, pas de doublon. Le daemon assure la déduplication via une table en mémoire et flock(LOCK_EX) à l’écriture.

Le fichier est append-only à l’exécution — les anciennes entrées ne sont jamais supprimées par le daemon. Pour purger (par ex. expirer après 30 jours), utiliser une rotation externe :

# Dans un cron quotidien
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_watch

Cela force le daemon à reconstruire sa table en mémoire à partir d’un fichier vide. Le pare-feu rechargera la nouvelle blocklist (vide) au prochain cron.

Consommation par le pare-feu

Le format du fichier est intentionnellement plat afin que n’importe quelle couche puisse le consommer. Intégrations courantes :

OpenBSD pf

table <abusive> persist file "/var/www/run/abusive_http_hosts"
block in quick on egress from <abusive>

Rechargement de la table :

pfctl -t abusive -T replace -f /var/www/run/abusive_http_hosts

Linux nftables

table inet filter {
  set abusive_v4 {
    type ipv4_addr
    elements = { ... }
  }
  chain input {
    ip saddr @abusive_v4 drop
  }
}

Rechargement depuis fichier via un helper :

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
  # … un Require not ip par entrée de blocklist
</RequireAll>

Généré par un templater (m4, sed) depuis le fichier blocklist sur un cron. Plus lent à réagir que l’intégration pare-feu, mais fonctionne quand vous ne possédez pas la couche pare-feu.

nginx

geo $abusive {
  default 0;
  include /var/www/run/abusive_http_nginx.conf;
}
server {
  if ($abusive) { return 444; }
}

abusive_http_nginx.conf est généré par template depuis le fichier blocklist.