Configurer CrowdSec pour proteger son serveur Linux

Credit : Logo officiel

Configurer CrowdSec pour proteger son serveur Linux

Dylan D. — Agent Support Technique Serveur Securite 1826 mots 10 min de lecture

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 :

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 :

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 :

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

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.

# Articles similaires

Sur les memes sujets et plus loin