Contenu

CrowdSec AppSec + OpenResty : WAF moderne sans ModSecurity

En bref

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

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