Coraza WAF via SPOE: Unterschied zwischen den Versionen
| Zeile 108: | Zeile 108: | ||
Im <code>frontend ft_https</code> ergänzen: | Im <code>frontend ft_https</code> ergänzen: | ||
| − | < | + | <pre> |
frontend ft_https | frontend ft_https | ||
| − | bind 10.88.2XX.41:443 ssl crt /etc/haproxy/ssl/revproxy.pem alpn http/1.1 | + | <span style="color:#60a5fa">bind 10.88.2XX.41:443 ssl crt /etc/haproxy/ssl/revproxy.pem alpn http/1.1</span> |
# ... bestehende Einträge ... | # ... bestehende Einträge ... | ||
| − | filter spoe engine coraza config /etc/haproxy/coraza.cfg | + | <span style="color:#a855f7">filter spoe engine coraza config /etc/haproxy/coraza.cfg</span> |
| − | http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny } | + | <span style="color:#a855f7">http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny }</span> |
| − | </ | + | </pre> |
Backend für den Coraza-SPOA hinzufügen: | Backend für den Coraza-SPOA hinzufügen: | ||
| − | < | + | <pre> |
| − | backend coraza-spoa | + | <span style="color:#a855f7">backend coraza-spoa</span> |
| − | mode tcp | + | <span style="color:#a855f7">mode tcp</span> |
| − | server coraza 127.0.0.1:9000 | + | <span style="color:#a855f7">server coraza 127.0.0.1:9000</span> |
| − | </ | + | </pre> |
| + | |||
;Wichtig: <code>mode tcp</code> ist zwingend – ohne das schlägt der Config-Check fehl. <code>alpn http/1.1</code> in der bind-Zeile ist erforderlich damit HAProxy eigene Fehlerseiten ausliefert. | ;Wichtig: <code>mode tcp</code> ist zwingend – ohne das schlägt der Config-Check fehl. <code>alpn http/1.1</code> in der bind-Zeile ist erforderlich damit HAProxy eigene Fehlerseiten ausliefert. | ||
Version vom 23. Mai 2026, 17:21 Uhr
Was ist das?
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.
Schaubild
Installation des SPOE-Agents
Coraza läuft als eigenständiger Prozess neben HAProxy. Das Binary wird direkt aus dem Quellcode gebaut – Go ist dafür erforderlich.
apt install -y golang-go git
git clone https://github.com/corazawaf/coraza-spoa.git /opt/coraza-spoa
cd /opt/coraza-spoa
go build -o /usr/local/bin/coraza-spoa .
cd /
- Hinweis
./...funktioniert hier nicht, da das Repo mehrere Packages enthält. Das Binary landet direkt unter/usr/local/bin/– kein separatercp-Schritt nötig.
Coraza-Konfiguration
Die Konfiguration erfolgt als YAML-Datei. Die OWASP-Regeln (@owasp_crs/) sind im Binary eingebaut – ein separater CRS-Clone ist nicht nötig.
- mkdir -p /etc/coraza-spoa
- mkdir -p /var/log/coraza
- chown haproxy:haproxy /var/log/coraza
- chmod 750 /var/log/coraza
- nano /etc/coraza-spoa/coraza-spoa.yaml
bind: 127.0.0.1:9000
log_level: info
log_file: /var/log/coraza/coraza-spoa.log
log_format: json
default_application: sample_app
applications:
- name: sample_app
directives: |
Include @coraza.conf-recommended
Include @crs-setup.conf.example
Include @owasp_crs/*.conf
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecAuditLog /var/log/coraza/audit.log
SecAuditLogType Serial
SecAuditEngine RelevantOnly
response_check: false
transaction_ttl_ms: 60000
log_level: info
log_file: /var/log/coraza/coraza-spoa.log
log_format: json
- Hinweis
chownundchmodsind zwingend – coraza-spoa läuft als Userhaproxyund benötigt Schreibrecht auf das Log-Verzeichnis.
SPOE-Agent als Systemd-Service
Coraza-SPOA wird als eigener Systemd-Service betrieben. Bei einem Absturz startet systemd den Prozess automatisch neu.
- 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-spoa/coraza-spoa.yaml
Restart=on-failure
User=haproxy
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now coraza-spoa
SPOE-Konfiguration für HAProxy
SPOE (Stream Processing Offload Engine) ist der HAProxy-Mechanismus um Requests an externe Prozesse auszulagern. Die Konfigurationsdatei verbindet HAProxy mit dem laufenden Coraza-Prozess.
- nano /etc/haproxy/coraza.cfg
[coraza]
spoe-agent coraza-agent
messages coraza-req
option var-prefix coraza
option set-on-error error
timeout hello 2s
timeout idle 2m
timeout processing 500ms
use-backend coraza-spoa
spoe-message coraza-req
args app=str(sample_app) id=unique-id src-ip=src src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
event on-frontend-http-request
- Wichtig
- Der Section-Header
[coraza]muss exakt mit dem engine-Namen inhaproxy.cfgübereinstimmen. Leerzeile am Dateiende ist zwingend, sonst meldet HAProxy Missing LF on last line.
HAProxy Konfiguration erweitern
HAProxy übergibt jeden eingehenden Request via SPOE an Coraza. Liefert Coraza den Verdict deny zurück, blockiert HAProxy den Request mit HTTP 403 und zeigt die eigene Fehlerseite an.
Im frontend ft_https ergänzen:
frontend ft_https
<span style="color:#60a5fa">bind 10.88.2XX.41:443 ssl crt /etc/haproxy/ssl/revproxy.pem alpn http/1.1</span>
# ... bestehende Einträge ...
<span style="color:#a855f7">filter spoe engine coraza config /etc/haproxy/coraza.cfg</span>
<span style="color:#a855f7">http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny }</span>
Backend für den Coraza-SPOA hinzufügen:
<span style="color:#a855f7">backend coraza-spoa</span>
<span style="color:#a855f7">mode tcp</span>
<span style="color:#a855f7">server coraza 127.0.0.1:9000</span>
- Wichtig
mode tcpist zwingend – ohne das schlägt der Config-Check fehl.alpn http/1.1in der bind-Zeile ist erforderlich damit HAProxy eigene Fehlerseiten ausliefert.
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
Logs beobachten:
- journalctl -fu coraza-spoa
- tail -f /var/log/coraza/audit.log
