Sécurisation de la Stack Traefik
Guide de Sécurisation de la Stack Traefik
Warning
Il existe une limitation connue avec le fonctionnement du captcha CrowdSec : si un attaquant réussit à résoudre le captcha une fois, il dispose d'une période de grâce de 30 minutes pendant laquelle ses requêtes ne sont plus vérifiées ni bloquées. Pour des environnements très critiques, il est recommandé d'utiliser des politiques de bannissement direct. Voir l'issue GitHub associée : CrowdSec Issue #5656.
Ce guide documente la mise en place d'un environnement Traefik hautement sécurisé en combinant : 1. La détection d'intrusions active avec CrowdSec pour bloquer ou défier les attaquants en temps réel. 2. Le durcissement passif avec des Security Headers (en-têtes HTTP de sécurité) appliqués de manière globale ou par service.
1. Architecture Globale de Sécurité
Utilisateur ──> [ Traefik (Proxy Inverse) ] ──> [ Applications ]
│
├── En-têtes HTTP de sécurité (HSTS, SAMEORIGIN, etc.)
│
└── [ Plugin CrowdSec (Bouncer) ]
│
├── IP Saine ──> Accès autorisé
├── Décision Captcha ──> Page de défi (Turnstile) ──> Accès autorisé si résolu
└── Décision Ban ──> Code HTTP 403 (Accès interdit)
| Composant | Rôle | Impact de sécurité |
|---|---|---|
| CrowdSec | Analyseur comportemental de logs | Détecte les attaques (brute force, scans agressifs, web-probing). |
| Bouncer Traefik | Agent de remédiation dynamique | Intercepte les connexions suspectes directement au niveau réseau/reverse-proxy. |
| Security Headers | Règles de conformité HTTP | Protège contre le Clickjacking, les injections de scripts (XSS de base) et impose le HTTPS. |
2. Configuration des Security Headers (En-têtes HTTP)
Le durcissement passif s'effectue via un middleware Traefik chargé dynamiquement. Il injecte des en-têtes HTTP de sécurité recommandés par l'OWASP.
A. Fichier de configuration dynamique (variable-security-headers.yaml)
Ce fichier définit le middleware réutilisable security-headers.
http:
middlewares:
security-headers:
headers:
customFrameOptionsValue: "SAMEORIGIN" # Protège contre le Clickjacking tout en autorisant les iframes locales
contentTypeNosniff: true # Empêche les navigateurs de deviner le type MIME (force le respect du Content-Type)
browserXssFilter: true # Active le filtre de protection XSS intégré des anciens navigateurs
referrerPolicy: "strict-origin-when-cross-origin" # Restreint les informations de Referer envoyées lors des requêtes externes
stsSeconds: 604800 # Force le HTTPS (HSTS) pendant 1 semaine (modifiable à 1 an "31536000" après validation)
stsIncludeSubdomains: true # Applique la règle HSTS à tous les sous-domaines
stsPreload: false # Garder à false pendant les phases de test
forceSTSHeader: true # Envoie l'en-tête HSTS y compris sur les réponses d'erreur
B. Activation globale dans Traefik (variable-traefik.yaml)
Pour appliquer ces en-têtes automatiquement à tous les services exposés en HTTPS via le point d'entrée sécurisé (websecure) :
entryPoints:
websecure:
address: :443
# ...
http:
middlewares:
- crowdsec-bouncer@file
- security-headers@file # Applique les en-têtes de sécurité à tous les routeurs liés
3. Configuration de CrowdSec et du Captcha
A. Prérequis : Acquisition des logs (acquis.yaml)
Créez le fichier de déclaration des logs pour CrowdSec dans /opt/crowdsec/crowdsec-config/acquis.yaml afin de lui permettre de lire les logs d'accès de Traefik :
B. Configuration de la whitelist API CrowdSec (config.yaml)
Après le premier lancement de CrowdSec, éditez /opt/crowdsec/crowdsec-config/config.yaml pour autoriser les adresses IP internes de vos conteneurs Docker à interroger l'API locale :
api:
server:
trusted_ips:
- 127.0.0.1
- 172.0.0.0/4 # Réseaux Docker internes
- ::1
prometheus:
enabled: true
listen_addr: 0.0.0.0
listen_port: 6060
C. Fichiers secrets (Clés d'API & Captcha)
Ces fichiers secrets doivent être placés dans le dossier de configuration dynamique de Traefik (ex: /opt/traefik/conf/) :
| Nom du fichier | Description | Méthode d'obtention / Commande |
|---|---|---|
crowdsec-api-key.txt |
Clé d'API du bouncer Traefik | docker exec crowdsec cscli bouncers add <NomDuBouncer> -o raw |
turnstile-site-key.txt |
Clé du site Turnstile (publique) | Générée sur Cloudflare > Turnstile pour votre domaine |
turnstile-secret-key.txt |
Clé secrète Turnstile (privée) | Obtenue sur la même page Cloudflare |
Abstract
Veillez à écrire ces clés sans retour à la ligne à la fin du fichier :
echo -n 'VOTRE_CLE' > /opt/traefik/conf/crowdsec-api-key.txt
4. Déploiement Docker Compose
Voici un exemple générique de configuration Docker Compose intégrant Traefik avec ses montages de volumes de sécurité, et CrowdSec.
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
environment:
GID: "${GID-1000}"
COLLECTIONS: "crowdsecurity/linux crowdsecurity/traefik"
volumes:
- /opt/crowdsec/crowdsec-db:/var/lib/crowdsec/data/
- /opt/crowdsec/crowdsec-config:/etc/crowdsec/
- /opt/traefik/log:/var/log/traefik/:ro
- $INFRASTRUCTURE_FOLDER_LOCATION/variable-crowdsec-profiles.yaml:/etc/crowdsec/profiles.yaml:ro
networks:
- frontend
restart: always
traefik:
image: traefik:latest
container_name: traefik
restart: always
networks:
- frontend
ports:
- "80:80"
- "443:443"
- "8081:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/certs:/etc/traefik/certs/
- /opt/traefik/conf:/etc/traefik/conf/
- /opt/traefik/log:/var/log/traefik/
- /opt/traefik/plugins-storage:/plugins-storage
- $INFRASTRUCTURE_FOLDER_LOCATION/variable-traefik.yaml:/etc/traefik/traefik.yaml:ro
- $INFRASTRUCTURE_FOLDER_LOCATION/variable-crowdsec-middleware.yaml:/etc/traefik/conf/middleware-crowdsec.yaml:ro
- $INFRASTRUCTURE_FOLDER_LOCATION/variable-security-headers.yaml:/etc/traefik/conf/security-headers.yaml:ro
environment:
- CF_DNS_API_TOKEN=$CF_DNS_API_TOKEN
5. Configuration Système : IPv6 Natif Docker
Par défaut, le proxy réseau de Docker (Userland Proxy) masque la véritable adresse IPv6 du client en la remplaçant par celle de la passerelle Docker (ex: fd01::1). Si CrowdSec prend une décision, il bannira la passerelle et bloquera l'accès à tous les clients IPv6.
Il est impératif d'activer le routage IPv6 natif via ip6tables dans le démon Docker de la machine hôte.
Éditez ou créez /etc/docker/daemon.json sur le serveur :
Redémarrez Docker pour appliquer les modifications :
6. Commandes utiles (CrowdSec CLI)
Toutes les commandes s'exécutent au sein du conteneur CrowdSec : docker exec crowdsec cscli ...
Gestion des décisions (Bans & Captchas)
- Lister les décisions actives :
cscli decisions list - Ajouter un captcha manuel (phase de test) :
cscli decisions add --ip <IP> -d 10m --type captcha - Bannir manuellement une adresse IP :
cscli decisions add --ip <IP> -d 24h --type ban - Supprimer une décision active sur une IP :
cscli decisions delete --ip <IP>
Hub & Mises à jour
- Vérifier l'état du bouncer Traefik :
cscli bouncers list - Mettre à jour les signatures et scénarios :
cscli hub update && cscli hub upgrade - Lister les scénarios actifs :
cscli scenarios list