Aller au contenu
Sécurité medium

CrowdSec : détection et blocage collaboratif des attaques

41 min de lecture

logo crowdsec

CrowdSec est un IDS/IPS open source collaboratif qui analyse vos logs en temps réel, détecte les comportements malveillants (brute force, scans, exploits) et bloque automatiquement les attaquants. Son point fort : chaque utilisateur partage ses signaux avec la communauté, créant une base de threat intelligence collective qui protège tout le réseau. Ce guide s'adresse aux administrateurs débutants à intermédiaires : vous partez d'une machine Linux nue et vous repartez avec un service protégé, un pare-feu qui bloque réellement les IP, un WAF actif et des alertes. Toutes les commandes et sorties ont été testées sur CrowdSec 1.7.8.

  • Comprendre l'architecture Security Engine, LAPI, Bouncers et CAPI
  • Installer CrowdSec depuis le dépôt officiel signé (apt/dnf, tarball, Docker)
  • Protéger un service de A à Z en 10 étapes concrètes, de la détection au blocage
  • Configurer les bouncers pare-feu, Nginx et Traefik pour bloquer réellement
  • Activer le WAF AppSec et gérer les allowlists pour éviter les faux positifs
  • Recevoir des notifications (Slack, e-mail) et superviser avec Prometheus

Analogie : si Fail2Ban est un vigile qui surveille l'entrée de votre immeuble, CrowdSec est un réseau de vigiles connectés. Quand l'un d'eux repère un intrus, tous les autres sont immédiatement prévenus et bloquent cette personne avant même qu'elle ne se présente.

CrowdSec se distingue par :

  • Intelligence communautaire (CAPI) : les signaux d'attaque sont partagés entre tous les utilisateurs, créant une base de threat intelligence collective.
  • Architecture modulaire : Security Engine (détection) et Bouncers (remédiation) découplés, déployables sur des machines différentes.
  • Performance : parsers écrits en Go avec enrichissement GeoIP natif.
  • Sources de logs variées : fichiers, journald, conteneurs Docker, S3, Kafka, Loki.
  • WAF intégré : le composant AppSec analyse les requêtes HTTP en temps réel.
  • LAPI REST complète : API pour piloter décisions, alertes et bouncers.
  • Console web gratuite : app.crowdsec.net pour superviser vos instances et gérer les blocklists.
  • Licence MIT : open source, libre d'utilisation commerciale.

Avant l'installation, voici les termes essentiels. Ils reviennent dans toutes les commandes cscli.

  • Collection : pack préconfiguré de parsers et scénarios pour un service. C'est un kit de surveillance prêt à l'emploi.
  • Parser : analyse et normalise une ligne de log brute. C'est le traducteur qui comprend le format du log.
  • Scénario : définit un comportement malveillant via un leaky bucket. Par exemple : « plus de 5 échecs en 10 s = attaque ».
  • Décision : action prise (ban, captcha, throttle). C'est la sanction appliquée à un attaquant.
  • Bouncer : composant qui applique les décisions. C'est le vigile qui exécute l'ordre de blocage.
  • Enricher : ajoute du contexte (GeoIP, DNS) aux événements. C'est la fiche d'identité de chaque événement.
  • Allowlist : liste d'IP ou de plages jamais bloquées. C'est le laissez-passer de vos machines de confiance.
  • Hub : dépôt centralisé de parsers, scénarios et collections. C'est le magasin d'applications de la sécurité CrowdSec.

Le Security Engine est le nom donné à l'ensemble du système CrowdSec. Il se compose de deux parties internes, le Log Processor et la Local API (LAPI), auxquelles s'ajoutent des composants externes : les Remediation Components (bouncers) et la Central API (CAPI).

Le Log Processor est la partie du Security Engine en charge de toute la détection. Il a deux fonctions principales :

  • Analyser les logs : il lit les journaux depuis des sources variées (fichiers, journald, conteneurs Docker, S3, Kafka, Loki), les parse et les compare à des scénarios de détection.
  • Filtrer le trafic HTTP : via le composant AppSec (WAF), il reçoit les requêtes HTTP directement depuis un serveur web compatible et les confronte à des règles AppSec.

Quand un scénario ou une règle AppSec se déclenche, le Log Processor envoie une alerte à la LAPI.

Le pipeline de parsing traite chaque ligne en trois stages successifs. Un événement doit être parsé avec succès à chaque stage pour passer au suivant, sinon il est ignoré :

  1. s00-raw, normalisation : les logs arrivent de sources différentes (syslog, fichier Nginx, conteneur Docker). Ce stage les met dans un format prédictible. Un log SSH arrivant par journald et le même arrivant par un fichier syslog produisent le même événement en sortie.
  2. s01-parse, extraction : à partir du format normalisé, ce stage extrait les informations pertinentes. Pour SSH, il identifie le type d'événement (échec d'authentification, connexion réussie), l'IP source, le nom d'utilisateur.
  3. s02-enrich, enrichissement : les champs extraits sont complétés par du contexte : géolocalisation GeoIP (pays, ville, ASN), résolution DNS, vérification des allowlists. C'est ici que les IP privées (RFC 1918) sont marquées comme allowlistées.

Une fois enrichi, l'événement est transmis aux scénarios. Un scénario fonctionne comme un leaky bucket (seau percé) : chaque événement qui correspond au filtre « remplit » le seau. Le seau se vide à un rythme défini par leakspeed. Si le seau déborde (plus d'événements que la capacity dans le temps imparti), un overflow se produit et génère une alerte. Le paramètre groupby (généralement l'IP source) assure que chaque attaquant a son propre seau.

Après un overflow, l'événement passe encore par les postoverflows, des parsers spéciaux, souvent des allowlists de dernière chance (par exemple, exclure les IP de fournisseurs DNS publics légitimes).

La Local API est le point central qui relie tous les composants. Elle :

  • Reçoit les alertes du Log Processor et crée des décisions selon les profils de profiles.yaml (type de ban, durée, scope IP ou range).
  • Expose les décisions aux bouncers via une API REST.
  • Communique avec la CAPI pour envoyer les signaux d'attaque et recevoir les blocklists communautaires.

Toute la communication entre composants passe par la LAPI en HTTP. C'est ce qui permet une architecture distribuée : plusieurs Log Processors et plusieurs bouncers, sur des machines différentes, partagent la même LAPI.

Les Remediation Components (bouncers) : l'exécution

Section intitulée « Les Remediation Components (bouncers) : l'exécution »

Les bouncers sont des composants externes au Security Engine. Ils interrogent la LAPI pour obtenir la liste des décisions actives et les appliquent concrètement, là où c'est le plus efficace :

  • Pare-feu : cs-firewall-bouncer ajoute les IP dans un ipset et applique une règle DROP via iptables ou nftables.
  • Reverse proxy : bouncers Nginx, Traefik ou HAProxy qui rejettent les requêtes au niveau HTTP.
  • CDN : bouncers Cloudflare ou AWS WAF pour le blocage en amont.
  • Applicatif : bouncers WordPress, PHP.

Sans bouncer, CrowdSec détecte les attaques mais ne bloque rien. La détection et la remédiation sont volontairement découplées.

La CAPI et la Console : l'intelligence communautaire

Section intitulée « La CAPI et la Console : l'intelligence communautaire »

La Central API (CAPI) est le point de connexion avec le réseau CrowdSec mondial. Elle reçoit les signaux de toutes les installations participantes, les agrège, les valide, puis redistribue des blocklists communautaires à l'ensemble des membres. Une attaque détectée par un participant protège proactivement tous les autres.

La Console (app.crowdsec.net) est l'interface web qui donne accès à la gestion des alertes et décisions, à la supervision de vos Security Engines et à l'abonnement aux blocklists.

Pour illustrer, voici ce qui se passe lors d'un brute force SSH :

  1. Acquisition : le Log Processor lit les logs SSH via journald (configuré dans acquis.d/).
  2. Parsing : la ligne Failed password for root from 185.220.101.34 traverse les 3 stages (normalisation syslog, extraction des champs SSH, enrichissement GeoIP et allowlist).
  3. Scénario : l'événement entre dans crowdsecurity/ssh-bf. Le seau de l'IP se remplit. Après plusieurs échecs rapprochés, le seau déborde en overflow.
  4. Postoverflow : les allowlists de dernière chance sont consultées. L'IP n'est pas allowlistée.
  5. Profil : la LAPI reçoit l'alerte, consulte profiles.yaml et crée une décision : ban de 4 heures.
  6. Remédiation : le bouncer pare-feu récupère la décision et ajoute l'IP dans l'ipset crowdsec-blacklists : règle DROP appliquée.
  7. Partage : en parallèle, le signal part vers la CAPI. Si assez d'installations signalent la même IP, elle rejoint la Community Blocklist.

Architecture CrowdSec : Security Engine, LAPI, Bouncers et CAPI

CrowdSec se distribue via un dépôt signé (clé GPG + apt/dnf), un tarball officiel ou un conteneur. La méthode recommandée est le dépôt signé : les mises à jour suivent alors votre gestionnaire de paquets habituel.

Le script d'installation du dépôt ajoute la clé GPG et la source apt de CrowdSec. Téléchargez-le, inspectez-le, puis exécutez-le. On ne l'exécute jamais à l'aveugle depuis un pipe.

Fenêtre de terminal
# Télécharger le script d'ajout du dépôt, l'inspecter, puis l'exécuter
curl -s https://install.crowdsec.net -o crowdsec-repo.sh
less crowdsec-repo.sh
sudo bash crowdsec-repo.sh
# Installer CrowdSec depuis le dépôt signé ainsi ajouté
sudo apt-get install -y crowdsec

Le script pose la clé crowdsec_crowdsec-archive-keyring.gpg et la source crowdsec_crowdsec.list. L'installation détecte SSH et installe la collection correspondante automatiquement.

Contrôlez la version installée. La sortie doit indiquer v1.7.8 :

Fenêtre de terminal
sudo cscli version
version: v1.7.8-debian-pragmatic-amd64
Codename: alphaga
BuildDate: 2026-05-11_12:36:14
GoVersion: 1.26.2
Platform: linux

CrowdSec enregistre la machine locale comme agent auprès de la LAPI. Vérifiez que le service tourne et que la machine est bien connue :

Fenêtre de terminal
sudo systemctl is-active crowdsec
# active
sudo cscli machines list
Name IP Address Last Update Status Version OS
ad42900...p0yxjF5vC 127.0.0.1 2026-07-06T08:30:20Z ✔️ v1.7.8 ubuntu/24.04

La configuration vit dans /etc/crowdsec/. Les fichiers principaux :

  • config.yaml : configuration globale (logs, base de données, API, Prometheus).
  • acquis.yaml et acquis.d/*.yaml : sources de logs à surveiller.
  • profiles.yaml : politiques de décision (ban, durée, notifications).
  • local_api_credentials.yaml : identifiants de la machine pour la LAPI.
  • online_api_credentials.yaml : identifiants pour la CAPI (communauté).
  • simulation.yaml : scénarios en mode simulation (pas de ban réel).

Le fichier profiles.yaml définit ce qui se passe quand un scénario déclenche une alerte :

/etc/crowdsec/profiles.yaml
name: default_ip_remediation
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 4h
on_success: break

Ce profil signifie : toute alerte avec remédiation sur une IP entraîne un ban de 4 heures. Vous ajouterez plus loin une clause notifications à ce même fichier pour être alerté.

Le Hub CrowdSec (hub.crowdsec.net) est le dépôt centralisé des parsers, scénarios et collections prêts à l'emploi. Sur une installation 1.7.8 fraîche, l'index couvre un large catalogue.

Fenêtre de terminal
# Mettre à jour l'index du hub
sudo cscli hub update
# Mettre à jour tous les composants installés
sudo cscli hub upgrade
# Lister tout ce qui est installé
sudo cscli hub list
Loaded: 164 parsers, 12 postoverflows, 783 scenarios, 9 contexts,
5 appsec-configs, 219 appsec-rules, 163 collections

Un scénario fonctionne comme un leaky bucket. Les événements remplissent le seau ; s'il déborde, une alerte est déclenchée. Exemple du scénario ssh-bf (brute force SSH) :

/etc/crowdsec/scenarios/ssh-bf.yaml
type: leaky
name: crowdsecurity/ssh-bf
description: "Detect ssh bruteforce"
filter: "evt.Meta.log_type == 'ssh_failed-auth'"
leakspeed: "10s" # le seau se vide d'un événement toutes les 10 s
capacity: 5 # le seau contient 5 événements au maximum
groupby: evt.Meta.source_ip
blackhole: 1m # après déclenchement, ignore l'IP pendant 1 min
labels:
service: ssh
remediation: true # active le blocage automatique
classification:
- attack.T1110 # MITRE ATT&CK : Brute Force

En clair : si une même IP génère plus de 5 échecs d'authentification SSH en moins de 50 secondes (5 × 10 s), CrowdSec déclenche une alerte et bloque l'IP.

Vous savez installer CrowdSec. Passons au cas concret : comment protéger un service que vous venez d'installer ? Cette section décrit le workflow complet, de la détection du service à la validation de la protection, en prenant Nginx comme exemple. La démarche est identique pour SSH, Apache, MariaDB, Postfix, HAProxy ou Caddy : seuls le nom de la collection et le format des logs changent.

CrowdSec intègre un mécanisme de service discovery qui détecte les services installés :

Fenêtre de terminal
sudo cscli setup detect --yaml
setup:
- detected_service: nginx
hub_spec:
collections:
- crowdsecurity/nginx
acquisition_spec:
filename: nginx.yaml
datasource:
filenames:
- /var/log/nginx/*.log
labels:
type: nginx
source: file
- detected_service: openssh-journal-ssh
hub_spec:
collections:
- crowdsecurity/sshd
acquisition_spec:
filename: sshd.yaml
datasource:
journalctl_filter:
- _SYSTEMD_UNIT=ssh.service
labels:
type: syslog
source: journalctl

La commande identifie chaque service, la collection à installer et la configuration d'acquisition correspondante.

Étape 2 : examiner la collection avant installation

Section intitulée « Étape 2 : examiner la collection avant installation »

Avant d'installer, inspectez ce que la collection contient :

Fenêtre de terminal
sudo cscli collections inspect crowdsecurity/nginx
type: collections
name: crowdsecurity/nginx
description: 'nginx support : parser and generic http scenarios'
dependencies:
parsers:
- crowdsecurity/nginx-logs
scenarios:
- crowdsecurity/nginx-req-limit-exceeded
collections:
- crowdsecurity/base-http-scenarios

La collection nginx inclut un parser (nginx-logs), un scénario spécifique et une sous-collection base-http-scenarios qui apporte plusieurs dizaines de scénarios HTTP : brute force, scans de fichiers sensibles, injections SQL, XSS, CVE connues, user-agents malveillants.

Fenêtre de terminal
sudo cscli collections install crowdsecurity/nginx

CrowdSec télécharge automatiquement toutes les dépendances (parsers, scénarios, sous-collections). Vérifiez ensuite :

Fenêtre de terminal
sudo cscli collections list
Name Status Version
crowdsecurity/base-http-scenarios ✔️ enabled 1.2
crowdsecurity/http-cve ✔️ enabled 2.9
crowdsecurity/linux ✔️ enabled 0.3
crowdsecurity/nginx ✔️ enabled 0.2
crowdsecurity/sshd ✔️ enabled 0.8

La collection installe les parsers et scénarios mais ne configure pas la source de logs. Indiquez à CrowdSec où lire les logs en créant un fichier dans /etc/crowdsec/acquis.d/ :

Fenêtre de terminal
sudo tee /etc/crowdsec/acquis.d/nginx.yaml << 'EOF'
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx
EOF

Selon votre infrastructure, les logs peuvent venir d'autres sources :

/etc/crowdsec/acquis.d/nginx.yaml
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx

Rechargez le service, puis vérifiez que CrowdSec lit bien les logs :

Fenêtre de terminal
sudo systemctl reload crowdsec
sudo cscli metrics
Source Lines read Lines parsed Lines unparsed
file:/var/log/nginx/access.log 41 41 -
journalctl:ssh.service 9 4 5

Les 41 lignes parsées confirment que le parser nginx-logs traite correctement les logs.

cscli explain rejoue une ligne de log dans tout le pipeline, du stage brut jusqu'aux scénarios. Testez avec une IP publique (une IP privée serait allowlistée) :

Fenêtre de terminal
sudo cscli explain \
--log 'Jan 15 10:00:00 srv sshd[1234]: Failed password for root from 185.220.101.34 port 22 ssh2' \
--type syslog
line: ... Failed password for root from 185.220.101.34 ...
├ s00-raw
| └ 🟢 crowdsecurity/syslog-logs (+12 ~9)
├ s01-parse
| └ 🟢 crowdsecurity/sshd-logs (+9 ~1)
├ s02-enrich
| ├ 🟢 crowdsecurity/dateparse-enrich (+2 ~2)
| ├ 🟢 crowdsecurity/geoip-enrich (+13)
| ├ 🟢 crowdsecurity/public-dns-allowlist (unchanged)
| └ 🟢 crowdsecurity/whitelists (unchanged)
├-------- parser success 🟢
├ Scenarios
├ 🟢 crowdsecurity/ssh-bf
├ 🟢 crowdsecurity/ssh-bf_user-enum
├ 🟢 crowdsecurity/ssh-slow-bf
└ 🟢 crowdsecurity/ssh-time-based-bf

Lecture : la ligne est normalisée (syslog-logs), les champs SSH sont extraits (sshd-logs), l'enrichissement GeoIP ajoute 13 champs, et plusieurs scénarios SSH matchent, du brute force rapide au brute force lent.

Avant de bloquer réellement, testez vos nouveaux scénarios en mode simulation. Les alertes sont générées mais aucun ban n'est appliqué :

Fenêtre de terminal
sudo cscli simulation status
# global simulation: disabled
sudo cscli simulation enable crowdsecurity/http-probing
sudo systemctl reload crowdsec

En simulation, les décisions apparaissent avec le préfixe (simul). Observez le comportement quelques heures, puis désactivez :

Fenêtre de terminal
sudo cscli simulation disable crowdsecurity/http-probing
sudo systemctl reload crowdsec

Jusqu'ici, CrowdSec détecte mais ne bloque rien. Pour appliquer les décisions, installez un bouncer. Chaque bouncer a besoin d'une clé API pour parler à la LAPI :

Fenêtre de terminal
sudo cscli bouncers add mon-firewall-bouncer
API key for 'mon-firewall-bouncer':
MC8xo8D12YS7g//YxumyYhIFV5pVWIMql8f1aMY/4Gc
Please keep this key since you will not be able to retrieve it!

Installez ensuite le bouncer pare-feu, le plus courant. Sur Debian/Ubuntu, le paquet enregistre lui-même son propre bouncer, vous n'avez pas à réutiliser la clé ci-dessus :

Fenêtre de terminal
sudo apt install crowdsec-firewall-bouncer-iptables

Le bouncer crée un ipset crowdsec-blacklists-0 et applique une règle DROP pour toutes les IP de cet ensemble. Vérifiez :

Fenêtre de terminal
sudo cscli bouncers list
Name IP Address Valid Type Version
cs-firewall-bouncer-1783326748 127.0.0.1 ✔️ crowdsec-firewall-bouncer v0.0.34
Fenêtre de terminal
sudo ipset list -name | grep crowdsec
# crowdsec-blacklists-0

Les décisions sont créées automatiquement quand un scénario déborde, mais vous pouvez aussi les gérer à la main.

Fenêtre de terminal
# Lister les décisions actives
sudo cscli decisions list
# Bannir manuellement une IP pendant 4 heures
sudo cscli decisions add --ip 192.0.2.55 --duration 4h --reason "IP suspecte"
# Bannir un sous-réseau entier
sudo cscli decisions add --range 203.0.113.0/24 --duration 24h --reason "Réseau malveillant"
# Supprimer une décision
sudo cscli decisions delete --ip 192.0.2.55
# Supprimer toutes les décisions
sudo cscli decisions delete --all

Un decisions list après un ban manuel confirme la sanction :

ID Source Scope:Value Reason Action Events expiration
1 cscli Ip:192.0.2.55 IP suspecte ban 1 3h59m59s

L'historique des alertes reste consultable même après expiration des bans :

Fenêtre de terminal
sudo cscli alerts list

cscli metrics agrège l'acquisition, les alertes et les appels LAPI. C'est votre tableau de bord en ligne de commande :

Fenêtre de terminal
sudo cscli metrics

Surveillez notamment le compteur d'alertes par scénario et les routes LAPI les plus sollicitées. Nous branchons Prometheus sur ces mêmes métriques plus loin.

ÉtapeCommandeCe que ça fait
1. Détectercscli setup detect --yamlIdentifier services et collections
2. Inspectercscli collections inspect crowdsecurity/nginxVérifier le contenu
3. Installercscli collections install crowdsecurity/nginxTélécharger parsers et scénarios
4. ConfigurerCréer /etc/crowdsec/acquis.d/nginx.yamlIndiquer où lire les logs
5. Rechargersystemctl reload crowdsecAppliquer la configuration
6. Validercscli explain --log "..." --type nginxTester le pipeline
7. Simulercscli simulation enable <scénario>Tester sans bloquer
8. Bloquerapt install crowdsec-firewall-bouncer-iptablesInstaller le bouncer
9. Gérercscli decisions list / add / deleteContrôler les blocages
10. Surveillercscli metricsVérifier en continu

Le bouncer pare-feu bloque au niveau réseau, mais pour une application web, il est souvent plus fin de bloquer au niveau du reverse proxy : l'attaquant reçoit une page 403 et vos autres services restent joignables. CrowdSec fournit des bouncers pour les proxys les plus courants.

Le bouncer Nginx s'appuie sur un module Lua pour filtrer les requêtes. Sur Debian/Ubuntu, le paquet s'installe depuis le dépôt CrowdSec et s'enregistre tout seul auprès de la LAPI : la clé API est écrite directement dans sa configuration, vous n'avez pas à la coller à la main.

Fenêtre de terminal
sudo apt install crowdsec-nginx-bouncer

Le fichier /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf contient alors la clé et l'URL de la LAPI déjà renseignées :

ENABLED=true
API_URL=http://127.0.0.1:8080
API_KEY=<renseignée automatiquement à l'installation>
APPSEC_URL=

Le bouncer applique les décisions de ban de la LAPI au niveau HTTP : une IP bannie reçoit la page de blocage CrowdSec. La ligne APPSEC_URL vide sert à brancher le WAF AppSec, que nous activons juste après.

Avec Traefik, le bouncer prend la forme d'un middleware (plugin) qui refuse les requêtes des IP bannies avant qu'elles n'atteignent vos services. Déclarez le plugin, puis créez un middleware alimenté par la clé API :

# middleware Traefik (dynamic config)
http:
middlewares:
crowdsec:
plugin:
crowdsec-bouncer:
crowdsecLapiUrl: http://crowdsec:8080
crowdsecLapiKey: "<clé générée par cscli bouncers add>"

Appliquez ensuite ce middleware à vos routeurs. Toute IP bannie reçoit un 403 au niveau du proxy. Le guide Traefik détaille l'intégration complète du plugin.

Depuis la 1.6, le Log Processor intègre un module WAF nommé AppSec. Là où les scénarios analysent des logs (donc après coup), AppSec analyse les requêtes HTTP en temps réel, transmises par le bouncer proxy, et peut les bloquer avant qu'elles n'atteignent l'application. La 1.7.8 y ajoute la validation de schéma OpenAPI et une limite de taille de corps de requête.

  • In-band : la requête est analysée avant d'atteindre l'application. Si elle matche une règle, elle est bloquée immédiatement. C'est le mode de protection.
  • Out-of-band : la requête est analysée après avoir été transmise à l'application. Ce mode détecte sans bloquer, idéal pour valider de nouvelles règles sans risque.

AppSec s'installe comme des collections de règles. La collection virtual patching bloque les tentatives d'exploitation de CVE connues (mise à jour quotidienne) ; generic rules couvre les schémas d'attaque courants (LFI, traversée de chemin, accès aux fichiers sensibles) :

Fenêtre de terminal
sudo cscli collections install \
crowdsecurity/appsec-virtual-patching \
crowdsecurity/appsec-generic-rules
sudo cscli appsec-configs list
Name Status Version Local Path
crowdsecurity/appsec-default ✔️ enabled 0.4 /etc/crowdsec/appsec-configs/appsec-default.yaml
crowdsecurity/virtual-patching ✔️ enabled 0.4 /etc/crowdsec/appsec-configs/virtual-patching.yaml

Déclarez ensuite une source d'acquisition appsec qui ouvre un port d'écoute pour le bouncer proxy. Utilisez la clé appsec_configs (au pluriel, une liste ; la forme appsec_config au singulier est dépréciée) :

/etc/crowdsec/acquis.d/appsec.yaml
source: appsec
listen_addr: 127.0.0.1:7422
path: /
appsec_configs:
- crowdsecurity/appsec-default
labels:
type: appsec

Reste à relier le bouncer à AppSec. Avec le bouncer Nginx installé plus haut, renseignez APPSEC_URL puis redémarrez Nginx. Le proxy enverra désormais chaque requête à AppSec, qui répond autoriser ou bloquer :

Fenêtre de terminal
sudo sed -i 's|^APPSEC_URL=.*|APPSEC_URL=http://127.0.0.1:7422|' \
/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf
sudo systemctl restart crowdsec nginx

Envoyez une requête légitime, elle passe (200). Envoyez une requête vers un fichier .env (fuite fréquente d'identifiants), AppSec la bloque avant qu'elle n'atteigne l'application (403) :

Fenêtre de terminal
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/ # 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/.env # 403

Vérifiez que le WAF a bien compté et bloqué la requête :

Fenêtre de terminal
sudo cscli metrics show appsec
Appsec Engine Processed Blocked
127.0.0.1:7422/ 3 2
Rule ID Triggered
crowdsecurity/vpatch-CVE-2017-9841 1
crowdsecurity/vpatch-env-access 1

Les blocages apparaissent aussi dans cscli alerts list (colonne kind: waf). Notez qu'un blocage in-band remédie la requête sur-le-champ (403) mais ne crée pas de décision de ban persistante : AppSec filtre requête par requête, il ne bannit pas l'IP au niveau réseau.

Un IDS trop zélé qui bannit votre propre IP de supervision est un incident en soi. Les allowlists (introduites dans la branche 1.7) déclarent des IP ou des plages qui ne seront jamais bloquées, quelles que soient les alertes. Elles se gèrent entièrement en ligne de commande et sont synchronisables avec la Console.

Fenêtre de terminal
# Créer une allowlist
sudo cscli allowlists create maintenance -d "IP de gestion"
# Ajouter une IP ou une plage
sudo cscli allowlists add maintenance 192.168.1.0/24 -d "LAN admin"
# Lister les allowlists
sudo cscli allowlists list
Name Description Created at Managed by Console Size
maintenance IP de gestion 2026-07-06T08:32:25.242Z no 1

Pour vérifier si une IP est couverte avant qu'un incident n'arrive :

Fenêtre de terminal
sudo cscli allowlists check 192.168.1.42
# 192.168.1.42 is allowlisted by item 192.168.1.0/24 from maintenance (LAN admin)

Par défaut, CrowdSec bloque en silence. Pour recevoir une alerte à chaque décision, activez un plugin de notification. CrowdSec en fournit plusieurs, tous désactivés au départ :

Fenêtre de terminal
sudo cscli notifications list
Active Name Type Profile name
🚫 http_default http
🚫 slack_default slack
🚫 splunk_default splunk
🚫 sentinel_default sentinel
🚫 email_default email
🚫 file_default file

Prenons Slack. Renseignez d'abord l'URL du webhook dans le fichier du plugin :

/etc/crowdsec/notifications/slack.yaml
type: slack
name: slack_default
webhook: https://hooks.slack.com/services/VOTRE/WEBHOOK/ICI

Puis branchez ce plugin sur un profil dans profiles.yaml, avec la clé notifications :

/etc/crowdsec/profiles.yaml
name: default_ip_remediation
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 4h
notifications:
- slack_default
on_success: break

Rechargez le service : chaque ban enverra désormais un message Slack. La démarche est identique pour l'e-mail (email.yaml) ou un webhook HTTP générique vers votre SIEM.

Le plugin fichier est le plus simple pour valider la chaîne de bout en bout sans dépendre d'un service externe. Il écrit chaque alerte en NDJSON. Sa configuration par défaut vise /tmp/crowdsec_alerts.json :

/etc/crowdsec/notifications/file.yaml
type: file
name: file_default
log_level: info
format: |
{{range . -}}
{ "time": "{{.StopAt}}", "program": "crowdsec", "alert": {{. | toJson }} }
{{ end -}}
log_path: "/tmp/crowdsec_alerts.json"
rotate:
enabled: true
max_size: 10
max_files: 5

Branchez file_default dans un profil, rechargez, puis provoquez un overflow de scénario réel (par exemple des échecs SSH répétés depuis une IP publique). Le fichier reçoit alors l'alerte complète avec sa décision de ban :

{ "time": "2026-07-06T09:17:48Z", "program": "crowdsec",
"alert": { "scenario": "crowdsecurity/ssh-bf",
"decisions": [{ "type": "ban", "duration": "4h", "scope": "Ip",
"value": "198.51.100.111" }] } }

cscli metrics donne une vue instantanée, mais pour un suivi dans la durée, exposez les métriques Prometheus de CrowdSec. Elles sont actives par défaut sur le port 6060, en écoute locale :

/etc/crowdsec/config.yaml
prometheus:
enabled: true
level: full
listen_addr: 127.0.0.1
listen_port: 6060

Vérifiez d'abord que l'endpoint répond, puis ajoutez la cible de scrape. Un simple curl confirme les compteurs, y compris ceux du WAF quand AppSec est actif :

Fenêtre de terminal
curl -s http://127.0.0.1:6060/metrics | grep -E '^cs_(active_decisions|appsec_block)'
# cs_active_decisions{action="ban",origin="crowdsec",...} 1
# cs_appsec_block_total{appsec_engine="127.0.0.1:7422/",source="127.0.0.1"} 1
prometheus.yml
scrape_configs:
- job_name: crowdsec
static_configs:
- targets: ["127.0.0.1:6060"]

CrowdSec publie un tableau de bord Grafana officiel qui visualise les alertes par scénario, les IP bloquées, l'activité de la LAPI et la santé de l'acquisition. Les métriques clés à surveiller : le volume d'alertes, le taux de lignes non parsées (signe d'un parser manquant) et la latence de la LAPI. Voir le guide Prometheus pour la mise en place du scraping et Grafana pour l'import du dashboard.

Sur un parc, on ne fait pas tourner une LAPI par machine. Le motif recommandé centralise la décision :

  • Une LAPI centralisée reçoit les alertes de tous les agents et détient la base de décisions.
  • Des agents distants (Log Processors) analysent les logs localement et ne remontent que les alertes, pas les logs bruts. Cela économise la bande passante et garde les logs sur place.
  • Des bouncers distribués interrogent tous la LAPI centralisée pour appliquer un blocage cohérent sur l'ensemble du parc.

Chaque agent distant s'enregistre auprès de la LAPI centrale avec cscli lapi register, et la LAPI valide la machine avec cscli machines validate. Vérifiez à tout moment la connexion d'un agent :

Fenêtre de terminal
sudo cscli lapi status
# You can successfully interact with Local API (LAPI)

La Console (app.crowdsec.net) est l'interface web gratuite pour superviser vos instances : visualiser les alertes avec géolocalisation, gérer les décisions graphiquement, s'abonner aux blocklists communautaires et surveiller plusieurs instances depuis un tableau de bord unique.

  1. Créer un compte sur app.crowdsec.net.

  2. Obtenir la clé d'enrôlement dans la console : bouton +, puis Enroll a Security Engine.

  3. Exécuter la commande sur votre serveur :

    Fenêtre de terminal
    sudo cscli console enroll <VOTRE_CLÉ>
  4. Valider l'enrôlement dans la console web.

Avec le plan Community (gratuit), vous souscrivez à 3 blocklists d'IP malveillantes, mises à jour en continu par la communauté. Elles bloquent proactivement des IP connues avant même qu'elles n'attaquent votre serveur.

SymptômeCause probableSolution
bind: address already in use au démarragePort LAPI (8080) occupéChanger listen_uri dans config.yaml et local_api_credentials.yaml
No active decisions malgré des attaquesPas de bouncer installéLe Security Engine détecte mais ne bloque pas sans bouncer
IP privée non détectée par les scénariosAllowlist des IP privéesNormal : les IP RFC 1918 sont exclues
missing login field au démarragePas enregistré sur la CAPIExécuter sudo cscli capi register
Scénario ne matche pasParser manquant ou log mal formatécscli explain --log "..." --type syslog pour diagnostiquer
Lignes unparsed élevéesLabel type erroné dans l'acquisitionVérifier que type correspond au parser de la collection

Les commandes de diagnostic essentielles :

Fenêtre de terminal
# Statut du service et logs
sudo systemctl status crowdsec
sudo tail -f /var/log/crowdsec.log
# Tester le parsing d'un log
sudo cscli explain --log "VOTRE_LIGNE" --type syslog
# Vérifier la connexion LAPI et les métriques
sudo cscli lapi status
sudo cscli metrics
  • Allowlistez vos accès de management et vos sondes dès l'installation pour ne jamais vous auto-verrouiller.
  • Commencez en simulation pour tout nouveau scénario avant de l'activer en production.
  • Enregistrez-vous sur la CAPI pour bénéficier des blocklists communautaires.
  • Limitez la LAPI à 127.0.0.1 sauf en architecture multi-serveurs.
  • Rôdez les règles AppSec en out-of-band avant de passer en in-band.
  • Mettez à jour le hub régulièrement : cscli hub update && cscli hub upgrade.
  • Branchez une notification (Slack, e-mail) pour ne pas bloquer en aveugle.
  • Supervisez les métriques Prometheus, en particulier le taux de lignes non parsées.
  • Sauvegardez /etc/crowdsec/ avant chaque mise à jour majeure.
  1. CrowdSec est un IDS/IPS collaboratif : chaque utilisateur renforce la protection de tous via la CAPI.
  2. L'architecture est modulaire : Security Engine (détection), LAPI (middleware), Bouncers (remédiation).
  3. Les collections sont le moyen le plus rapide de protéger un service.
  4. Sans bouncer, CrowdSec ne bloque rien : la détection et la remédiation sont découplées.
  5. cscli explain est votre meilleur allié pour diagnostiquer le pipeline de parsing.
  6. Le WAF AppSec bloque les requêtes HTTP en temps réel, avant l'application.
  7. Les allowlists évitent les faux positifs et l'auto-verrouillage.
  8. Notifications et Prometheus transforment un blocage silencieux en supervision active.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn