Challenges - Reverse Proxy & TLS
Manuelle Proxy-Konfiguration, Security-Entscheidungen und TLS von Grund auf.
Wo laufen die Kommandos? (Windows)
Stack steuern geht aus PowerShell (scripts/workshop.ps1) oder WSL. Aber alle Test-Kommandos (curl, openssl, grep, for-Schleifen, ./scripts/compose.sh) laufen im WSL-Terminal (bash).
Warnung: In PowerShell ist curl ein Alias fuer Invoke-WebRequest und versteht -I/-k/--cacert nicht. Immer im WSL-Terminal testen.
Abgabe-Format
- 1-3 Minuten Demo
- Done-Check live ausfuehren
- 2-3 Saetze: was, warum, welche Wirkung
Easy
Easy 1) Routing verstehen (aktiv)
nginx-Doku: location · proxy_pass
Muss: zuerst in proxy/nginx.conf nachsehen, dann testen.
Warum wichtig: Routing ist die Grundfunktion jedes Reverse Proxys - ohne sauberes Matching ist alles andere instabil.
- Welche
locationmatched/service/a? - Welcher
upstreamwird verwendet?
Zielzustand: Du kannst Location → Upstream → Backend benennen und begruenden, warum A und B unterschiedlich antworten.
curl http://localhost:8080/service/a # -> "Target A"
curl http://localhost:8080/service/b # -> "Target B"
Easy 2) backend-c hinzufuegen
nginx-Doku: upstream · proxy_pass
Muss: Compose-Service + Upstream + Route /service/c.
Zusatz: backends/c/index.html ist vorhanden und darf angepasst werden.
Warum wichtig: Neue Services kommen laufend dazu; Erweiterungen ohne Seiteneffekte sind Praxisalltag.
Zielzustand: /service/c liefert Backend C; A und B laufen unveraendert weiter.
curl http://localhost:8080/service/c # -> "Reverse Proxy Target C"
curl http://localhost:8080/service/a # -> weiterhin "Target A"
curl http://localhost:8080/service/b # -> weiterhin "Target B"
Easy 3) Eigene Route /demo/a
nginx-Doku: rewrite · location
Muss: Alias-Route bauen, die auf Backend A fuehrt.
Warum wichtig: Der Proxy entkoppelt externe Pfade von internen Backend-Implementierungen.
Zielzustand: /demo/a liefert dieselbe Antwort wie /service/a.
curl http://localhost:8080/demo/a # -> "Target A"
Medium
Medium 4) Security Headers
nginx-Doku: add_header
Setze mindestens nosniff, DENY, strict-origin-when-cross-origin, Permissions-Policy, COOP, CORP.
Optional: CSP fuer statische Seiten.
Warum wichtig: Diese Header reduzieren konkrete Browser-Angriffsvektoren und gehoeren zur Security-Baseline.
Fallstrick: Header im server {}-Block setzen. Sobald in einem location {} ein add_header steht, verwirft Nginx dort alle Server-Header → dann erneut setzen.
Zielzustand: curl -I / zeigt alle geforderten Security-Header.
curl -I http://localhost:8080/ # -> nosniff, DENY, Referrer-Policy, Permissions-Policy, COOP, CORP
Medium 5) Interne Route absichern
nginx-Doku: ngx_http_access_module (allow/deny)
Muss: /internal/status nur fuer 127.0.0.1.
Wichtig: Host-Request zeigt typischerweise 403 (Docker-Netzwerk).
Warum wichtig: Nicht jeder Endpoint darf oeffentlich erreichbar sein; Netzsegmentierung beginnt oft am Proxy.
Zielzustand: Host → 403; container-intern (127.0.0.1) → Antwort.
curl -i http://localhost:8080/internal/status # -> 403 (vom Host)
./scripts/compose.sh exec -T reverse-proxy sh -lc "wget -qO- http://127.0.0.1/internal/status" # -> "internal ok"
Medium 6) Logging verbessern
nginx-Doku: log_format
Eigenes log_format mit Upstream-Infos einbauen.
Hinweis: log_format gehoert in den http {}-Block, sonst startet Nginx nicht.
Warum wichtig: Ohne brauchbare Logs dauert Fehleranalyse deutlich laenger und Incident-Response wird unzuverlaessig.
Zielzustand: Log-Zeile im neuen Format mit Upstream-Infos (upstream=..., urt=...).
curl http://localhost:8080/service/a
./scripts/compose.sh logs reverse-proxy # -> neue Zeile mit upstream=... urt=...
Medium 7) Load Balancing
nginx-Doku: Load Balancing (Guide) · upstream
Zweite Instanz von Backend A (backend-a2) einbauen und Round-Robin zeigen.
Warum wichtig: Lastverteilung ist Kernnutzen eines Reverse Proxys fuer Skalierung und Verfuegbarkeit.
Zielzustand: Ueber mehrere Requests antworten beide Instanzen (Mischung aus A und A2).
for i in $(seq 1 8); do
curl -s http://localhost:8080/service/a | grep -o "INSTANCE=[A-Za-z0-9]*"
done # -> Mischung aus "INSTANCE=A" und "INSTANCE=A2"
Medium 8) Response Header Minimization
nginx-Doku: proxy_hide_header
Mindestens einen Backend-Response-Header per proxy_hide_header ausblenden.
Abgrenzung zu #4: #4 setzt Schutz-Header, #8 entfernt unnoetige Header aus Upstream-Responses.
Warum wichtig: Weniger preisgegebene Metadaten erschweren Fingerprinting und zielgerichtete Angriffe.
Zielzustand: Der ausgeblendete Header (z. B. ETag) fehlt jetzt in der Antwort.
curl -I http://localhost:8080/service/a # -> ETag/Last-Modified nicht mehr vorhanden
Medium 9) Debugging Challenge
nginx-Doku: proxy_pass (Trailing-Slash-Semantik) · upstream
Mit proxy/nginx.broken.conf arbeiten, Fehler finden und reparieren.
Zuerst sichern: diese Challenge ueberschreibt deine nginx.conf → vorher cp proxy/nginx.conf proxy/nginx.conf.bak, am Ende zurueckkopieren.
Warum wichtig: In der Praxis geht es oft um Diagnose unter Zeitdruck, nicht nur um Greenfield-Konfiguration.
Typische Fehler in der kaputten Datei: Upstream-Name-Mismatch, falscher Port, fehlender Trailing Slash in proxy_pass.
Zielzustand: Nach den Fixes liefern A und B wieder ihre Backends; Nginx startet fehlerfrei.
curl http://localhost:8080/service/a # -> "Target A"
curl http://localhost:8080/service/b # -> "Target B"
./scripts/compose.sh logs reverse-proxy
Hard (TLS)
Hard 10) HTTPS von 0 (Easy-RSA)
Doku: HTTPS-Server konfigurieren · ngx_http_ssl_module · Easy-RSA
Zertifikat fuer localhost, Port 8443:443, Root-CA importiert.
Wichtig: Der neue Port ist eine Compose-Aenderung → mit ./scripts/lab.sh redeploy deployen, nicht nur ./scripts/lab.sh proxy-reload.
Warum wichtig: TLS-Grundaufbau ist Voraussetzung fuer vertrauliche und manipulationssichere Kommunikation.
Zielzustand: Aufruf liefert Backend A ohne -k (kein SAN-/Zertifikatsfehler). Zertifikat mit SAN signieren!
curl https://localhost:8443/service/a # -> Backend A, KEIN "SSL certificate problem"
Hard 11) HTTP -> HTTPS Redirect
nginx-Doku: return
Voraussetzung: Challenge 10 abgeschlossen. Bestehende Config weiterverwenden.
Warum wichtig: Redirect verhindert unabsichtliche Klartext-Nutzung und erzwingt den sicheren Transport.
Zielzustand: HTTP auf 8080 antwortet mit 301 und Location: https://localhost:8443/....
curl -I http://localhost:8080/service/a # -> 301, Location: https://localhost:8443/service/a
Hard 12) TLS Haertung + Chain + HSTS
Doku: ssl_protocols · add_header · HSTS (MDN)
Voraussetzung: Challenge 10 und 11 abgeschlossen. Gleiche Config weiter erweitern.
Warum wichtig: Erst Haertung + HSTS reduzieren Downgrade-Risiken und sorgen fuer dauerhaft sichere Clients.
Warnung (HSTS-Falle): Der Browser merkt sich HSTS host-weit fuer localhost (nicht pro Port). Nach https://localhost:8443 wird auch http://localhost:8080 auf https erzwungen. Zum Testen curl nutzen; Browser-HSTS ggf. unter chrome://net-internals/#hsts fuer localhost loeschen. max-age ist im Lab bewusst kurz (1h).
Zielzustand: curl -I zeigt Strict-Transport-Security; s_client verhandelt TLSv1.2/1.3 mit Verify return code: 0 (ok).
curl -I https://localhost:8443/service/a # -> enthaelt Strict-Transport-Security
openssl s_client -connect localhost:8443 -servername localhost
Bonus Expert
Expert 13) Wireshark: HTTP vs HTTPS sauber ausarbeiten
Doku: Wireshark: TLS
Warum wichtig: Sichtbarkeit auf Paketebene macht den Sicherheitsgewinn von TLS fuer alle nachvollziehbar.
- HTTP auf
8080mitschneiden und Klartext zeigen. - HTTPS auf
8443mitschneiden. ClientHello,ServerHello,Certificatemarkieren.- 3-5 Bulletpoints: was ist sichtbar, was ist geschuetzt?
Optional: TLS Decrypt mit SSLKEYLOGFILE.
Zielzustand: HTTP-Mitschnitt zeigt Pfad/Header im Klartext; HTTPS zeigt nur den Handshake, Nutzdaten ohne Key nicht lesbar.
Abgabe: mind. 3 Screenshots + technische Interpretation.