Contenu

CrowdSec AppSec + OpenResty : WAF moderne sans ModSecurity

Après des années avec ModSecurity + OWASP CRS sur nginx, j’ai migré arleo.eu vers une stack plus moderne : CrowdSec AppSec sur OpenResty. Le résultat est une architecture WAF inline mieux intégrée, plus facile à maintenir, et plus cohérente avec le reste de la stack de sécurité.

Pourquoi abandonner ModSecurity ?

ModSecurity v2 est en fin de vie active. Le maintien des règles OWASP CRS sur nginx classique génère de la friction : faux positifs fréquents, logs difficiles à corréler avec CrowdSec, et une configuration dispersée entre plusieurs outils sans vision unifiée.

Le passage à OpenResty (nginx + LuaJIT natif) était déjà motivé par le bouncer CrowdSec qui repose sur Lua. CrowdSec AppSec s’inscrit naturellement dans cette architecture.

Architecture

Internet
   ↓
Cloudflare (CDN + WAF cloud + DDoS)
   ↓
OpenResty (host NUC)
   ↓
Lua bouncer CrowdSec
   ↙              ↘
IP check          AppSec engine
(port 8080)       (port 7422)
                      ↓
               OWASP CRS + règles custom
                      ↓ (si OK)
               VM Hugo (192.168.122.69)

Le bouncer Lua intercepte chaque requête et la soumet en parallèle à deux composants :

  • IP check (8080) : décisions CrowdSec classiques (bans, allowlist)
  • AppSec engine (7422) : analyse WAF inline — OWASP CRS, détection SQLi/XSS/path traversal

Les IPs whitelistées CrowdSec court-circuitent AppSec (ALWAYS_SEND_TO_APPSEC=false), ce qui évite la latence inutile pour les sources de confiance.

Configuration clé du bouncer

# /etc/crowdsec/bouncers/crowdsec-openresty-bouncer.conf
APPSEC_URL=http://127.0.0.1:7422
APPSEC_FAILURE_ACTION=passthrough
APPSEC_CONNECT_TIMEOUT=500
APPSEC_SEND_TIMEOUT=500
APPSEC_PROCESS_TIMEOUT=2000
ALWAYS_SEND_TO_APPSEC=false

APPSEC_FAILURE_ACTION=passthrough est critique : si AppSec est indisponible (redémarrage de l’agent, pic de charge), le trafic passe quand même. Pas de blackout pour un composant WAF défaillant.

Exception pour le endpoint MCP

Le proxy MCP (/mcp) transporte des payloads qui contiennent du code Markdown, bash, ini — ce qui fait monter le score OWASP CRS et déclenche des faux positifs. Une règle d’exception désactive 8 IDs CRS sur ce path uniquement :

# /etc/crowdsec/appsec-rules/mcp-whitelist.yaml
name: crowdsecurity/mcp-whitelist
description: Disable CRS false positives on /mcp endpoint
type: appsec-rule
rules:
  - zones: [METHOD, URI]
    variables: [uri]
    match:
      type: startsWith
      value: /mcp
    actions:
      - disable:932230
      - disable:932235
      - disable:932250
      - disable:932340
      - disable:941400
      - disable:942360
      - disable:949110
      - disable:959100

Avantages par rapport à ModSecurity

Intégration native — AppSec est un composant de l’agent CrowdSec. Les décisions WAF alimentent le même pipeline que les bans IP : logs unifiés dans BetterStack, métriques via cscli metrics show appsec, corrélation immédiate entre attaques applicatives et comportements réseau.

Maintenance simplifiée — les règles OWASP CRS sont gérées via cscli hub update comme n’importe quelle collection CrowdSec. Plus de gestion manuelle de fichiers de règles ModSecurity.

Résilience — le mode passthrough sur failure évite les indisponibilités en cascade. ModSecurity en mode DetectionOnly demandait une gestion séparée du failover.

Performances — AppSec tourne en process séparé de l’agent CrowdSec. OpenResty + LuaJIT maintient des latences faibles, sans le overhead du module Apache/nginx ModSecurity.

Périmètre d’activation

AppSec est actif uniquement sur les vhosts exposés publiquement :

  • www.arleo.eu
  • mcp-hugo.arleo.eu

Vérification rapide

# Tester AppSec directement
curl -s -X POST http://127.0.0.1:7422/ \
  -H "x-crowdsec-appsec-uri: /.env" \
  -H "x-crowdsec-appsec-ip: 1.2.3.4" \
  -H "x-crowdsec-appsec-host: www.arleo.eu" \
  -H "x-crowdsec-appsec-verb: GET"
# Attendu : {"action":"ban","http_status":403}

# Métriques
cscli metrics show appsec

Conclusion

CrowdSec AppSec sur OpenResty remplace ModSecurity de façon cohérente et sans dette technique. L’écosystème CrowdSec couvre maintenant l’ensemble de la stack : détection comportementale (agent), blocage IP (bouncer Lua), WAF inline (AppSec), sync Cloudflare (crowdsec-cf-sync), et monitoring (BetterStack + Vector). Une seule source de vérité pour la sécurité du homelab.


/images/logos/crowdsec-owasp-openresty.webp

Ressources