Skip to content

feat(lab11): hardened nginx + WAF sidecar#1564

Open
aylixxx wants to merge 5 commits into
inno-devops-labs:mainfrom
aylixxx:feature/lab11
Open

feat(lab11): hardened nginx + WAF sidecar#1564
aylixxx wants to merge 5 commits into
inno-devops-labs:mainfrom
aylixxx:feature/lab11

Conversation

@aylixxx

@aylixxx aylixxx commented Jul 15, 2026

Copy link
Copy Markdown

Goal

Harden the Nginx reverse proxy in front of Juice Shop with TLS 1.3, a full security-header set, and production-grade rate limiting, connection limiting, timeouts, and cipher hardening, documented with reproducible proof in submissions/lab11.md.

Changes

  • Added: submissions/lab11.md (TLS/header proofs, rate-limit proof, timeout proof, cipher-hardening proof, cert-rotation runbook, OCSP-stapling explanation)
  • Modified: labs/lab11/reverse-proxy/nginx.conf — added HTTP→HTTPS redirect, TLS 1.3-only config, six security headers (HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, CSP-Report-Only), limit_req/limit_conn rate and connection limiting on /rest/user/login, fail-closed timeouts (client_body_timeout, client_header_timeout, proxy_connect_timeout, proxy_read_timeout), Mozilla Modern cipher/curve hardening, and session cache settings
  • Removed: -

Testing

Commands used:

docker compose up -d
docker compose ps

# HTTPS redirect
curl -sI http://localhost:8080 | tee results/http-redirect.txt

# TLS 1.3 negotiation
echo | openssl s_client -connect localhost:8443 -tls1_3 -brief 2>&1 | head -8 | tee results/tls13.txt

# Security headers
curl -skI https://localhost:8443 | tee results/headers.txt

# Rate limit (60 concurrent requests to login)
seq 1 60 | xargs -n1 -P 30 -I{} curl -sk -o /dev/null -w "%{http_code}\n" \
  -X POST -H "Content-Type: application/json" \
  -d '{"email":"test@test.com","password":"wrong"}' \
  https://localhost:8443/rest/user/login | sort | uniq -c | tee results/ratelimit.txt

# Timeout (incomplete request, client_header_timeout)
time python3 - <<'EOF' | tee results/timeout.txt
import socket, time
s = socket.create_connection(("localhost", 8080))
s.sendall(b"GET / HTTP/1.0\r\n")
start = time.time()
data = s.recv(4096)
print("Server responded:", data)
print(f"Elapsed: {time.time()-start:.2f}s")
s.close()
EOF

# Cipher hardening
echo | openssl s_client -connect localhost:8443 -tls1_3 -brief 2>&1 | tee results/cipher.txt

Observed results:

HTTP redirect: 301 → https://localhost:8443/

TLS 1.3: Protocol version: TLSv1.3

Security headers: all 6 present (HSTS, X-Content-Type-Options, X-Frame-Options,
Referrer-Policy, Permissions-Policy, Content-Security-Policy-Report-Only)

Rate limit (60 requests):
  6 401
  54 429

Timeout:
  Server responded: b''
  Elapsed: 10.02s

Cipher hardening:
  Protocol version: TLSv1.3
  Ciphersuite: TLS_AES_256_GCM_SHA384
  Peer Temp Key: X25519, 253 bits

Artifacts & Screenshots

Checklist

  • Title is clear (feat(lab11): <topic>)
  • No secrets/large temp files committed
  • Submission file at submissions/lab11.md exists
  • Task 1 — TLS 1.3 + 6 security headers (with proof)
  • Task 2 — Rate limit + timeouts + cipher hardening + cert-rotation runbook
  • Bonus — Coraza/ModSec WAF + OWASP CRS catching a payload Nginx-alone passes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant