WAF mit HAProxy und Coraza Rocky

Aus Xinux Wiki
Version vom 6. August 2026, 04:33 Uhr von Thomas.will (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „= WAF-Demo: HAProxy mit Coraza auf Rocky Linux = == Ziel == Diese Übung zeigt eine minimale Web Application Firewall auf Basis von '''HAProxy''' und '''Coraz…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

WAF-Demo: HAProxy mit Coraza auf Rocky Linux

Ziel

Diese Übung zeigt eine minimale Web Application Firewall auf Basis von HAProxy und Coraza (OWASP CRS) vor einem einfachen Webserver. Gleichzeitig demonstriert der Aufbau, dass Rocky Linux bereits von Haus aus durch firewalld und SELinux gehärtet ist, bevor überhaupt eine WAF ins Spiel kommt. Bewusst nur eine einzige Komponente pro Aufgabe, ein Backend, eine Fehlerseite.

Topologie

Beschreibung

Ein einzelner Rocky-Linux-Host waf01.it2XX.int übernimmt alle Rollen.

  • HAProxy lauscht extern auf Port 80
  • coraza-spoa (WAF-Engine) lauscht nur auf 127.0.0.1:9000
  • httpd (Backend) lauscht nur auf 127.0.0.1:8888

Nur Port 80 (und SSH für die Administration) ist von außen erreichbar. Die interne Kommunikation zwischen HAProxy, Coraza und dem Backend bleibt vollständig auf Loopback.

Backend-Webserver vorbereiten

httpd installieren
  • dnf install -y httpd
Backend auf einen unüblichen Port legen

Wir nutzen bewusst Port 8888 statt 80, um später mit SELinux arbeiten zu müssen statt uns auf den Standard-Kontext zu verlassen.

# /etc/httpd/conf.d/backend.conf
Listen 127.0.0.1:8888
<VirtualHost 127.0.0.1:8888>
    DocumentRoot /var/www/backend
</VirtualHost>
Testseite anlegen
  • mkdir -p /var/www/backend
  • echo "Backend erreichbar" > /var/www/backend/index.html

Härtung mit firewalld

Beschreibung

Von außen darf ausschließlich HTTP (Port 80) und SSH erreichbar sein. Die internen Ports 8888 und 9000 hängen am Loopback und benötigen daher gar keine Freigabe.

  • firewall-cmd --permanent --add-service=http
  • firewall-cmd --permanent --add-service=ssh
  • firewall-cmd --reload
Kontrolle
  • firewall-cmd --list-all

Härtung mit SELinux

Beschreibung

httpd läuft standardmäßig unter dem Typ httpd_t. Port 8888 gehört aber nicht zur Standardliste von http_port_t, daher blockiert SELinux den Start zunächst, obwohl firewalld gar nicht betroffen ist – ein guter Anlass, den Unterschied zwischen Netzwerkfilter und Mandatory Access Control zu zeigen.

Prüfen, welche Ports http_port_t bereits enthält
  • semanage port -l | grep http_port_t
Port 8888 korrekt zu http_port_t hinzufügen
  • semanage port -a -t http_port_t -p tcp 8888

Damit kann sowohl httpd auf 8888 binden als auch HAProxy (Typ haproxy_t) sich dorthin verbinden, ohne die pauschale Boolean haproxy_connect_any aktivieren zu müssen. Bewusst kein chcon, sondern die persistente Policy-Änderung über semanage.

httpd starten und aktivieren
  • systemctl enable --now httpd

HAProxy installieren

  • dnf install -y haproxy

Coraza (coraza-spoa) installieren

Beschreibung

coraza-spoa ist ein eigenständiger Go-Daemon, der als SPOE-Agent für HAProxy arbeitet. Es gibt kein Rocky-Paket, aber ein fertiges Release-Binary, sodass kein Compiler auf dem System nötig ist.

OWASP Core Rule Set und Basisregeln laden
Coraza-Konfiguration
# /etc/coraza-spoa/config.yaml
bind: 127.0.0.1:9000
loglevel: info

applications:
  waf01:
    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

SPOE-Filter einbinden und Backend definieren
# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0
    maxconn 2000

defaults
    mode http
    timeout connect 5s
    timeout client 30s
    timeout server 30s

frontend fe_web
    bind *:80
    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 127.0.0.1:8888 check

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(waf01) 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

Beschreibung

Genau eine Fehlerseite für alle von der WAF geblockten Requests, kein zusätzliches Fehlerseiten-Set.

# /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>
Fehlerseite in haproxy.cfg einbinden

In den defaults-Block ergänzen:

errorfile 403 /etc/haproxy/errors/403-waf.http
  • systemctl enable --now haproxy

Test

Normale Anfrage
Angriffsversuch, der von Coraza/OWASP CRS erkannt werden sollte

Die erste Anfrage liefert die Backend-Testseite mit Status 200, die zweite die eigene 403-Fehlerseite, ohne dass die Anfrage überhaupt das Backend erreicht.

Zusammenfassung

  • firewalld lässt von außen ausschließlich HTTP und SSH zu
  • SELinux verhindert, dass httpd oder HAProxy Ports außerhalb der freigegebenen Policy nutzen, unabhängig von firewalld
  • HAProxy mit Coraza blockiert bekannte Angriffsmuster, bevor sie das Backend erreichen
  • Genau eine Fehlerseite für alle WAF-Blocks