WAF mit HAProxy und Coraza Rocky: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| Zeile 129: | Zeile 129: | ||
*vim /etc/haproxy/errors/403-waf.http | *vim /etc/haproxy/errors/403-waf.http | ||
<pre> | <pre> | ||
| − | |||
HTTP/1.1 403 Forbidden | HTTP/1.1 403 Forbidden | ||
Content-Type: text/html | Content-Type: text/html | ||
Version vom 6. August 2026, 05:12 Uhr
WAF-Demo: HAProxy mit Coraza auf Rocky Linux
Ziel
WAF mit HAProxy und Coraza (OWASP CRS) vor www.it2XX.int, TLS-Terminierung auf revproxy.it2XX.int.
Topologie
- revproxy.it2XX.int (10.88.2XX.41) – HAProxy terminiert TLS auf Port 443, coraza-spoa läuft lokal auf 127.0.0.1:9000
- www.it2XX.int (10.88.2XX.11) – bestehender Backend-Webserver, TLS auf Port 443
HAProxy installieren
- dnf install -y haproxy git
Zertifikat auf dem Reverse Proxy vorbereiten
- Beschreibung
HAProxy erwartet Zertifikat und Key als eine gemeinsame PEM-Datei.
- cat /etc/ssl/own.crt /etc/ssl/own.key > /etc/haproxy/own-combined.pem
- chmod 600 /etc/haproxy/own-combined.pem
- SELinux-Kontext setzen
- semanage fcontext -a -t cert_t "/etc/haproxy/own-combined\.pem"
- restorecon -v /etc/haproxy/own-combined.pem
Härtung mit firewalld (revproxy)
- firewall-cmd --permanent --add-service=https
- firewall-cmd --reload
- Kontrolle
- firewall-cmd --list-services
Härtung mit SELinux (revproxy)
- Kontrolle der Kontexte
- semanage port -l | grep http_port_t
- ls -Z /etc/haproxy/own-combined.pem
Coraza (coraza-spoa) installieren
- mkdir -p /etc/coraza-spoa
- curl -L -o /usr/local/bin/coraza-spoa https://github.com/corazawaf/coraza-spoa/releases/latest/download/coraza-spoa_linux_amd64
- chmod +x /usr/local/bin/coraza-spoa
- OWASP Core Rule Set und Basisregeln laden
- git clone --depth=1 https://github.com/coreruleset/coreruleset /etc/coraza-spoa/coreruleset
- curl -L -o /etc/coraza-spoa/coraza.conf https://raw.githubusercontent.com/corazawaf/coraza/main/coraza.conf-recommended
- cp /etc/coraza-spoa/coreruleset/crs-setup.conf.example /etc/coraza-spoa/crs-setup.conf
- Coraza-Konfiguration
# /etc/coraza-spoa/config.yaml
bind: 127.0.0.1:9000
loglevel: info
applications:
revproxy:
directives: |
Include /etc/coraza-spoa/coraza.conf
SecRuleEngine On
Include /etc/coraza-spoa/crs-setup.conf
Include /etc/coraza-spoa/coreruleset/rules/*.conf
- systemd-Unit
# /etc/systemd/system/coraza-spoa.service [Unit] Description=Coraza SPOA für HAProxy After=network.target [Service] ExecStart=/usr/local/bin/coraza-spoa -config /etc/coraza-spoa/config.yaml Restart=on-failure [Install] WantedBy=multi-user.target
- systemctl daemon-reload
- systemctl enable --now coraza-spoa
HAProxy-Konfiguration
# /etc/haproxy/haproxy.cfg
global
log /dev/log local0
maxconn 2000
defaults
mode http
timeout connect 5s
timeout client 30s
timeout server 30s
errorfile 403 /etc/haproxy/errors/403-waf.http
frontend fe_web
bind 10.88.2XX.41:443 ssl crt /etc/haproxy/own-combined.pem
filter spoe engine coraza config /etc/haproxy/coraza.cfg
http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny }
default_backend backend_web
backend backend_web
server web01 10.88.2XX.11:443 check ssl verify none
backend coraza-spoa
mode tcp
option spop-check
server spoa1 127.0.0.1:9000 check
SPOE-Konfiguration für Coraza
# /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
log global
spoe-message coraza-req
args app=str(revproxy) 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
Eigene Fehlerseite
- mkdir -p /etc/haproxy/errors
- vim /etc/haproxy/errors/403-waf.http
HTTP/1.1 403 Forbidden Content-Type: text/html <html><body><h1>Anfrage blockiert</h1><p>Diese Anfrage wurde von der Web Application Firewall abgelehnt.</p></body></html>
- systemctl enable --now haproxy
Test
- curl -ik https://revproxy.it2XX.int/
- curl -ik "https://revproxy.it2XX.int/?id=1' OR '1'='1"
Erste Anfrage: Status 200 von www.it2XX.int. Zweite Anfrage: 403-Fehlerseite, www.it2XX.int wird nicht erreicht.