Credit : Logo officiel
Configurer CrowdSec pour proteger son serveur Linux
Configurer CrowdSec pour protéger son serveur Linux
Dimanche 23h12. Une notification pousse depuis ma console CrowdSec : un VPS client subit une vague de scans WordPress avec des user-agents wp-scan. CrowdSec a déjà banni 47 IP en cinq minutes, sans intervention de ma part. Mieux : ces IP figuraient déjà dans la blocklist communautaire, donc elles n'ont jamais eu le temps d'envoyer plus de deux requêtes avant le ban. C'est exactement la promesse de CrowdSec : un Fail2ban qui apprend de l'expérience collective des autres serveurs.
Depuis 2024, CrowdSec a remplacé Fail2ban sur tous les VPS IONOS que je gère. Voici comment je l'installe et le configure sur Debian 12 avec Nginx, SSH et WordPress.
CrowdSec en deux minutes
L'architecture repose sur trois composants découplés :
- L'agent lit les logs (
/var/log/auth.log,/var/log/nginx/access.log, etc.) et applique des scénarios pour détecter les comportements suspects. - Quand un scénario déclenche, l'agent émet une décision (bannir une IP, par exemple) qu'il stocke dans une base SQLite locale.
- Les bouncers sont des programmes externes (firewall, plugin Nginx, etc.) qui consomment ces décisions et appliquent le blocage réel.
La différence majeure avec Fail2ban : les décisions de votre agent sont partagées (anonymisées) avec la communauté CrowdSec. En retour, vous recevez une blocklist communautaire mise à jour en temps réel, contenant les IP malveillantes détectées par les milliers d'autres serveurs du réseau.
Installation sur Debian 12
Le dépôt officiel s'ajoute via le script d'installation :
curl -s https://install.crowdsec.net | bash
apt install crowdsec -y
Vérification :
cscli version
systemctl status crowdsec
Sortie attendue :
version: v1.6.3-debian-pragmatic-amd64
Codename: alphaga
BuildDate: 2026-04-15
GoVersion: 1.22.4
Platform: linux
L'installateur détecte automatiquement les services présents (Nginx, sshd, postfix...) et installe les collections correspondantes. Une collection regroupe parsers + scénarios + acquis.
cscli collections list
Sortie typique sur un serveur web/SSH :
┌────────────────────────────────┬──────────┬─────────────┐
│ Name │ Status │ Version │
├────────────────────────────────┼──────────┼─────────────┤
│ crowdsecurity/sshd │ enabled │ 0.5 │
│ crowdsecurity/linux │ enabled │ 0.2 │
│ crowdsecurity/nginx │ enabled │ 0.3 │
│ crowdsecurity/base-http-scenarios │ enabled │ 0.7 │
└────────────────────────────────┴──────────┴─────────────┘
Installer le bouncer firewall
L'agent détecte, mais il faut un bouncer pour appliquer le blocage. Le plus simple : crowdsec-firewall-bouncer-iptables (ou nftables sur les systèmes modernes).
apt install crowdsec-firewall-bouncer-nftables -y
Vérification :
cscli bouncers list
┌──────────────────────────────────┬─────────┬───────────┬────────┐
│ Name │ IP │ Revoked │ Status │
├──────────────────────────────────┼─────────┼───────────┼────────┤
│ cs-firewall-bouncer-1715089234 │ 127.0.0.1 │ false │ active │
└──────────────────────────────────┴─────────┴───────────┴────────┘
Le bouncer interroge l'API locale toutes les 10 secondes et synchronise les règles iptables/nftables. Vérifiez les chaînes injectées :
nft list table inet crowdsec
Brancher la console CrowdSec
La console web (gratuite) centralise les alertes de tous vos serveurs.
cscli console enroll -e context VOTRE_CLE_ENROLLMENT
systemctl restart crowdsec
Récupérez la clé sur app.crowdsec.net après création de compte. Acceptez l'enrollment côté console et vous voyez immédiatement le tableau de bord :
- Carte mondiale des IP attaquantes
- Top 10 des scénarios déclenchés
- Historique des bans
- Gestion centralisée multi-serveurs
C'est ce qui m'a fait basculer définitivement de Fail2ban : avoir une vue consolidée sur 30 serveurs en une page.
Souscrire à la blocklist communautaire
La fonctionnalité phare. Sur la console, abonnez-vous gratuitement à la CrowdSec Community Blocklist. Votre serveur reçoit automatiquement les IP signalées comme malveillantes par les autres membres.
cscli decisions list --origin lists
Sur un de mes serveurs, j'ai 38 000 IP en pré-blocage permanent. Ces IP ne tenteront même pas une requête : elles sont stoppées au niveau firewall avant d'atteindre Nginx.
Whitelister vos IP
ÉTAPE CRITIQUE. Sans whitelist, vous risquez de vous bloquer vous-même.
Créez /etc/crowdsec/parsers/s02-enrich/mywhitelist.yaml :
name: crowdsecurity/whitelist-mes-ip
description: "Whitelist IP de confiance"
whitelist:
reason: "IP fixe maison + bureau"
ip:
- "203.0.113.50"
- "198.51.100.10"
cidr:
- "10.0.0.0/8"
- "192.168.0.0/16"
Rechargez :
systemctl reload crowdsec
cscli parsers list | grep whitelist
Si votre IP change souvent (chez vous en FAI dynamique), ajoutez plutôt un fichier hostname :
whitelist:
expression:
- evt.Meta.source_ip in DnsLookup('monpc.dyndns.org')
Commandes essentielles
# Décisions actives (IP bannies)
cscli decisions list
# Alertes récentes
cscli alerts list
cscli alerts inspect 42
# Statistiques en temps réel
cscli metrics
# Parsers et scénarios actifs
cscli parsers list
cscli scenarios list
# Ajouter manuellement un ban
cscli decisions add --ip 192.0.2.99 --duration 24h --reason "scan suspect"
# Lever un ban
cscli decisions delete --ip 192.0.2.99
# Tout effacer (debug uniquement)
cscli decisions delete --all
La sortie de cscli metrics est précieuse pour comprendre ce qui tourne :
Acquisition Metrics:
+----------------------------+------------+--------------+
| Source | Lines read | Lines parsed |
+----------------------------+------------+--------------+
| /var/log/nginx/access.log | 152340 | 152340 |
| /var/log/auth.log | 4521 | 4521 |
+----------------------------+------------+--------------+
Scénario personnalisé : détecter un scan WordPress
Les scénarios par défaut couvrent 90% des cas, mais on peut affiner. Exemple : détecter une IP qui sollicite trop d'URL wp-login.php, xmlrpc.php ou /wp-admin.
Fichier /etc/crowdsec/scenarios/wp-bad-bot.yaml :
type: leaky
name: dylan/wordpress-scan
description: "Detection scan WordPress agressif"
filter: |
evt.Meta.log_type == 'http_access-log' &&
(evt.Meta.http_path matches '(?i)(wp-login|xmlrpc|wp-admin)' ||
evt.Meta.http_user_agent matches '(?i)wp-?scan|nuclei|nikto')
groupby: evt.Meta.source_ip
capacity: 5
leakspeed: 30s
blackhole: 5m
labels:
service: http
type: scan
remediation: true
Validez et rechargez :
cscli scenarios list dylan/wordpress-scan
systemctl reload crowdsec
Le scénario déclenche un ban de 5 minutes dès qu'une IP envoie 5 requêtes suspectes en 30 secondes. Pour aller plus loin sur la sécurité WordPress, voir Bloquer xmlrpc.php sur WordPress.
Bouncers spécifiques
Au-delà du firewall, plusieurs bouncers ciblent des couches précises :
crowdsec-nginx-bouncer: bloque au niveau applicatif Nginx avec une page captcha optionnellecrowdsec-cloudflare-bouncer: pousse les bans vers la WAF Cloudflarecrowdsec-wordpress-bouncer: plugin WordPress qui bloque dans wp-admin
Exemple Nginx avec page captcha :
apt install crowdsec-nginx-bouncer -y
Le bouncer modifie automatiquement votre config Nginx pour ajouter une vérification Lua. Une IP bannie reçoit un captcha plutôt qu'un blocage TCP : utile si vous craignez les faux positifs.
Pour la couche WAF complète, voir Configurer un pare-feu applicatif (WAF) avec Nginx.
Performance et impact système
Un point qui revient souvent : combien de RAM et de CPU consomme CrowdSec ? Sur un VPS IONOS 2 vCPU / 4 Go avec une charge HTTP normale (10 req/s), j'observe :
USER PID %CPU %MEM VSZ RSS COMMAND
crowdsec 1234 0.8 1.2 920000 48000 /usr/bin/crowdsec
firewall 1235 0.1 0.3 180000 12000 crowdsec-firewall-bouncer
Moins de 1% de CPU en moyenne, 50 Mo de RAM. C'est bien plus léger que Fail2ban à charge équivalente, parce que CrowdSec lit les logs en streaming via tail et non en parsant des fichiers entiers à intervalle régulier.
Pour monitorer en continu, branchez Prometheus sur le port 6060 :
# /etc/crowdsec/config.yaml
prometheus:
enabled: true
level: full
listen_addr: 127.0.0.1
listen_port: 6060
Puis grattez les métriques :
curl -s http://127.0.0.1:6060/metrics | grep cs_
Intégration directe possible avec Grafana, voir Créer un dashboard de monitoring avec Grafana.
Mise à jour des collections
Les parsers et scénarios évoluent constamment. Synchronisez régulièrement :
cscli hub update
cscli hub upgrade
systemctl reload crowdsec
J'ai un cron qui fait ça toutes les semaines :
0 4 * * 0 /usr/bin/cscli hub update && /usr/bin/cscli hub upgrade && /bin/systemctl reload crowdsec
Acquisition de logs personnalisée
Par défaut CrowdSec écoute les logs détectés automatiquement. Pour ajouter une source personnalisée (par exemple un log applicatif maison), créez /etc/crowdsec/acquis.d/mon-app.yaml :
filenames:
- /var/log/mon-app/access.log
labels:
type: nginx
service: mon-app
Puis redémarrez :
systemctl restart crowdsec
cscli metrics | grep mon-app
Pour les logs Docker, l'acquisition docker lit directement les logs des conteneurs via la socket :
source: docker
container_name:
- my-nginx
labels:
type: nginx
Utile quand vos services tournent dans Docker, comme dans Docker pour débutants : conteneuriser une app Node.js.
Erreurs courantes et leur fix
Acquisition error: file does not exist
Cause : un fichier de log mentionné dans /etc/crowdsec/acquis.yaml n'existe pas (par exemple /var/log/nginx/access.log sur un serveur sans Nginx).
Solution : éditez /etc/crowdsec/acquis.yaml et commentez la section concernée, puis systemctl restart crowdsec.
Bouncer not registered
Cause : le bouncer n'arrive pas à s'authentifier auprès de l'API locale.
Solution :
cscli bouncers add cs-firewall-bouncer
# Copier la clé generee dans /etc/crowdsec/bouncers/cs-firewall-bouncer.yaml
systemctl restart crowdsec-firewall-bouncer
Ban inefficace, l'IP arrive toujours
Cause : le bouncer ne tourne pas, ou ses règles ont été écrasées par un iptables -F quelque part.
Solution :
systemctl status crowdsec-firewall-bouncer
nft list ruleset | grep crowdsec
Si rien ne s'affiche, redémarrez le bouncer. Si UFW a flushé les chaînes, ordonnez les services : UFW d'abord, bouncer ensuite.
Trop de faux positifs sur une URL légitime
Cause : un scénario par défaut est trop strict pour votre cas (ex: une page admin atypique).
Solution : créez un postoverflow qui ignore certains chemins :
# /etc/crowdsec/postoverflows/s00-enrich/ignore-admin.yaml
name: dylan/ignore-mon-admin
description: "Ignorer faux positifs sur /mon-admin-custom"
filter: "evt.Overflow.Alert.Source.Value == '203.0.113.50'"
reason: "IP equipe interne"
whitelist:
reason: "trusted"
expression:
- evt.Meta.http_path startsWith '/mon-admin-custom/'
High memory usage on small VPS
Cause : par défaut CrowdSec garde 6 mois d'alertes dans SQLite.
Solution : dans /etc/crowdsec/config.yaml :
db_config:
flush:
max_items: 5000
max_age: 7d
Pour aller plus loin
- Fail2ban : protéger son serveur du brute force — pour comprendre l'ancien standard que CrowdSec remplace.
- Sécuriser SSH : configuration avancée de sshd_config — pierre angulaire à combiner avec CrowdSec.
- Configurer un pare-feu applicatif (WAF) avec Nginx — couche WAF complémentaire.
- Hardening Linux : sécuriser son serveur — la vue d'ensemble du durcissement serveur.
- Logs Linux : où chercher, comment lire — pour exploiter ce que CrowdSec analyse.
Comparatif rapide CrowdSec vs Fail2ban
| Critère | Fail2ban | CrowdSec |
|---|---|---|
| Détection | Regex sur logs | Parsers + scénarios YAML |
| Action | iptables direct | Bouncers découplés |
| Communauté | Aucune | Blocklist partagée |
| API | Non | API HTTP locale |
| Console centrale | Non | Oui (gratuite) |
| Empreinte mémoire | ~80 Mo | ~50 Mo |
| Mise à jour scénarios | Manuelle | Hub (cscli hub upgrade) |
Fail2ban reste pertinent sur des serveurs très contraints en RAM ou avec des règles ultra-simples. Dès qu'on parle de WAF, multi-serveurs ou détection avancée, CrowdSec gagne sur tous les tableaux.
Une sécurité qui apprend des autres
CrowdSec n'est pas qu'un Fail2ban moderne : c'est un changement de paradigme. Au lieu de réagir aux attaques que vous subissez déjà, vous bénéficiez de la connaissance collective de milliers de serveurs. Sur un VPS exposé à Internet, c'est aujourd'hui le meilleur ratio effort/protection que je connaisse. L'installation prend trente minutes, l'effet se mesure en jours : moins de bruit dans les logs, moins de tentatives qui aboutissent, et un tableau de bord qui rend visible ce qui était auparavant invisible.