From d0e925bf707df1ab03bdaaf9fe9e8c3fe25589d4 Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 17 Mar 2026 04:49:49 -0700 Subject: [PATCH] docs: add reverse proxy security note to login rate limiting section --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index d13957c..0ba8204 100644 --- a/README.md +++ b/README.md @@ -2472,6 +2472,27 @@ When the limit is exceeded, the server returns **429 Too Many Requests** with a `Retry-After: 1` header. Stale per-IP entries are automatically cleaned up every 10 minutes. +> **⚠️ Security: Reverse Proxy Required for Production Use** +> +> The rate limiter extracts the client IP by checking the `X-Forwarded-For` +> header first, then `X-Real-IP`, and finally falling back to the TCP +> `RemoteAddr`. Both `X-Forwarded-For` and `X-Real-IP` are **client-controlled +> request headers** — any client can set them to arbitrary values. +> +> Without a properly configured reverse proxy in front of this server: +> +> - An attacker can **bypass rate limiting entirely** by rotating +> `X-Forwarded-For` values on each request (each value is treated as a +> distinct IP). +> - An attacker can **deny service to a specific user** by spoofing that user's +> IP in the `X-Forwarded-For` header, exhausting their rate limit bucket. +> +> **Recommendation:** Always deploy behind a reverse proxy (e.g. nginx, Caddy, +> Traefik) that strips or overwrites incoming `X-Forwarded-For` and `X-Real-IP` +> headers with the actual client IP. If running without a reverse proxy, be +> aware that the rate limiting provides no meaningful protection against a +> targeted attack. + **Why rate limits here but not on session creation?** Session creation is protected by hashcash proof-of-work (stateless, no IP tracking needed). Login involves bcrypt password verification against a registered account — a