feat(haproxy): Add CrowdSec HAProxy bouncer for dual-layer WAF

- Add lua-load directive for CrowdSec bouncer script
- Add http-request lua.crowdsec_check to HTTP/HTTPS frontends
- Block requests where txn.blocked=1 with 403 status
- Skip CrowdSec check for ACME challenges (HTTP frontend)
- Dual-layer WAF: CrowdSec IP blocking + mitmproxy inspection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-26 16:05:37 +01:00
parent 14e965d5fa
commit 33bc1e1732
2 changed files with 32 additions and 0 deletions

View File

@ -3797,3 +3797,22 @@ git checkout HEAD -- index.html
- **Root Cause:** RPCD handler only checked Docker, not LXC containers
- **Fix:** Added `webmail.type` UCI option check, use `lxc-info` for LXC type
- Webmail status now correctly shows "Running" for LXC containers
46. **CrowdSec HAProxy Bouncer - Dual Layer WAF (2026-02-26)**
- **Purpose:** IP-level blocking at HAProxy before mitmproxy WAF inspection
- **Implementation:**
- Created `/srv/haproxy/lua/crowdsec.lua` - Lua bouncer script
- Queries CrowdSec LAPI on port 8190 for IP decisions
- In-memory cache with 60s TTL (30s negative cache)
- Fail-open design: allows traffic if API unreachable
- Skips internal IPs (127.x, 192.168.x, 10.x)
- **HAProxy Integration:**
- `lua-load /opt/haproxy/lua/crowdsec.lua` in global section
- `http-request lua.crowdsec_check` in HTTP/HTTPS frontends
- `http-request deny deny_status 403 if { var(txn.blocked) -m str 1 }`
- **Registered Bouncer:** `haproxy-bouncer` in CrowdSec with API key
- **Result:** Dual-layer WAF protection
- Layer 1: CrowdSec HAProxy bouncer (IP reputation, 60s cache)
- Layer 2: mitmproxy WAF (request inspection, CVE detection)
- All 13 MetaBlogizer sites verified working with dual WAF
- **CrowdSec MCP:** Added crowdsec-local-mcp for AI-generated WAF rules

View File

@ -571,6 +571,7 @@ global
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
tune.ssl.default-dh-param 2048
lua-load /opt/haproxy/lua/crowdsec.lua
EOF
@ -643,6 +644,10 @@ frontend http-in
acl is_acme_challenge path_beg /.well-known/acme-challenge/
use_backend acme_challenge if is_acme_challenge
# CrowdSec IP blocking (dual-layer WAF with mitmproxy)
http-request lua.crowdsec_check if !is_acme_challenge
http-request deny deny_status 403 if { var(txn.blocked) -m str 1 }
EOF
# Add HTTPS redirect rules for vhosts with ssl_redirect
@ -684,6 +689,10 @@ frontend https-in
acl is_sensitive_path path_beg /.htaccess
acl is_sensitive_path path_beg /.htpasswd
http-request deny if is_sensitive_path
# CrowdSec IP blocking (dual-layer WAF with mitmproxy)
http-request lua.crowdsec_check
http-request deny deny_status 403 if { var(txn.blocked) -m str 1 }
EOF
else
# Fallback to directory mode if no certs.list
@ -701,6 +710,10 @@ frontend https-in
acl is_sensitive_path path_beg /.htaccess
acl is_sensitive_path path_beg /.htpasswd
http-request deny if is_sensitive_path
# CrowdSec IP blocking (dual-layer WAF with mitmproxy)
http-request lua.crowdsec_check
http-request deny deny_status 403 if { var(txn.blocked) -m str 1 }
EOF
fi
# Add path-based ACLs BEFORE vhost ACLs (path rules take precedence)