fix(web): trust XFF for real client IP and correct port to 23081
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m41s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m9s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m29s

- Configure nginx `set_real_ip_from` for RFC1918 ranges and enable
  `real_ip_recursive` so allowlists evaluate the true client IP
  instead of Docker's NAT gateway, preventing public exposure of
  `/metrics` and `/nginx_status`
- Update published port from 23181 to 23081 in docker-compose
This commit is contained in:
2026-06-17 06:58:36 -04:00
parent ec4f12d601
commit 4dde063299
2 changed files with 15 additions and 2 deletions

View File

@@ -32,6 +32,19 @@
# resolution at startup and returns 502 after `docker compose restart app`.
resolver 127.0.0.11 valid=10s;
# Recover the real client IP from X-Forwarded-For (set by HAProxy on Titania)
# before evaluating the RFC1918 allowlists below. nginx runs as a sidecar with
# a published port, so every proxied request arrives via Docker's NAT gateway
# (an RFC1918 address) — without this, the allowlists match that gateway and
# pass ALL external traffic, exposing /metrics and /nginx_status publicly.
# HAProxy's own health checks (e.g. to /healthz) carry no XFF and keep their
# real 10.10.x.x source, so they stay allowed.
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Preserve X-Forwarded-Proto from the upstream reverse proxy (HAProxy TLS
# termination on Titania); fall back to $scheme only if there's no upstream
# header. Inside the compose network $scheme is always `http` because HAProxy