HAProxy Erweiterungen
HAProxy Middleware
HAProxy lässt sich durch verschiedene Middleware-Module erweitern, die zwischen Client und Backend Traffic inspizieren, filtern oder transformieren. Die folgenden Module können unabhängig voneinander eingesetzt werden.
Modul 1: Rate Limiting und Security Headers
Beide Funktionen sind nativ in HAProxy verfügbar – kein Zusatztool erforderlich.
Rate Limiting mit Stick Tables
HAProxy kann Requests pro IP begrenzen und bei Überschreitung mit HTTP 429 antworten.
Die folgende Konfiguration ergänzt den bestehenden frontend ft_https und backend backend_www:
- nano /etc/haproxy/haproxy.cfg
# Stick Table im Backend definieren
backend backend_www
stick-table type ip size 100k expire 30s store http_req_rate(10s)
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 50 }
server www 10.88.2XX.11:443 ssl verify none check
- Erklärung
stick-table– speichert Request-Raten pro IP im RAMhttp_req_rate(10s)– zählt Requests innerhalb von 10 Sekundengt 50– blockiert ab mehr als 50 Requests in 10 Sekundendeny_status 429– antwortet mit 429 Too Many Requests
Security Headers
Im frontend ft_https ergänzen:
frontend ft_https
# ... bestehende Konfiguration ...
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
Test
- curl -vk https://revproxy.it2XX.int
In der Ausgabe sollten die gesetzten Header sichtbar sein:
< strict-transport-security: max-age=31536000; includeSubDomains < x-frame-options: SAMEORIGIN < x-content-type-options: nosniff
Rate Limiting testen (z.B. mit ab oder einer Schleife):
- for i in $(seq 1 60); do curl -sk -o /dev/null -w "%{http_code}\n" https://revproxy.it2XX.int; done
Ab Request 51 sollte 429 erscheinen.
Modul 2: CrowdSec HAProxy Bouncer
CrowdSec läuft als IDS/IPS und kommuniziert über den SPOE-Mechanismus direkt mit HAProxy. Blockentscheidungen werden auf Proxy-Ebene getroffen, bevor der Request das Backend erreicht.
- Voraussetzung
- CrowdSec ist installiert und läuft (siehe CrowdSec)
Installation
- apt install crowdsec-haproxy-bouncer
SPOE-Konfiguration
Der Bouncer legt automatisch eine SPOE-Konfigurationsdatei an:
/etc/haproxy/spoe-crowdsec.conf
Inhalt prüfen:
- cat /etc/haproxy/spoe-crowdsec.conf
[config]
spoe-agent crowdsec
messages check-client-ip
option var-prefix crowdsec
timeout hello 100ms
timeout idle 30s
timeout processing 50ms
use-backend crowdsec_backend
spoe-message check-client-ip
args src
event on-client-session
HAProxy Konfiguration erweitern
- nano /etc/haproxy/haproxy.cfg
Im global-Block ergänzen:
global
# ... bestehende Einträge ...
lua-prepend-path /usr/lib/crowdsec/lua/haproxy/?.lua
lua-load /usr/lib/crowdsec/lua/haproxy/crowdsec.lua
setenv CROWDSEC_API_KEY <DEIN_BOUNCER_KEY>
setenv CROWDSEC_API_URL http://127.0.0.1:8080
Im frontend ft_https ergänzen:
frontend ft_https
# ... bestehende Einträge ...
filter spoe engine crowdsec config /etc/haproxy/spoe-crowdsec.conf
http-request lua.crowdsec_allow
http-request deny deny_status 403 if { var(txn.crowdsec.action) -m str "ban" }
Backend für den CrowdSec-Agent hinzufügen:
backend crowdsec_backend
server crowdsec 127.0.0.1:7422
Bouncer-Key generieren
- cscli bouncers add haproxy-bouncer
Den ausgegebenen Key in die HAProxy-Konfiguration unter CROWDSEC_API_KEY eintragen.
Konfiguration testen und neu laden
- haproxy -c -f /etc/haproxy/haproxy.cfg
- systemctl reload haproxy
Test
CrowdSec-Entscheidungen anzeigen:
- cscli decisions list
Eine Test-IP manuell bannen:
- cscli decisions add --ip 10.88.2XX.99 --duration 5m --reason "Test"
Vom gebannten Client aus sollte ein HTTP 403 zurückkommen. Ban wieder entfernen:
- cscli decisions delete --ip 10.88.2XX.99
Logs beobachten:
- journalctl -fu haproxy
- journalctl -fu crowdsec
Modul 3: Coraza WAF via SPOE
Coraza ist eine moderne WAF-Engine (Go), die das OWASP Core Rule Set (CRS) ausführt. Die Integration in HAProxy erfolgt über SPOE – denselben Mechanismus wie bei CrowdSec.
- Hinweis
- Dieses Modul hat den höchsten Einrichtungsaufwand und eignet sich für fortgeschrittene Kurse oder als Demonstrationsobjekt.
Installation des SPOE-Agents
apt install golang git
git clone https://github.com/corazawaf/coraza-spoa.git /opt/coraza-spoa
cd /opt/coraza-spoa
go build -o coraza-spoa ./...
cp coraza-spoa /usr/local/bin/
OWASP Core Rule Set herunterladen
mkdir -p /etc/coraza/crs
git clone https://github.com/coreruleset/coreruleset.git /etc/coraza/crs
cp /etc/coraza/crs/crs-setup.conf.example /etc/coraza/crs/crs-setup.conf
Coraza-Konfiguration
- nano /etc/coraza/coraza.conf
Include /etc/coraza/crs/crs-setup.conf
Include /etc/coraza/crs/rules/*.conf
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecAuditLog /var/log/coraza/audit.log
SecAuditLogType Serial
SecAuditEngine RelevantOnly
- mkdir -p /var/log/coraza
SPOE-Agent als Systemd-Service
- nano /etc/systemd/system/coraza-spoa.service
[Unit]
Description=Coraza SPOA for HAProxy
After=network.target
[Service]
ExecStart=/usr/local/bin/coraza-spoa -config /etc/coraza/coraza.conf
Restart=on-failure
User=haproxy
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now coraza-spoa
SPOE-Konfiguration für HAProxy
- nano /etc/haproxy/spoe-coraza.conf
[config]
spoe-agent coraza
messages coraza-req
option var-prefix coraza
timeout hello 100ms
timeout idle 30s
timeout processing 500ms
use-backend coraza_backend
spoe-message coraza-req
args src method=method path=path query=query ver=req.ver hdrs_bin=req.hdrs.bin body_size=req.body_size body=req.body
event on-frontend-http-request
HAProxy Konfiguration erweitern
Im frontend ft_https ergänzen:
frontend ft_https
# ... bestehende Einträge ...
filter spoe engine coraza config /etc/haproxy/spoe-coraza.conf
http-request deny deny_status 403 if { var(txn.coraza.action) -m str "deny" }
Backend für den Coraza-Agent hinzufügen:
backend coraza_backend
server coraza 127.0.0.1:9000
Konfiguration testen und neu laden
- haproxy -c -f /etc/haproxy/haproxy.cfg
- systemctl reload haproxy
Test
Klassischer WAF-Test mit einem OWASP-typischen Angriff (SQL Injection):
- curl -vk "https://revproxy.it2XX.int/?id=1'+OR+'1'='1"
Erwartet: HTTP 403
XSS-Test:
- curl -vk "https://revproxy.it2XX.int/?q=<script>alert(1)</script>"
Erwartet: HTTP 403
Audit-Log beobachten:
- tail -f /var/log/coraza/audit.log