Cybersécurité

Configurer bouncers CrowdSec Caddy et Nginx : tutoriel 2026

12 دقائق للقراءة

📍 Article principal de la série : CrowdSec 2026 : guide pratique.

Bloquer une IP au niveau iptables est efficace mais brutal. Au niveau HTTP via Caddy ou Nginx, on peut afficher un captcha, throttle, ou rediriger. Ce tutoriel détaille la configuration des bouncers HTTP pour les deux reverse proxies les plus utilisés.

Prérequis

  • CrowdSec installé sur le VPS (voir tutoriel installation).
  • Caddy 2 ou Nginx 1.18+ en façade.
  • Niveau attendu : intermédiaire.
  • Temps estimé : 30-45 minutes.

Bouncer Caddy

Étape 1 — Installer le bouncer Caddy

apt install -y crowdsec-caddy-bouncer

Pour Caddy compilé custom : xcaddy build --with github.com/hslatman/caddy-crowdsec-bouncer.

Étape 2 — Générer une API key bouncer

cscli bouncers add caddy-bouncer
# Note la clé retournée, par exemple ABC123XYZ

Étape 3 — Configuration Caddyfile

{
  order crowdsec first
  crowdsec {
    api_url http://127.0.0.1:8080
    api_key ABC123XYZ
    ticker_interval 15s
    appsec_url http://127.0.0.1:7422  # optionnel pour AppSec
  }
}

vault.votre-entreprise.com {
  crowdsec
  reverse_proxy vaultwarden:80
}

wiki.votre-entreprise.com {
  crowdsec
  reverse_proxy outline:3000
}

Étape 4 — Recharger Caddy

caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy

Étape 5 — Test bouncer Caddy

# Bannir une IP de test
cscli decisions add --ip 1.2.3.4 --duration 1h --type ban

# Tester (depuis 1.2.3.4 ou simulant)
curl -H "X-Forwarded-For: 1.2.3.4" https://vault.votre-entreprise.com
# Doit retourner 403 Forbidden

Bouncer Nginx

Étape 1 — Installer le bouncer Nginx

apt install -y crowdsec-nginx-bouncer

Le bouncer s’installe via module Lua nginx-mod-luajit (auto via apt).

Étape 2 — Générer une API key

cscli bouncers add nginx-bouncer
# Note la clé

Étape 3 — Configuration /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf

API_URL=http://127.0.0.1:8080
API_KEY=YOUR_KEY
SECURE=false
LOG_FILE=/var/log/crowdsec-nginx-bouncer.log
UPDATE_FREQUENCY=10
DEFAULT_REMEDIATION=ban
TEMPLATE_DIR=/var/lib/crowdsec/lua/templates/

Étape 4 — Vérifier nginx.conf

Le bouncer ajoute automatiquement access_by_lua_file dans le main http block. Vérifier :

nginx -t
systemctl reload nginx

Captcha au lieu de ban

Pour ne pas bannir totalement (cas de sites e-commerce où des clients légitimes peuvent être faux positifs), utiliser captcha :

# Configuration profile
nano /etc/crowdsec/profiles.yaml
name: captcha_remediation
filters:
  - Alert.Remediation == true && Alert.GetScenario() contains "http"
decisions:
  - type: captcha
    duration: 4h
notifications:
  - http_default
on_success: continue

Recharger : systemctl reload crowdsec.

AppSec : protection L7 avancée

CrowdSec AppSec (CrowdSec 1.6+) fournit un WAF style ModSecurity. Détecte SQLi, XSS, path traversal au niveau requête.

cscli collections install crowdsecurity/appsec-virtual-patching
cscli collections install crowdsecurity/appsec-generic-rules

# Ajouter dans Caddyfile
crowdsec {
  appsec_url http://127.0.0.1:7422
}

Erreurs fréquentes

Erreur Cause Solution
Bouncer Caddy 401 API key incorrecte Régénérer + update Caddyfile
Captcha boucle Cookie session pas conservé Verify Caddy session config
Lua error nginx Module Lua manquant apt install nginx-mod-luajit
Real IP via CDN faux X-Forwarded-For ignoré Trust proxy via real_ip_header
AppSec faux positifs Règles trop strictes Tuner whitelist AppSec
Performance dégradée Trop de requêtes vers LAPI Augmenter ticker_interval

Ce que les retours d’expérience locaux ajoutent

Trois précisions. Real IP via Cloudflare : si Cloudflare en façade, configurer trusted_proxies cloudflare dans Caddy pour récupérer vraie IP visiteur. Sinon, vous bloquez Cloudflare. Captcha mobile-friendly : Google reCAPTCHA challenge sur 4G partagée à Niamey peut être lent. Utiliser hCaptcha (plus léger). Géo-blocking soft : ne pas hard-block tout pays, mais throttle selon score risque.

Tutoriels frères

FAQ

Caddy ou Nginx + bouncer ? Caddy plus simple, Nginx plus mature. Performance équivalente.

Performance avec bouncer ? +1-3 ms latence par requête. Négligeable.

AppSec gratuit ? Oui en self-hosted. Premium WAF rules payantes.

Bouncer multi-Caddy ? Une API key par instance, ou clé partagée si LAPI central.

Désactiver temporairement ? cscli decisions delete --all efface bans actifs.

Lectures complémentaires

Hébergement recommandé pour les lecteurs

Si vous n’avez pas encore d’hébergeur, Hostinger est celui que nous utilisons et que nous recommandons après plusieurs années d’usage.

Profiter de l’offre →

Lien d affiliation. Si vous achetez via ce lien, le blog reçoit une petite commission sans surcoût pour vous.

Architecture CrowdSec en deux moteurs

CrowdSec se compose de deux briques distinctes qu’il faut bien différencier. Le Security Engine analyse les logs (Nginx, Caddy, SSH, Cloudflare) et décide quelles IP bannir grâce à ses scénarios communautaires. Le Remediation Component, ou bouncer, est le composant qui applique réellement la sanction au niveau du serveur web ou du firewall. Sans bouncer, le Security Engine compile une liste mais aucune IP n’est effectivement bloquée.

Vérifiez l’état des deux moteurs avec les commandes suivantes après installation :

sudo cscli metrics
sudo cscli decisions list
sudo cscli bouncers list

Vous devez voir au moins un bouncer enregistré (caddy ou nginx selon votre stack), des scénarios actifs (crowdsecurity/http-probing, crowdsecurity/http-bad-user-agent, etc.) et idéalement des décisions actives provenant de la community blocklist. Si la liste des bouncers est vide, aucune protection n’est appliquée — c’est l’erreur la plus fréquente lors d’un premier déploiement.

Étape complémentaire — Enrichir la détection avec les parsers locaux

Les scénarios par défaut couvrent OWASP Top 10 et les attaques génériques, mais ils ignorent les patterns spécifiques à votre stack. Si vous exposez WordPress, ajoutez les collections dédiées qui détectent les tentatives sur xmlrpc.php, wp-login.php et les énumérations d’utilisateurs :

sudo cscli collections install crowdsecurity/wordpress
sudo cscli collections install crowdsecurity/whitelist-good-actors
sudo systemctl reload crowdsec

La whitelist good-actors évite de bannir Googlebot, BingBot, UptimeRobot et les crawlers SEO légitimes — un faux positif sur Googlebot peut faire chuter votre référencement en quelques heures. Vérifiez la liste avec cscli hubtest list après chaque mise à jour.

Étape complémentaire — Connexion à la Console CrowdSec

La Console hébergée fournit une visualisation claire des attaques bloquées, le partage de signaux avec la communauté et l’envoi de notifications par email ou webhook. L’enrôlement prend deux minutes :

sudo cscli console enroll <votre-token-console>
sudo systemctl restart crowdsec
sudo cscli console status

Une fois validé depuis l’interface web, vous obtenez un dashboard qui affiche les top scénarios déclenchés, les pays sources des attaques et l’évolution temporelle. Pour un opérateur basé à Dakar, vous constaterez que 70 % des scans proviennent de réseaux d’hébergement européens et nord-américains automatisés, et que les vraies tentatives ciblées arrivent souvent depuis des plages IP locales (Sonatel, Orange CI, Moov Africa) compromises.

Étape complémentaire — Notifications WhatsApp Business

Pour un sysadmin à Abidjan ou Dakar joignable principalement sur WhatsApp, configurez une notification CrowdSec qui envoie un message via la WhatsApp Cloud API Graph v25.0 dès qu’une décision critique tombe. Créez le profil dans /etc/crowdsec/profiles.yaml et le notification dans /etc/crowdsec/notifications/whatsapp.yaml :

cat > /etc/crowdsec/notifications/whatsapp.yaml <<'EOF'
type: http
name: whatsapp
log_level: info
format: |
  { "messaging_product":"whatsapp","to":"221XXXXXXXX",
    "type":"text","text":{"body":"CrowdSec alert: {{.Decisions}} bans" } }
url: https://graph.facebook.com/v25.0/PHONE_ID/messages
method: POST
headers:
  Authorization: Bearer EAAxxxxxx
EOF
sudo systemctl restart crowdsec

La sortie attendue dans journalctl -u crowdsec affiche « notification sent » à chaque ban critique. Évitez de spammer en filtrant par scénario (uniquement les attaques en cours) et en limitant à un message toutes les 15 minutes via le champ group_wait dans le profil.

Étape complémentaire — Tester l’efficacité réelle

Un bouncer mal configuré donne une fausse impression de sécurité. Validez le déploiement en simulant une attaque depuis une IP de test (par exemple un VPS Scaleway Stardust à 0,90 EUR/mois soit environ 590 FCFA). Lancez un scan ciblé et vérifiez que vous êtes banni en moins de 30 secondes :

nmap -sV --script=http-enum https://votre-site.sn
curl -I https://votre-site.sn/wp-login.php
sudo cscli decisions list | grep <ip-test>

La première requête doit recevoir une réponse normale, la dixième doit retourner 403 ou un Captcha selon votre configuration. Si la décision n’apparaît pas dans cscli decisions list, le scénario n’est pas actif ou le bouncer n’est pas correctement branché. Refaites un cycle complet : install, enroll, reload, test.

Coûts et hébergement Afrique de l’Ouest

CrowdSec community est gratuit pour les déploiements jusqu’à 3 machines. Au-delà, l’offre Premium démarre à 50 USD/mois soit environ 32 800 FCFA et débloque l’AppSec virtual patching, les blocklists premium (Mirai, Cobalt Strike) et le support prioritaire. Pour un freelance qui héberge 5 sites WordPress sur un VPS Hetzner CX22 (4 Go RAM, 40 Go SSD) à 4,40 EUR/mois soit 2 887 FCFA, la version community suffit largement.

Comptez 200 Mo de RAM additionnels pour le Security Engine et 50 Mo par bouncer. Sur un VPS 2 Go, vous avez encore confortablement de la marge pour Caddy, PHP-FPM et MariaDB. Activez le swap de 2 Go pour absorber les pics lors d’attaques distribuées massives qui peuvent générer des dizaines de milliers de logs par minute à parser.

Mise en pratique sur un parc multi-sites Dakar

Pour une agence qui gère 15 sites clients sur 3 VPS distincts, déployez le Security Engine sur chaque VPS mais centralisez les décisions via un Local API Server. Cela évite que chaque machine maintienne sa propre base de bannissements et permet une vue consolidée. Le serveur central reçoit les signaux de tous les nœuds et redistribue les décisions, ce qui transforme votre parc en réseau de défense mutuelle. Une attaque détectée sur le site d’un client à Almadies banni l’IP fautive sur tous les autres sites en moins de 10 secondes.

Backup et restauration de la base CrowdSec

La base SQLite de CrowdSec stocke les décisions actives, l’historique des alertes et les machines enrôlées. Sa perte vous oblige à reconfigurer chaque bouncer manuellement. Sauvegardez-la quotidiennement vers votre bucket MinIO Object Lock :

sudo systemctl stop crowdsec
sudo cp /var/lib/crowdsec/data/crowdsec.db /tmp/crowdsec-$(date +%F).db
sudo systemctl start crowdsec
mc cp /tmp/crowdsec-*.db local/backups-prod/crowdsec/

L’arrêt du service avant copie évite la corruption WAL. La restauration se fait dans l’ordre inverse : arrêt, écrasement du fichier, redémarrage et vérification via cscli machines list. Si vous voyez vos bouncers réapparaître avec le bon hash, la restauration est réussie.

Intégration avec un load balancer en amont

Si vous placez Cloudflare ou un load balancer Hetzner devant votre serveur, l’IP source que voit Caddy ou Nginx est celle du proxy, pas du visiteur. CrowdSec banni alors aveuglément l’IP du LB et coupe tout votre trafic. Trois étapes corrigent ce piège classique. Premièrement, configurez votre serveur web pour faire confiance aux headers X-Forwarded-For provenant des plages IP du proxy. Deuxièmement, ajoutez les plages du LB dans la whitelist CrowdSec. Troisièmement, vérifiez que les logs contiennent bien la vraie IP cliente avant que le parser CrowdSec ne les analyse.

sudo cscli postoverflows install crowdsecurity/cdn-whitelist
sudo cscli decisions list --ip 172.71.0.0
sudo systemctl reload crowdsec

La sortie ne doit jamais lister les IP du CDN comme bannies. Si c’est le cas, votre configuration trusted_proxies est incomplète et vous risquez un blackout commercial à tout moment.

Scénarios personnalisés métier e-commerce

Les scénarios génériques détectent les attaques techniques mais ratent les abus métier. Pour une boutique WooCommerce qui subit du card testing (test de cartes volées via /checkout), créez un scénario custom qui compte les tentatives d’achat échouées par IP et bannit au-delà de 5 en 10 minutes :

sudo nano /etc/crowdsec/scenarios/woocommerce-card-testing.yaml
sudo cscli hubtest run woocommerce-card-testing
sudo systemctl reload crowdsec

Le test hubtest valide que votre scénario déclenche bien sur des logs simulés sans générer de faux positifs sur du trafic légitime. C’est l’étape qui distingue un sysadmin amateur d’un opérateur sérieux capable de défendre une boutique qui encaisse 500 000 FCFA par jour via Wave et Mixx by Yas.

Maintenance hebdomadaire et mise à jour des hubs

Les scénarios et parsers évoluent continuellement. Sans maintenance, votre installation devient obsolète en quelques semaines face aux nouvelles techniques d’attaque. Planifiez un cron hebdomadaire qui met à jour le hub et redémarre proprement le service :

cat > /etc/cron.weekly/crowdsec-update <<'EOF'
#!/bin/bash
cscli hub update
cscli hub upgrade
systemctl reload crowdsec
cscli metrics > /var/log/crowdsec-weekly-$(date +%F).log
EOF
chmod +x /etc/cron.weekly/crowdsec-update

Vérifiez chaque mois le log généré : il vous indique combien d’alertes ont été générées, quels scénarios sont les plus actifs et si certains bouncers ont décroché. Une chute brutale du nombre d’alertes signale souvent un bouncer crashé silencieusement, pas une accalmie réelle. Connectez ce log à votre Uptime Kuma push monitor pour recevoir une alerte WhatsApp si le rapport hebdomadaire ne tombe pas un dimanche soir.

Coordination avec votre fournisseur de connectivité

Lors d’une attaque DDoS volumétrique qui sature votre lien Sonatel ou Orange CI, CrowdSec ne suffit plus — les paquets arrivent et consomment votre bande passante avant même que le bouncer ne puisse intervenir. Préparez en amont un contact technique chez votre opérateur capable d’activer un nullroute upstream sur votre /32. Documentez ce contact dans votre runbook avec numéro WhatsApp de garde et email d’astreinte. Une attaque de 10 Gbps sur un lien fibre 100 Mbps vous coupe en 2 secondes ; sans procédure pré-validée, vous perdez 6 heures à trouver le bon interlocuteur. Avec un contact direct, vous coupez en 15 minutes et vous sauvez votre journée commerciale.

مشاركة