|
|
| (2 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
| Zeile 5: |
Zeile 5: |
|
| |
|
| ==Modul 1: Rate Limiting und Security Headers== | | ==Modul 1: Rate Limiting und Security Headers== |
| | | *[[HAProxy Rate Limiting und Security Header]] |
| 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 <code>frontend ft_https</code> und <code>backend backend_www</code>:
| |
| | |
| *nano /etc/haproxy/haproxy.cfg
| |
| | |
| <syntaxhighlight lang="text">
| |
| # 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
| |
| </syntaxhighlight>
| |
| | |
| ;Erklärung:
| |
| *<code>stick-table</code> – speichert Request-Raten pro IP im RAM
| |
| *<code>http_req_rate(10s)</code> – zählt Requests innerhalb von 10 Sekunden
| |
| *<code>gt 50</code> – blockiert ab mehr als 50 Requests in 10 Sekunden
| |
| *<code>deny_status 429</code> – antwortet mit ''429 Too Many Requests''
| |
| | |
| ===Security Headers===
| |
| | |
| Im <code>frontend ft_https</code> ergänzen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| 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"
| |
| </syntaxhighlight>
| |
| | |
| ===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 <code>ab</code> 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 <code>429</code> erscheinen.
| |
| | |
| ----
| |
|
| |
|
| ==Modul 2: CrowdSec HAProxy Bouncer== | | ==Modul 2: CrowdSec HAProxy Bouncer== |
| | | *[[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
| |
| | |
| <syntaxhighlight lang="text">
| |
| [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
| |
| </syntaxhighlight>
| |
| | |
| ===HAProxy Konfiguration erweitern===
| |
| | |
| *nano /etc/haproxy/haproxy.cfg
| |
| | |
| Im <code>global</code>-Block ergänzen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| 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
| |
| </syntaxhighlight>
| |
| | |
| Im <code>frontend ft_https</code> ergänzen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| 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" }
| |
| </syntaxhighlight>
| |
| | |
| Backend für den CrowdSec-Agent hinzufügen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| backend crowdsec_backend
| |
| server crowdsec 127.0.0.1:7422
| |
| </syntaxhighlight>
| |
| | |
| ===Bouncer-Key generieren===
| |
| | |
| *cscli bouncers add haproxy-bouncer
| |
| | |
| Den ausgegebenen Key in die HAProxy-Konfiguration unter <code>CROWDSEC_API_KEY</code> 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== | | ==Modul 3: Coraza WAF via SPOE== |
| | | *[[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===
| |
| | |
| <syntaxhighlight lang="bash">
| |
| 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/
| |
| </syntaxhighlight>
| |
| | |
| ===OWASP Core Rule Set herunterladen===
| |
| | |
| <syntaxhighlight lang="bash">
| |
| 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
| |
| </syntaxhighlight>
| |
| | |
| ===Coraza-Konfiguration===
| |
| | |
| *nano /etc/coraza/coraza.conf
| |
| | |
| <syntaxhighlight lang="text">
| |
| 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
| |
| </syntaxhighlight>
| |
| | |
| *mkdir -p /var/log/coraza
| |
| | |
| ===SPOE-Agent als Systemd-Service===
| |
| | |
| *nano /etc/systemd/system/coraza-spoa.service
| |
| | |
| <syntaxhighlight lang="text">
| |
| [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
| |
| </syntaxhighlight>
| |
| | |
| <syntaxhighlight lang="bash">
| |
| systemctl daemon-reload
| |
| systemctl enable --now coraza-spoa
| |
| </syntaxhighlight>
| |
| | |
| ===SPOE-Konfiguration für HAProxy===
| |
| | |
| *nano /etc/haproxy/spoe-coraza.conf
| |
| | |
| <syntaxhighlight lang="text">
| |
| [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
| |
| </syntaxhighlight>
| |
| | |
| ===HAProxy Konfiguration erweitern===
| |
| | |
| Im <code>frontend ft_https</code> ergänzen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| 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" }
| |
| </syntaxhighlight>
| |
| | |
| Backend für den Coraza-Agent hinzufügen:
| |
| | |
| <syntaxhighlight lang="text">
| |
| backend coraza_backend
| |
| server coraza 127.0.0.1:9000
| |
| </syntaxhighlight>
| |
| | |
| ===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
| |