feat(auth): SA3 — trusted-proxy X-Forwarded-For for rate limiting
_client_ip trusted the first X-Forwarded-For hop unconditionally, so anyone able to reach the app port could forge XFF and dodge the login/register/reset/demo rate limits. Now trust XFF ONLY when the request's socket peer is a configured reverse proxy (settings.trusted_proxy_ips, e.g. the VPS Caddy's WireGuard peer IP), and take the RIGHTMOST entry — the client our proxy actually saw and appended, immune to a client pre-seeding a fake XFF. A request from any other peer (hitting the port directly) is keyed on its real socket IP, so XFF can't be forged to bypass the limits. New TRUSTED_PROXY_IPS env (empty default = no proxy, use the direct peer). Documented in .env.example, docs/self-hosting.md, README. Unit-verified against spoof-through-proxy and direct-bypass cases.
This commit is contained in:
parent
2eca56d68a
commit
7297dbd2a8
5 changed files with 52 additions and 7 deletions
10
.env.example
10
.env.example
|
|
@ -31,6 +31,16 @@ ADMIN_EMAILS=
|
|||
# Optional: origin of a separately-served frontend dev server (enables CORS). Leave empty in production.
|
||||
FRONTEND_ORIGIN=
|
||||
|
||||
# Reverse-proxy trust for rate limiting. If you run the app behind a reverse proxy (Caddy/Nginx/
|
||||
# Traefik…) that terminates TLS, set this to the IP the proxy CONNECTS FROM as the app sees it — the
|
||||
# proxy's address on the app's network (e.g. the Docker/host/VPN IP), NOT the public client IP. Then
|
||||
# the login/registration/password-reset rate limiters key on the real client (read from the proxy's
|
||||
# X-Forwarded-For) instead of the proxy's own IP. Requests arriving from any OTHER peer (e.g. someone
|
||||
# hitting the container port directly) are not trusted and are rate-limited by their real socket IP,
|
||||
# so X-Forwarded-For can't be forged to dodge the limits. Comma-separated. Leave EMPTY if the app is
|
||||
# directly exposed with no proxy (then the direct socket IP is used). Example: TRUSTED_PROXY_IPS=10.10.0.1
|
||||
TRUSTED_PROXY_IPS=
|
||||
|
||||
# Optional YouTube Data API key (Google Cloud Console -> Credentials -> Create API key).
|
||||
# When set, all public reads (channels/videos/playlist backfill + enrichment) use the key
|
||||
# instead of a user's OAuth token, so 24/7 backfill never depends on a refresh token that
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue