1. Le principe #
Un plugin et deux rôles.
Deux intégrations distinctes #
Traefik et CrowdSec se complètent de deux façons :
- Détection : CrowdSec lit les logs d'accès de Traefik grâce à la collection
crowdsecurity/traefik. - Blocage : le plugin communautaire
crowdsec-bouncer-traefik-plugininterroge la LAPI et renvoie403aux adresses bannies.
2. La mise en place #
Configuration statique et dynamique.
La clé #
docker compose exec crowdsec cscli bouncers add traefik
# ou, côté image CrowdSec : BOUNCER_KEY_traefik=une-cle-longue-et-aleatoireConfiguration statique #
entryPoints:
web:
address: ":80"
forwardedHeaders:
trustedIPs: # uniquement si un proxy ou un CDN est devant Traefik
- 10.0.0.0/8
accessLog:
filePath: /var/log/traefik/access.log
providers:
file:
filename: /etc/traefik/dynamic.yml
experimental:
plugins:
bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.8.1Redémarrez Traefik : il télécharge le plugin au démarrage. Il a donc besoin d'accéder à Internet à ce moment-là.
Configuration dynamique #
http:
middlewares:
crowdsec:
plugin:
bouncer:
enabled: true
crowdsecMode: stream
updateIntervalSeconds: 15
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec:8080
crowdsecLapiKey: VOTRE_CLE
forwardedHeadersTrustedIPs:
- 10.0.0.0/8
routers:
app:
rule: "Host(`app.example.com`)"
entryPoints: [web]
service: app
middlewares: [crowdsec]
services:
app:
loadBalancer:
servers:
- url: "http://app:8080"Avec les labels Docker :
services:
whoami:
image: traefik/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.middlewares=crowdsec@docker"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecmode=stream"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapihost=crowdsec:8080"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=VOTRE_CLE"Les modes du plugin #
| Mode | Fonctionnement |
|---|---|
none | Une requête à la LAPI par requête reçue |
live | Pareil, avec un cache par IP de defaultDecisionSeconds (60 s). Mode par défaut |
stream | Cache local des IP bannies, synchronisé toutes les updateIntervalSeconds (60 s). Recommandé |
alone | Sans LAPI locale : liste de la CAPI |
appsec | Uniquement l’inspection AppSec |
3. Le piège de l’IP réelle #
Derrière un CDN ou un load balancer.
Le symptôme #
Tout semble fonctionner, mais une IP bannie continue de passer. Nous l'avons reproduit : sans la confiance de l'entrypoint, Traefik écrase X-Forwarded-For. Le plugin voit l'adresse du proxy, jamais celle du client.
| Configuration testée | IP bannie |
|---|---|
Sans forwardedHeaders.trustedIPs sur l’entrypoint | 200 : pas de blocage |
Avec, en mode stream | 403 après la synchronisation |
| Avec, décision supprimée | 200 de nouveau |
La solution #
Il faut déclarer le proxy de confiance à deux endroits : forwardedHeaders.trustedIPs sur l'entrypoint, et forwardedHeadersTrustedIPs dans le plugin. Limitez ces plages à vos vrais proxys : un client ne doit pas pouvoir falsifier son adresse.
Pour exclure votre réseau interne du contrôle, utilisez clientTrustedIPs.
4. Aller plus loin #
Détection et WAF.
Lire les logs de Traefik #
filenames:
- /var/log/traefik/access.log
labels:
type: traefikdocker compose exec crowdsec cscli collections install crowdsecurity/traefik
docker compose exec crowdsec cscli metrics show acquisition parsersActiver AppSec #
crowdsecAppsecEnabled: true
crowdsecAppsecHost: crowdsec:7422
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: trueAttention à la disponibilité. Avec crowdsecAppsecUnreachableBlock: true (valeur par défaut), le site est bloqué si AppSec est injoignable. Choisissez ce comportement en connaissance de cause.Sources #
Blocage vérifié sur Traefik 3.7.17, plugin 1.8.1 et CrowdSec 1.8.2.
Mon suivi
Connectez-vous pour suivre votre progression et prendre des notes. Se connecter
Articles recommandés
Bouncers CrowdSec : Cloudflare, équipements réseau, Kubernetes et bouncer sur mesure
Bloquer au CDN avec Cloudflare Workers, alimenter pfSense ou MikroTik avec Blocklist Mirror, prot...
Les plugins Traefik : l'exemple de CrowdSec pour bloquer les attaques
Étendre Traefik avec des plugins (catalogue officiel, interpréteur Yaegi), puis protéger ses appl...
Les bouncers CrowdSec : principes et bouncer pare-feu
Comprendre les bouncers CrowdSec : où bloquer, modes live et stream, clés d'API, API des décision...
Bouncers CrowdSec pour Nginx, Apache et HAProxy
Mettre en place les bouncers CrowdSec pour Nginx, OpenResty, Apache et HAProxy SPOA : configurati...
Décisions, profils, allowlists et AppSec dans CrowdSec
Gérer les décisions avec cscli, adapter la durée et le type de blocage avec les profils, éviter l...
CrowdSec : comprendre le pare-feu collaboratif
Ce qu'est CrowdSec, comment il détecte et bloque les attaques : Security Engine, parsers, scénari...
Traefik : sécuriser et transformer les requêtes avec les middlewares (BasicAuth, ForwardAuth…)
Les middlewares Traefik modifient les requêtes et réponses entre le routeur et le service : authe...
Observabilité de CrowdSec : IP bannies, attaques bloquées, Prometheus et Grafana
Suivre CrowdSec : cscli metrics, IP bannies, attaques détectées, volume bloqué par les bouncers, ...
Traefik : les logs (journaux applicatifs et access logs)
Configurer les deux journaux de Traefik : le journal de fonctionnement (niveaux, format) et les a...