WAF mit HAProxy und Coraza Rocky: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Konsolidiert: Rocky-Coraza-Fassung als kanonische Seite (bisher drei Fast-Duplikate) |
|||
| (24 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
= WAF-Demo: HAProxy mit Coraza auf Rocky Linux = | == WAF-Demo: HAProxy mit Coraza auf Rocky Linux == | ||
* Animation: [https://xinux.org/waf-haproxy-coraza.html WAF: HAProxy mit Coraza] ([https://xinux.org/waf-haproxy-coraza-einfach.html einfach]) | |||
WAF mit HAProxy und Coraza (OWASP CRS) vor | |||
WAF mit HAProxy und Coraza (OWASP CRS) vor web.it2XX.xinmen.de, TLS-Terminierung auf waf.it2XX.xinmen.de. | |||
==Maschine== | |||
*Wir klonen das Rocky Template | |||
==Vorgaben== | |||
{| class="wikitable" | |||
! Einstellung !! Wert | |||
|- | |||
| '''Name''' || waf.it2XX.xinmen.de | |||
|- | |||
| '''IP-Adresse''' || 10.88.2XX.5/24 | |||
|- | |||
| '''Gateway''' || 10.88.2XX.1 | |||
|- | |||
| '''Nameserver''' || 1.1.1.1 | |||
|- | |||
| '''Search-Domain''' || it2XX.xinmen.de | |||
|- | |||
| '''Benutzername''' || kit | |||
|- | |||
| '''Benutzerpasswort''' || kit | |||
|- | |||
| '''Administrator''' || root | |||
|- | |||
| '''Administratorpasswort''' || radler | |||
|- | |||
| '''Netz''' || DMZ | |||
|} | |||
==Einstellungen== | |||
;Selbterklärend | |||
*rocky-setup.sh -f waf.it2XX.xinmen.de -a 10.88.2XX.5/24 -g 10.88.2XX.1 -n 1.1.1.1 | |||
==Zertifikate besorgen== | |||
*wget https://xinux.de/downloads/script/get-cert.sh | |||
*sudo bash get-cert.sh | |||
== Topologie == | == Topologie == | ||
* | * waf.it2XX.xinmen.de (10.88.2XX.5) – HAProxy terminiert TLS auf Port 443, coraza-spoa läuft lokal auf 127.0.0.1:9000 | ||
* | * web.it2XX.xinmen.de (10.88.2XX.2) – bestehender Backend-Webserver, TLS auf Port 443 | ||
== HAProxy installieren == | == HAProxy installieren == | ||
*dnf install -y haproxy | *dnf install -y haproxy git | ||
== Zertifikat auf dem Reverse Proxy vorbereiten == | == Zertifikat auf dem Reverse Proxy vorbereiten == | ||
| Zeile 18: | Zeile 55: | ||
*chmod 600 /etc/haproxy/own-combined.pem | *chmod 600 /etc/haproxy/own-combined.pem | ||
==Härtung SELinux-Kontext setzen== | |||
*semanage fcontext -a -t cert_t "/etc/haproxy/own-combined\.pem" | *semanage fcontext -a -t cert_t "/etc/haproxy/own-combined\.pem" | ||
*restorecon -v /etc/haproxy/own-combined.pem | *restorecon -v /etc/haproxy/own-combined.pem | ||
| Zeile 33: | Zeile 70: | ||
*semanage port -l | grep http_port_t | *semanage port -l | grep http_port_t | ||
*ls -Z /etc/haproxy/own-combined.pem | *ls -Z /etc/haproxy/own-combined.pem | ||
unconfined_u:object_r:'''cert_t''':s0 /etc/haproxy/own-combined.pem | |||
== Härtung - Haproxy ausgehende Verbindungen erlauben == | |||
*setsebool -P haproxy_connect_any on | |||
*systemctl restart haproxy | |||
== Coraza (coraza-spoa) installieren == | == Coraza (coraza-spoa) installieren == | ||
* | ;coraza-spoa Binary installieren | ||
* | *dnf install -y golang git | ||
*git clone --depth=1 https://github.com/corazawaf/coraza-spoa /usr/local/src/coraza-spoa | |||
*cd /usr/local/src/coraza-spoa | |||
*go run mage.go build | |||
*cp build/coraza-spoa /usr/local/bin/coraza-spoa | |||
*chmod +x /usr/local/bin/coraza-spoa | *chmod +x /usr/local/bin/coraza-spoa | ||
;OWASP Core Rule Set und Basisregeln laden | ;OWASP Core Rule Set und Basisregeln laden | ||
*mkdir -p /etc/coraza-spoa | |||
*git clone --depth=1 https://github.com/coreruleset/coreruleset /etc/coraza-spoa/coreruleset | *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 | *curl -L -o /etc/coraza-spoa/coraza.conf https://raw.githubusercontent.com/corazawaf/coraza/main/coraza.conf-recommended | ||
| Zeile 45: | Zeile 93: | ||
;Coraza-Konfiguration | ;Coraza-Konfiguration | ||
*vim /etc/coraza-spoa/config.yaml | |||
<pre> | <pre> | ||
# /etc/coraza-spoa/config.yaml | # /etc/coraza-spoa/config.yaml | ||
bind: 127.0.0.1:9000 | bind: 127.0.0.1:9000 | ||
log_level: info | |||
log_file: /dev/stdout | |||
log_format: console | |||
applications: | applications: | ||
revproxy: | - name: revproxy | ||
log_level: info | |||
log_file: /dev/stdout | |||
log_format: console | |||
directives: | | directives: | | ||
Include | Include @coraza.conf-recommended | ||
Include /etc/coraza-spoa/crs-setup.conf | Include /etc/coraza-spoa/crs-setup.conf | ||
Include /etc/coraza-spoa/coreruleset/rules/*.conf | Include /etc/coraza-spoa/coreruleset/rules/*.conf | ||
SecRuleEngine On | |||
response_check: false | |||
transaction_ttl_ms: 5000 | |||
</pre> | </pre> | ||
;systemd-Unit | ;systemd-Unit | ||
*vim /etc/systemd/system/coraza-spoa.service | |||
<pre> | <pre> | ||
# /etc/systemd/system/coraza-spoa.service | # /etc/systemd/system/coraza-spoa.service | ||
| Zeile 78: | Zeile 135: | ||
== HAProxy-Konfiguration == | == HAProxy-Konfiguration == | ||
;Konfiguration | |||
*vim /etc/haproxy/haproxy.cfg | |||
<pre> | <pre> | ||
# /etc/haproxy/haproxy.cfg | # /etc/haproxy/haproxy.cfg | ||
| Zeile 92: | Zeile 151: | ||
frontend fe_web | frontend fe_web | ||
bind 10.88.2XX. | bind 10.88.2XX.5:443 ssl crt /etc/haproxy/own-combined.pem | ||
filter spoe engine coraza config /etc/haproxy/coraza.cfg | filter spoe engine coraza config /etc/haproxy/coraza.cfg | ||
http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny } | http-request deny deny_status 403 if { var(txn.coraza.action) -m str deny } | ||
| Zeile 98: | Zeile 157: | ||
backend backend_web | backend backend_web | ||
server web01 10.88.2XX. | server web01 10.88.2XX.2:443 check ssl verify none | ||
backend coraza-spoa | backend coraza-spoa | ||
| Zeile 107: | Zeile 166: | ||
== SPOE-Konfiguration für Coraza == | == SPOE-Konfiguration für Coraza == | ||
*vim /etc/haproxy/coraza.cfg | |||
<pre> | <pre> | ||
[coraza] | [coraza] | ||
spoe-agent coraza-agent | spoe-agent coraza-agent | ||
| Zeile 126: | Zeile 185: | ||
== Eigene Fehlerseite == | == Eigene Fehlerseite == | ||
*mkdir -p /etc/haproxy/errors | |||
*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 | ||
| Zeile 133: | Zeile 193: | ||
<html><body><h1>Anfrage blockiert</h1><p>Diese Anfrage wurde von der Web Application Firewall abgelehnt.</p></body></html> | <html><body><h1>Anfrage blockiert</h1><p>Diese Anfrage wurde von der Web Application Firewall abgelehnt.</p></body></html> | ||
</pre> | </pre> | ||
*haproxy -c -f /etc/haproxy/haproxy.cfg | |||
*systemctl restart haproxy | |||
*systemctl enable --now haproxy | *systemctl enable --now haproxy | ||
== Test == | == Test == | ||
*curl -ik https:// | *curl -ik https://waf.it2XX.xinmen.de/ | ||
*curl -ik "https:// | *curl -ik "https://waf.it2XX.xinmen.de/?id=1' OR '1'='1" | ||
Erste Anfrage: Status 200 von | Erste Anfrage: Status 200 von web.it2XX.xinmen.de. Zweite Anfrage: 403-Fehlerseite, web.it2XX.xinmen.de wird nicht erreicht. | ||
Aktuelle Version vom 31. Oktober 2026, 15:14 Uhr
WAF-Demo: HAProxy mit Coraza auf Rocky Linux
- Animation: WAF: HAProxy mit Coraza (einfach)
WAF mit HAProxy und Coraza (OWASP CRS) vor web.it2XX.xinmen.de, TLS-Terminierung auf waf.it2XX.xinmen.de.
Maschine
- Wir klonen das Rocky Template
Vorgaben
| Einstellung | Wert |
|---|---|
| Name | waf.it2XX.xinmen.de |
| IP-Adresse | 10.88.2XX.5/24 |
| Gateway | 10.88.2XX.1 |
| Nameserver | 1.1.1.1 |
| Search-Domain | it2XX.xinmen.de |
| Benutzername | kit |
| Benutzerpasswort | kit |
| Administrator | root |
| Administratorpasswort | radler |
| Netz | DMZ |
Einstellungen
- Selbterklärend
- rocky-setup.sh -f waf.it2XX.xinmen.de -a 10.88.2XX.5/24 -g 10.88.2XX.1 -n 1.1.1.1
Zertifikate besorgen
- wget https://xinux.de/downloads/script/get-cert.sh
- sudo bash get-cert.sh
Topologie
- waf.it2XX.xinmen.de (10.88.2XX.5) – HAProxy terminiert TLS auf Port 443, coraza-spoa läuft lokal auf 127.0.0.1:9000
- web.it2XX.xinmen.de (10.88.2XX.2) – 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
Härtung 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
unconfined_u:object_r:cert_t:s0 /etc/haproxy/own-combined.pem
Härtung - Haproxy ausgehende Verbindungen erlauben
- setsebool -P haproxy_connect_any on
- systemctl restart haproxy
Coraza (coraza-spoa) installieren
- coraza-spoa Binary installieren
- dnf install -y golang git
- git clone --depth=1 https://github.com/corazawaf/coraza-spoa /usr/local/src/coraza-spoa
- cd /usr/local/src/coraza-spoa
- go run mage.go build
- cp build/coraza-spoa /usr/local/bin/coraza-spoa
- chmod +x /usr/local/bin/coraza-spoa
- OWASP Core Rule Set und Basisregeln laden
- mkdir -p /etc/coraza-spoa
- 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
- vim /etc/coraza-spoa/config.yaml
# /etc/coraza-spoa/config.yaml
bind: 127.0.0.1:9000
log_level: info
log_file: /dev/stdout
log_format: console
applications:
- name: revproxy
log_level: info
log_file: /dev/stdout
log_format: console
directives: |
Include @coraza.conf-recommended
Include /etc/coraza-spoa/crs-setup.conf
Include /etc/coraza-spoa/coreruleset/rules/*.conf
SecRuleEngine On
response_check: false
transaction_ttl_ms: 5000
- systemd-Unit
- vim /etc/systemd/system/coraza-spoa.service
# /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
- Konfiguration
- vim /etc/haproxy/haproxy.cfg
# /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.5: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.2: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
- vim /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>
- haproxy -c -f /etc/haproxy/haproxy.cfg
- systemctl restart haproxy
- systemctl enable --now haproxy
Test
- curl -ik https://waf.it2XX.xinmen.de/
- curl -ik "https://waf.it2XX.xinmen.de/?id=1' OR '1'='1"
Erste Anfrage: Status 200 von web.it2XX.xinmen.de. Zweite Anfrage: 403-Fehlerseite, web.it2XX.xinmen.de wird nicht erreicht.