Aller au contenu

Security Stack : Caddy + CrowdSec

La Security Stack est la couche de protection qui se place entre Internet et tous les services de l’infrastructure. Elle combine deux composants :

ComposantRôlePort
CaddyReverse proxy avec TLS automatique et HTTP/380, 443, 443/udp
CrowdSecWAF comportemental et threat intelligence collaborative8080 (interne)
Internet
▼ (ports 80, 443, 443/udp)
┌─────────────────────────────────────────────────────────┐
│ Caddy (security-stack) │
│ ├─ TLS termination (Let's Encrypt, auto-renew) │
│ ├─ HTTP/3 QUIC support │
│ ├─ Security headers (HSTS, CSP, X-Frame-Options) │
│ └─ CrowdSec bouncer module │
└───────────────────────┬─────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ CrowdSec Engine │
│ ├─ Parse Caddy access logs │
│ ├─ Detect attacks (scenarios) │
│ ├─ Apply decisions (ban, captcha) │
│ └─ Share threat intel (CAPI) │
└───────────────────────┬─────────────────────────────────┘
▼ (réseau webproxy)
┌─────────────────────────────────────────────────────────┐
│ Services internes │
│ ┌─────┐ ┌─────────┐ ┌──────┐ ┌────────┐ ┌──────┐ │
│ │ N8N │ │ Grafana │ │ Odoo │ │ ntfy │ │ Blog │ │
│ └─────┘ └─────────┘ └──────┘ └────────┘ └──────┘ │
└─────────────────────────────────────────────────────────┘

CritèreCaddyNginxTraefik
TLS automatiqueNatif (Let’s Encrypt)Certbot externeNatif
HTTP/3 QUICNatifModule expérimentalNon
ConfigurationCaddyfile simplenginx.conf verbeuxYAML/Labels
RechargementSans interruptionReload gracefulSans interruption
CrowdSecModule bouncer officielModule luaPlugin tiers

Critères de décision :

  1. Simplicité — La syntaxe Caddyfile est lisible et concise
  2. TLS zéro-config — Certificats Let’s Encrypt automatiques, pas de cron Certbot
  3. Intégration CrowdSec native — Module bouncer officiel, pas de workaround
FonctionBénéfice
Threat intelligence collaborativeLes IPs malveillantes détectées par d’autres instances CrowdSec sont partagées
Scénarios de détectionRègles prêtes pour HTTP, SSH, CVE connus
Bouncer temps réelLes IPs bannies sont bloquées avant d’atteindre le backend
Whitelists automatiquesBots légitimes (Googlebot, etc.) ne sont pas bloqués

{
# Options globales
email admin@guigpap.com
# Module CrowdSec
crowdsec {
api_url http://crowdsec:8080
api_key {env.CROWDSEC_API_KEY}
ticker_interval 15s
}
}
# Redirection www → apex
www.guigpap.com {
redir https://guigpap.com{uri} permanent
}
# Site principal
guigpap.com {
crowdsec
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
reverse_proxy blog:4321
}
# N8N avec webhooks protégés
n8n.guigpap.com {
crowdsec
# Bloquer les webhooks internes depuis l'extérieur
@blocked_webhooks {
path /webhook/notify/*
path /webhook/prometheus/*
path /webhook/claude/*
path /webhook/claude-simple-chat
path /webhook/docker-controller
path /webhook/odoo/*
}
respond @blocked_webhooks 403
reverse_proxy n8n:5678
}
# Autres services
grafana.guigpap.com {
crowdsec
reverse_proxy grafana:3000
}
odoo.guigpap.com {
crowdsec
reverse_proxy odoo:8069
}
Fenêtre de terminal
# Lister les collections actives
docker exec crowdsec cscli collections list
CollectionRôle
crowdsecurity/caddyParser des logs Caddy
crowdsecurity/base-http-scenariosDétection attaques HTTP courantes
crowdsecurity/http-cveExploits CVE connus
crowdsecurity/appsec-virtual-patchingPatching virtuel
crowdsecurity/linuxScénarios système Linux
crowdsecurity/sshdDétection brute force SSH
crowdsecurity/whitelist-good-actorsListe blanche bots légitimes
  1. Caddy reçoit une requête
  2. Le module bouncer interroge l’API CrowdSec (cache local)
  3. Si l’IP est dans la liste de décisions → 403 Forbidden
  4. Sinon → requête transmise au backend
WebhookAppelé parBloqué depuis Internet
/webhook/notify/*DIUNOui
/webhook/prometheus/*AlertmanagerOui
/webhook/claude/*Claude OllamaOui
/webhook/odoo/*Odoo internalOui
/webhook/docker-controllerTelegram OrchestratorOui

Les services internes appellent ces webhooks via http://n8n:5678 (réseau Docker), pas via le domaine public.

Fenêtre de terminal
# Gestion CrowdSec
docker exec crowdsec cscli decisions list # IPs bannies
docker exec crowdsec cscli decisions delete --ip 1.2.3.4 # Débannir
docker exec crowdsec cscli alerts list # Alertes récentes
docker exec crowdsec cscli metrics # Statistiques
# Gestion Caddy
docker exec caddy caddy validate --config /etc/caddy/Caddyfile
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
docker logs caddy --tail 100

LimiteImpactMitigation
Pas de HA CaddySingle point of failureMonitoring + restart auto
CrowdSec non testé en chargeComportement inconnu sous attaque DDoSRate limiting amont possible
Faux positifs possiblesIPs légitimes potentiellement bloquéesWhitelist manuelle à prévoir

Si des faux positifs apparaissent :

  • Créer des whitelists par IP ou par User-Agent
  • Ajuster les seuils des scénarios (cscli scenarios inspect)
  • Désactiver des scénarios trop agressifs

Si la charge augmente :

  • Activer le mode streaming Caddy pour les gros fichiers
  • Ajouter un cache (Varnish) devant certains services
  • Considérer un CDN (Cloudflare) pour le contenu statique

Si une attaque DDoS survient :

  • CrowdSec détecte mais ne suffit pas seul
  • Activer le mode Under Attack de Cloudflare
  • Contacter l’hébergeur pour mitigation amont
MétriqueSourceSeuil d’attention
IPs bannies/jourcscli decisions list> 100 = vérifier les scénarios
Alertes HTTPcscli alerts listSpike soudain = attaque potentielle
403 responsesLogs CaddyTaux anormal = faux positifs possibles

  • Glossaire — WAF, Bouncer, TLS, Reverse Proxy