CrowdSec

Mis à jour le samedi 13 décembre 2025 par johackim

CrowdSec est un Pare-feu communautaire open-source pour se protéger des attaques informatiques.

Il analyse le comportement des visiteurs via les logs et répond de manière adaptée :

  • Bloquer l'adresse IP
  • Ajouter un captcha
  • Ajouter un code HTTP 403
  • ect...

Les adresses IP agressives sont envoyées à CrowdSec pour être partagés entre tous les utilisateurs afin d'améliorer la sécurité de chacun.

Installation

Pour l'installer sur Ubuntu ou Debian :

curl -s https://install.crowdsec.net | sudo sh
sudo apt install -y crowdsec

Pour l'installer sur Arch Linux :

yay -S --noconfirm crowdsec-bin

Pour les autres systèmes, voir la documentation.

Désinstallation

Pour le désinstaller :

sudo apt purge -y crowdsec crowdsec-firewall-bouncer-iptables
sudo apt autoremove -y
sudo rm -rf /usr/share/crowdsec/ /etc/crowdsec/

Initialisation

Pour démarrer CrowdSec, il faut démarrer le service :

sudo systemctl enable --now crowdsec

Par défaut, crowdsec ne fait que lire les logs et afficher des alertes.

Pour réellement bloquer les adresses IP suite à une décision, il faut installer le bouncer iptables :

apt install -y crowdsec-firewall-bouncer-iptables # Ubuntu/Debian
# Ou
yay -S --noconfirm crowdsec-firewall-bouncer-iptables # Arch Linux

# Démarrer le service
sudo systemctl enable --now crowdsec-firewall-bouncer

Bannir une adresse IP

Pour bannir une adresse IP, voici la commande :

cscli decisions add -t ban -i <IP>

Ou une plage d'adresse IPs :

cscli decisions add -t ban -r <CIDR>

Il n'est pas possible de bannir une IP définitivement, mais vous pouvez utiliser le paramètre -d 999999h pour mettre une durée de +100ans.

Lister les alertes

Vous pouvez lister les attaques détectées par CrowdSec :

cscli alerts list

Et les inspecter plus en détail :

cscli alerts inspect -d <id>

Console de CrowdSec

Et si vous souhaitez relier votre serveur à la Console de CrowdSec (facultatif) :

Cela vous permettra d'ajouter des blocklists facilement.

Ajouter une blocklist manuellement

Le plus simple pour ajouter une blocklist, c'est de passer par la [[#Console de CrowdSec|console]].

Mais il est possible d'importer manuellement une blocklist (ex: https://github.com/firehol/blocklist-ipsets/) :

for ip in $(cat blocklist.txt); do cscli decisions add -t ban -i "$ip"; done

Ajouter une whitelist manuellement

Et si vous souhaitez whitelister des IPs (ex: les IPs de Github), éditez le fichier /etc/crowdsec/parsers/s02-enrich/whitelists.yaml et relancez le service crowdsec.

Vous pouvez aussi créer un fichier /etc/crowdsec/parsers/s02-enrich/custom-whitelist.yaml.

Exemple :

name: custom/zammad-whitelist
description: "Whitelist traffic"
whitelist:
  reason: "Legitimate traffic"
  expression:
    - evt.Line.Raw contains 'zammad'

Pour vérifiez que votre whitelist est bien pris en compte, vous pouvez exécuter un cscli metrics | grep whitelist.

Créez le fichier /etc/crowdsec/postoverflows/s01-whitelist/custom-whitelist.yaml si vous souhaitez l'appliquer uniquement pour un scenario spécifique :

name: custom/zammad-whitelist
description: "Whitelist traffic"
filter: "evt.Overflow.Alert.Scenario == 'custom/http-crawl-non_statics'"
whitelist:
  reason: "Legitimate traffic"
  expression:
    - evt.Line.Raw contains 'zammad'

Vous pouvez vérifier que votre postoverflow existe bien avec cscli postoverflows list.

Voir l'état de CrowdSec

Pour avoir un visuel de l'état de crowdsec :

cscli metrics

Supprimer les faux positifs

Si vous rencontrez un faux positif, vous pouvez modifier les seuils de tolérance :

  1. Identifier la raison du bannissement avec cscli alerts inspect -d <id>
  2. Ajuster le leakspeed (vitesse d'oubli des erreurs), capacity (nombre d'erreurs avant ban) ou filter du scenario
  3. (facultatif) Ou supprimer le scenario en question via cscli decisions remove --scenario <scenario>
  4. Puis redémarrez avec systemctl restart crowdsec ou kill -1 1 (si docker)
  5. Désactiver le ban manuellement avec cscli decisions remove --id <id>

Par exemple, j'ai supprimé le lien symbolique /etc/crowdsec/scenarios/http-generic-bf.yaml et j'ai créer un nouveau fichier /etc/crowdsec/scenarios/http-generic-bf-custom.yaml avec les valeurs suivantes :

--- /etc/crowdsec/hub/scenarios/crowdsecurity/http-generic-bf.yaml
+++ /etc/crowdsec/scenarios/http-generic-bf-custom.yaml
@@ -21,12 +21,12 @@
 # Generic 401 Authorization Errors
 type: leaky
 #debug: true
-name: LePresidente/http-generic-401-bf
+name: custom/http-generic-401-bf
 description: "Detect generic 401 Authorization error brute force"
 filter: "evt.Meta.log_type == 'http_access-log' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '401'"
 groupby: evt.Meta.source_ip
-capacity: 5
-leakspeed: "10s"
+capacity: 10
+leakspeed: "5s"
 blackhole: 1m
 labels:
   confidence: 3
@@ -41,12 +41,12 @@
 # Generic 403 Forbidden (Authorization) Errors
 type: leaky
 #debug: true
-name: LePresidente/http-generic-403-bf
+name: custom/http-generic-403-bf
 description: "Detect generic 403 Forbidden (Authorization) error brute force"
 filter: "evt.Meta.log_type == 'http_access-log' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '403'"
 groupby: evt.Meta.source_ip
-capacity: 5
-leakspeed: "10s"
+capacity: 10
+leakspeed: "5s"
 blackhole: 1m
 labels:
   confidence: 3

Pareil pour le scenario http-crawl-non_statics :

--- /etc/crowdsec/hub/scenarios/crowdsecurity/http-crawl-non_statics.yaml
+++ /etc/crowdsec/scenarios/http-crawl-non_statics-custom.yaml
@@ -1,10 +1,10 @@
 type: leaky
-name: crowdsecurity/http-crawl-non_statics
+name: custom/http-crawl-non_statics
 description: "Detect aggressive crawl on non static resources"
 filter: "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && evt.Parsed.static_ressource == 'false' && evt.Parsed.verb in ['GET', 'HEAD']"
 distinct: "evt.Parsed.file_name"
-leakspeed: 0.5s
-capacity: 40
+leakspeed: 0.2s
+capacity: 100
 #debug: true
 #this limits the memory cache (and event_sequences in output) to five events
 cache_size: 5

Vos nouveaux scenarios devraient apparaitre dans le retour de la commande suivante :

cscli metrics | grep custom

Création d'un scenario personnalisé

Créer un fichier (ex: http-socketio-flood.yaml) dans le dossier /etc/crowdsec/scenarios/ avec le contenu suivant :

type: leaky
name: custom/socketio-flood
description: "Detect Socket.IO polling flood"
filter: "evt.Meta.log_type in ['http_access-log', 'http_request'] && evt.Parsed.request contains '/socket.io/'"
groupby: "evt.Meta.source_ip"
capacity: 40
leakspeed: "1s"
blackhole: 1m
labels:
 service: http
 type: dos
 remediation: true

Ne pas éditer les fichiers dans le dossier /etc/crowdsec/hub/scenarios/crowdsecurity/ car chaque modification peut être écraser par un simple cscli hub update.

Tester la sécurité de son serveur

Pour vérifier si votre configuration de crowdsec fonctionne correctement vous pouvez simuler des attaques.

Par exemple, simuler des tentatives de connexion SSH échouées :

for i in {1..10}; do ssh fakeuser@<IP_ADDRESS>; done

Ou pour tester la sécurité de votre serveur HTTP(S) :

for i in {1..50}; do curl -s "https://example.com/non-existent-page-$i"; done
# Ou
nikto -host https://example.com
note

Effectuer ce test via une autre adresse IP (ex: via un VPN) pour éviter d'être bloqué 😅.

Puis vérifiez les décisions de crowdec :

sudo cscli decisions list

Si une décision apparait, vous ne devriez plus avoir accès au serveur SSH ou HTTP(S) pendant plusieurs heures.

Utilisation avec Traefik

Pour utiliser CrowdSec avec Traefik et Docker Swarm, j'utilise ces 2 stacks docker :

Installation de traefik :

ACCESSLOG=true MIDDLEWARES=crowdsec-bouncer@file ACME_EMAIL=noreply@example.com docker stack deploy -c <(curl -so - https://raw.githubusercontent.com/ethibox/awesome-stacks/master/stacks/traefik.yml) traefik

Installation de crowdsec :

docker stack deploy -c stacks/crowdsec.yml crowdsec

Une fois installé, j'ajoute la configuration suivante dans le fichier /etc/crowdsec/acquis.d/traefik.yaml à l'intérieur du conteneur Crowdsec :

filenames:
  - /var/log/traefik/access.log
labels:
  type: traefik

J'ajoute un fichier dynamic.yml avec le contenu suivant :

http:
  middlewares:
    crowdsec-bouncer:
      forwardAuth:
        address: http://crowdsec_bouncer:8080/api/v1/forwardAuth
        trustForwardHeader: true

Ensuite, je rentre la commande suivante à l'intérieur du conteneur CrowdSec :

docker exec -it $(docker ps -qf name=crowdsec_crowdsec) cscli bouncers add traefik-bouncer
note

Il est possible de devoir exécuter cscli bouncers delete traefik-bouncer avant pour pouvoir récupérer la clé.

Et je redémarre la stack docker avec la variable d'environnement CROWDSEC_BOUNCER_API_KEY qui contient la clé d'api qui s'affiche en sortie de la commande précédente.

Chaque service relié à Traefik sera protégé par CrowdSec.

Si vous exécutez une commande comme dirsearch -u https://example.com sur un de vos sites internet, votre IP sera automatiquement banni pendant 4h.

J'ai quelques erreur au démarrage de traefik :

ERR Error calling http://crowdsec_bouncer:8080/api/v1/forwardAuth error="Get \"http://crowdsec_bouncer:8080/api/v1/forwardAuth\": context canceled" middlewareName=crowdsec-bouncer@file middlewareType=ForwardAuth

Mais cela n'empêche un bon fonctionnement. Cela semble être des faux positifs.

Je vous conseille d'ajouter une tâche cron avec logrotate pour limiter la taille des fichiers de log afin d'éviter de saturer votre stockage :

@daily logrotate -f /etc/logrotate.d/traefik

Avec la configuration suivante dans le fichier /etc/logrotate.d/traefik :

/var/log/traefik/access.log {
    rotate 14
    missingok
    notifempty
    create 644 root root
    postrotate
        docker ps -qf name=traefik_traefik | xargs -r docker kill --signal="USR1"
        docker ps -qf name=crowdsec_crowdsec | xargs -r docker kill --signal="HUP"
    endscript
}

Et pour éviter d'utiliser la collection crowdsecurity/sshd, vu que cela concerne uniquement traefik, je supprime la collection via la commande suivante :

cscli collections remove --force crowdsecurity/sshd

Tester la configuration crowdsec

Pour éviter d'avoir le service crowdsec qui plante lors du changement, vous pouvez tester votre configuration avant :

crowdsec -c /etc/crowdsec/config.yaml -t

Installer une nouvelle collection

Si vous avez des bruteforce sur des application spécifique (ex: wordpress), vous pouvez installer des collections :

cscli collections install crowdsecurity/wordpress
# Ou juste un scenario :
cscli scenarios install crowdsecurity/http-bf-wordpress_bf_xmlrpc
# Ou une liste blanche :
cscli parsers install crowdsecurity/nextcloud-whitelist

Possibilité de chercher des collections ou des scenario depuis les pages suivantes :

Débloquer une IP

cscli alert list --ip <ip>
cscli alert inspect <id>
cat /var/log/traefik/access.log | grep <ip>

Références :