Traefik est le reverse proxy au cœur de l'infrastructure Docker du homelab. Il gère le routage de toutes les requêtes HTTP/HTTPS vers les conteneurs appropriés, avec gestion automatique des certificats SSL et intégration de la sécurité via CrowdSec.
Les conteneurs redémarrent automatiquement sauf s'ils ont été arrêtés manuellement.
### Accès à l'hôte Docker
```yaml
extra_hosts:
- "host.docker.internal:host-gateway"
```
Cette configuration permet aux conteneurs Traefik d'accéder à l'hôte Docker via le nom `host.docker.internal`, utile pour proxifier des services tournant directement sur l'hôte.
## Instance traefik-public
### Rôle et utilisation
L'instance **traefik-public** gère tous les services **accessibles depuis Internet** :
- Applications web publiques
- APIs exposées
- Services authentifiés mais accessibles de l'extérieur
### Binding réseau
```yaml
ports:
- "192.168.1.2:80:80"
- "192.168.1.2:443:443"
```
Traefik écoute uniquement sur l'IP **192.168.1.2**, correspondant à la première NIC de la VM.
### Entry points
**Port 80 (HTTP)** :
```yaml
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
```
Redirection automatique de HTTP vers HTTPS pour toutes les requêtes.
**Port 443 (HTTPS)** :
```yaml
websecure:
address: ":443"
http:
middlewares:
- crowdsec-bouncer@file
- secheaders@file
- ratelimit@file
transport:
respondingTimeouts:
idleTimeout: 300s
```
Trois middlewares appliqués par défaut sur tous les services publics :
1.**crowdsec-bouncer** : Blocage des IPs malveillantes détectées par CrowdSec
2.**secheaders** : Headers de sécurité HTTP (HSTS, CSP, etc.)
3.**ratelimit** : Limitation du nombre de requêtes
### Middlewares publics
Fichier : `dynamic-public/middlewares.yml`
**ratelimit** :
```yaml
ratelimit:
rateLimit:
average: 100
burst: 50
period: 1s
```
Autorise en moyenne 100 requêtes/seconde avec des pics jusqu'à 50 requêtes supplémentaires.
**secheaders** :
```yaml
secheaders:
headers:
stsSeconds: 31536000
forceSTSHeader: true
```
Force HSTS (HTTP Strict Transport Security) pendant 1 an, obligeant les navigateurs à toujours utiliser HTTPS.
**evasive** :
```yaml
evasive:
rateLimit:
average: 3
burst: 5
period: 1s
```
Rate limiting strict pour les endpoints sensibles (3 req/s en moyenne, 5 en burst).
### Intégration CrowdSec
**CrowdSec** est un système de détection et prévention d'intrusions communautaire. Traefik-public intègre le **bouncer CrowdSec** pour bloquer automatiquement les IPs malveillantes.
**Middleware CrowdSec** (appliqué sur websecure) :
```yaml
middlewares:
- crowdsec-bouncer@file
```
Le bouncer interroge l'API CrowdSec locale pour vérifier si l'IP source est bannie. En cas de match, la requête est bloquée avec un code HTTP 403.
### Certificats SSL
Stockage des certificats :
```yaml
volumes:
- ./letsencrypt-public:/letsencrypt
```
Configuration ACME dans `traefik-public.yml` :
```yaml
certificatesResolvers:
cloudflare:
acme:
email: your-email@example.com
storage: /letsencrypt/cloudflare_acme.json
keyType: EC256
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
```
Les certificats sont automatiquement renouvelés 30 jours avant expiration.
### Logging
```yaml
log:
level: DEBUG
filePath: "/var/log/traefik/traefik.log"
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
```
Logs stockés dans `/var/log/traefik/` sur l'hôte Docker :
- **traefik.log** : Logs système de Traefik (démarrage, erreurs, recharges)
- **access.log** : Logs d'accès au format JSON (requêtes HTTP)
### Configuration provider Docker
```yaml
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik_network
```
- **exposedByDefault: false** : Les conteneurs ne sont pas automatiquement exposés, il faut explicitement ajouter des labels Traefik
- **network: traefik_network** : Traefik utilisera ce réseau pour communiquer avec les conteneurs
- **Ne jamais exposer** de services d'administration via traefik-public
- **Toujours vérifier** l'entrypoint utilisé dans les labels Docker
- **Privilégier** traefik-private pour tout ce qui n'a pas besoin d'être public
### Middlewares de sécurité
- **CrowdSec** : Actif uniquement sur traefik-public, bloque les attaques automatisées
- **localonly** : Appliqué par défaut sur traefik-private
- **ratelimit** : Protection anti-DDoS basique
- **secheaders** : Renforcement de la sécurité côté navigateur
### Gestion des certificats
- **Rotation automatique** : Let's Encrypt renouvelle les certificats tous les 90 jours
- **Backup** : Sauvegarder régulièrement les fichiers `cloudflare_acme.json`
- **Monitoring** : Vérifier les logs pour détecter les échecs de renouvellement
### Logging et monitoring
- **Logs accessibles** : Montés en volumes sur l'hôte pour analyse
- **Format JSON** : Facilite le parsing et l'intégration avec des outils de monitoring
- **Niveau DEBUG** : Utile pour le troubleshooting, peut être réduit en production
## Limites de cette configuration
Bien que fonctionnelle et sécurisée, cette architecture présente certaines limites à connaître :
### Réseau Docker partagé
**Problème** : Les deux instances Traefik (public et private) utilisent le **même réseau Docker** (`traefik_network`). Cela signifie que tous les conteneurs connectés à ce réseau peuvent potentiellement communiquer entre eux, qu'ils soient exposés publiquement ou localement.
**Impact** :
- Un conteneur exposé via traefik-public peut techniquement accéder à un conteneur exposé via traefik-private
- Le cloisonnement réseau n'est pas complet, il repose uniquement sur les IP bindings (192.168.1.2 vs 192.168.1.3)
**Amélioration possible** :
- Créer deux réseaux Docker distincts : `traefik_public_network` et `traefik_private_network`
- Connecter chaque instance Traefik uniquement à son réseau dédié
- Garantir une isolation réseau complète au niveau Docker
### Absence de segmentation VLAN
**Problème** : Les deux NICs de la VM partagent le même réseau physique (192.168.1.0/24) sans segmentation VLAN.
**Impact** :
- Le NIC pour traefik-private (192.168.1.3) a techniquement accès à Internet via la passerelle réseau, alors qu'il n'en a pas besoin
- Pas de cloisonnement réseau au niveau L2/L3 entre les interfaces publique et privée
- En cas de compromission, un attaquant pourrait potentiellement pivoter entre les deux réseaux
**Amélioration possible** :
- **VLAN public** : Placer le NIC de traefik-public (192.168.1.2) dans un VLAN avec accès Internet
- **VLAN privé** : Placer le NIC de traefik-private (192.168.1.3) dans un VLAN isolé, sans accès Internet
- Configurer des règles de firewall strictes entre les VLANs
- Cette segmentation renforcerait considérablement le cloisonnement et limiterait la surface d'attaque
### Accès au socket Docker
**Problème** : Les deux instances Traefik ont un accès **direct et complet** au socket Docker (`/var/run/docker.sock`). Le socket Docker est l'API d'administration de Docker, donnant un contrôle total sur l'hôte.
**Impact sécurité** :
- Un conteneur Traefik compromis pourrait contrôler tous les conteneurs de l'hôte
- Possibilité d'élévation de privilèges (lancer un conteneur en mode privileged, monter des volumes sensibles, etc.)
- Accès en lecture seule (`ro`) limite les dégâts, mais permet toujours d'extraire des informations sensibles (variables d'environnement, secrets, etc.)
**Amélioration possible** :
- Utiliser un **proxy au socket Docker** comme [Tecnativa/docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)
- Ce proxy permet de filtrer finement les opérations autorisées (ex: seulement lire les conteneurs et leurs labels)
- Réduire la surface d'attaque en limitant l'accès API aux endpoints strictement nécessaires à Traefik
Exemple de configuration :
```yaml
docker-socket-proxy:
image: tecnativa/docker-socket-proxy
environment:
CONTAINERS: 1 # Autoriser lecture des conteneurs
NETWORKS: 1 # Autoriser lecture des réseaux
SERVICES: 0 # Interdire accès aux services Swarm
TASKS: 0 # Interdire accès aux tâches Swarm
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
```
Ces améliorations ne sont pas critiques pour un homelab, mais seraient **fortement recommandées en environnement de production**.