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) :
- Inscrivez-vous gratuitement sur https://app.crowdsec.net/signup
- Exécuter la commande
cscli console enroll <key>(la clé est affichée sur https://app.crowdsec.net/security-engines)
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 :
- Identifier la raison du bannissement avec
cscli alerts inspect -d <id> - Ajuster le
leakspeed(vitesse d'oubli des erreurs),capacity(nombre d'erreurs avant ban) oufilterdu scenario - (facultatif) Ou supprimer le scenario en question via
cscli decisions remove --scenario <scenario> - Puis redémarrez avec
systemctl restart crowdsecoukill -1 1(si docker) - 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
noteEffectuer 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
noteIl 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 :
- Korben - Découverte et installation de Crowdsec
- https://docs.crowdsec.net/
- https://crowdsec.net/blog/enhance-docker-compose-security
- https://blog.levassb.ovh/post/crowdsec/
- https://github.com/crowdsecurity/hub/blob/master/collections/crowdsecurity/traefik.yaml
- https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
- https://github.com/fbonalair/traefik-crowdsec-bouncer
- https://app.crowdsec.net/hub/author/crowdsecurity/collections/traefik
- https://blog.stephane-robert.info/docs/securiser/reseaux/crowdsec/
- https://it-connect.fr/reverse-proxy-traefik-integration-de-crowdsec-pour-bloquer-les-attaques/