Automatiser le ban d'IPs avec Cloudflare WAF, CrowdSec et AbuseIPDB

⚡ En bref
Le monitoring passif ne suffit pas. Ce pipeline automatise la fermeture de la boucle en moins de 5 minutes entre une attaque détectée par Cloudflare WAF et le ban effectif de l’IP dans CrowdSec, sa synchronisation vers Cloudflare et son signalement sur AbuseIPDB. Un script Python poll l’API GraphQL Cloudflare toutes les 5 minutes, applique un seuil de 3 hits, et déclenche le ban avec escalade récidiviste.
🧠 Pourquoi
Voir une attaque dans les logs BetterStack après coup n’empêche pas l’IP malveillante de continuer à frapper. Sans automatisation, la boucle détection → ban prend des heures ou ne se ferme jamais. Les actions WAF Cloudflare (block, challenge, managed_challenge, jschallenge) sont des signaux clairs d’attaque, mais ils restent confinés dans le dashboard Cloudflare — sans pont vers CrowdSec, aucune IP n’est bannie localement, aucune n’est signalée à la communauté AbuseIPDB.
🔧 Ce qui a été fait
Architecture du pipeline
Cloudflare WAF (block / challenge / managed_challenge)
↓ poll toutes les 5 minutes (API GraphQL)
crowdsec-cf-sync.py → seuil : 3 hits / 5 min par IP
↓
CrowdSec (cscli decisions add) → escalade récidivistes
↓
Cloudflare IP Access Rules (ban synchronisé)
↓
AbuseIPDB (report catégories 19 + 21)
↓
BetterStack (log enrichi source crowdsec-decisions)1. Collecte des événements WAF Cloudflare
La fonction poll_cloudflare_waf() interroge l’API GraphQL Cloudflare toutes les 5 minutes et récupère les événements avec les actions suivantes :
blockchallengemanaged_challengejschallenge
Un fichier d’état (cf_waf_state.json) conserve le timestamp du dernier événement traité pour éviter tout doublon entre deux cycles.
2. Détection et seuil
Les événements sont regroupés par IP source. Le ban se déclenche uniquement si une IP cumule 3 hits ou plus dans une fenêtre glissante de 5 minutes. Ce seuil évite les faux positifs liés aux challenges légitimes (bots de monitoring, scanners déclarés comme Palo Alto Xpanse, etc.).
3. Whitelist
La whitelist CrowdSec existante (my_allowlist) est consultée avant tout ban. Elle inclut notamment les IPs des bots de monitoring, les plages Cloudflare et BetterStack. Aucune IP whitelistée ne peut être bannie par ce mécanisme.
4. Escalade des bans (récidivistes)
Le système applique la même logique d’escalade que les autres sources de ban :
| Occurrence | Durée du ban |
|---|---|
| 1er ban | 4 heures |
| 2ème ban | 24 heures |
| 3ème ban et + | 168 heures (7 jours) |
Le compteur de récidive est partagé avec les bans CrowdSec classiques via recidivists.json.
5. Signalement AbuseIPDB
Chaque IP bannie est automatiquement signalée sur AbuseIPDB avec :
- Catégorie 19 : Web Application Attack
- Catégorie 21 : Web App Scan
- Un commentaire incluant le nombre de hits Cloudflare et les URIs ciblées
6. Logging BetterStack
Chaque ban génère une entrée enrichie dans la source crowdsec-decisions avec les champs spécifiques :
{
"source": "cloudflare_waf",
"cf_action": "managed_challenge",
"hit_count": 23,
"uris_targeted": ["/wp.php", "/shell.php", "/backdoor.php"],
"cs_scenario": "cloudflare-waf/23-hits",
"cs_duration": "168h"
}Exemple réel — nuit du 9 avril 2026
Un scan massif de webshells PHP a été détecté et neutralisé automatiquement :
| Champ | Valeur |
|---|---|
| IP source | Azure France |
| Hits détectés | 23 en < 1 minute |
| URIs ciblées | /wp.php, /shell.php, /gpt-sh.php, /wp-content/plugins/hellopress/wp_filemanager.php… |
| Action Cloudflare | managed_challenge (Bot Fight Mode) |
| Ban appliqué | 168h (récidiviste) |
| Score AbuseIPDB | 100% |
| Délai détection → ban | < 5 minutes |
Aucune de ces ressources n’existe sur le serveur (Grav CMS, pas WordPress).
Fichiers et services impliqués
| Composant | Emplacement |
|---|---|
| Script principal | /usr/local/bin/crowdsec-cf-sync.py |
| État WAF | /var/log/crowdsec/cf_waf_state.json |
| Récidivistes | /var/log/crowdsec/recidivists.json |
| Service systemd | crowdsec-cf-sync.service |
| Config Vector | /etc/vector/vector.yaml |
Commandes utiles
# Surveiller les bans WAF en temps réel
journalctl -fu crowdsec-cf-sync | grep -i "waf\|cloudflare"
# Voir les récidivistes
cat /var/log/crowdsec/recidivists.json | python3 -c "
import json,sys
d=json.load(sys.stdin)
for ip,v in sorted(d.items(), key=lambda x: x[1]['count'], reverse=True):
print(f'{ip:20} count={v[\"count\"]} last={v[\"last_seen\"]}')
"
# Voir l'état du dernier poll WAF
cat /var/log/crowdsec/cf_waf_state.json | python3 -m json.tool
# Redémarrer le service
systemctl restart crowdsec-cf-sync🏁 Conclusion
Ce pipeline réduit le délai de réponse à une attaque de plusieurs heures à moins de 5 minutes. Les IPs agressives sont bannies localement, synchronisées vers Cloudflare et signalées à la communauté AbuseIPDB de façon automatique et sans intervention manuelle. L’escalade récidiviste garantit que les attaquants persistants accumulent des bans de plus en plus longs.
Pour aller plus loin :
- 💡 Ajouter une intégration avec VirusTotal pour scorer les IPs avant signalement sur AbuseIPDB
- 💡 Implémenter un tableau de bord BetterStack dédié avec alertes sur les pics de bans WAF