From d31710bd8ef74e5781f11644a2cb6a3ac69d2fac Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 28 Jun 2026 13:10:08 +0200 Subject: [PATCH] docs(clientip): document X-Forwarded-For-only proxy client-IP resolution Update the HTTPS reverse-proxy guide and the trust_forwarded_headers / trusted_proxy_cidrs settings comments to reflect that the client IP is now resolved from X-Forwarded-For only (no longer X-Real-IP / True-Client-IP), read via the request context rather than by rewriting r.RemoteAddr. The nginx example now sets X-Forwarded-For. (Release note staged locally at _/releases/v0_117_0.md, which is gitignored like prior release notes.) Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/content/docs/guides/HTTPS-SETUP.md | 28 ++++++++++++------------- pkg/service/datastore/datastore.go | 16 +++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/content/docs/guides/HTTPS-SETUP.md b/docs/content/docs/guides/HTTPS-SETUP.md index 8bcd151..6aeeeee 100644 --- a/docs/content/docs/guides/HTTPS-SETUP.md +++ b/docs/content/docs/guides/HTTPS-SETUP.md @@ -120,25 +120,25 @@ server { location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` -> **Tell the service to honour `X-Real-IP`/`X-Forwarded-For`.** When deploying -> behind a reverse proxy on the same host as above, set -> `"trust_forwarded_headers": true` in `data/settings.json`. With that flag -> on, the service rewrites `r.RemoteAddr` from the proxy-supplied headers, -> so handlers that act on the source IP (e.g. the Spotify priming triggered -> by `/marge/streaming/support/power_on`) see the speaker's real address -> instead of the proxy's loopback peer. +> **Tell the service to resolve the client IP from `X-Forwarded-For`.** When +> deploying behind a reverse proxy, set `"trust_forwarded_headers": true` in +> `data/settings.json`. With that flag on, the service reads the real client +> IP from `X-Forwarded-For` (chi walks the chain right-to-left, skipping your +> trusted-proxy IPs), so handlers that act on the source IP (e.g. the Spotify +> priming from `/marge/streaming/support/power_on`) see the speaker's real +> address instead of the proxy's. > -> By default only `127.0.0.0/8` and `::1/128` are trusted to set those -> headers. If your reverse proxy lives on a different host, list its CIDR(s) -> in `"trusted_proxy_cidrs"` (e.g. `["10.0.0.0/8"]`). Do **not** enable -> `trust_forwarded_headers` on a flat LAN deployment without a proxy: a -> malicious speaker on the LAN can send the headers itself and spoof its -> source IP. +> By default only `127.0.0.0/8` and `::1/128` are trusted proxy ranges. If +> your reverse proxy lives on a different host, list its CIDR(s) in +> `"trusted_proxy_cidrs"` (the proxy's own IP ranges, e.g. +> `["10.0.0.0/8"]`). Do **not** enable `trust_forwarded_headers` on a flat +> LAN with no proxy: a malicious speaker on the LAN could send +> `X-Forwarded-For` itself and spoof its source IP. --- diff --git a/pkg/service/datastore/datastore.go b/pkg/service/datastore/datastore.go index ba471aa..8419576 100644 --- a/pkg/service/datastore/datastore.go +++ b/pkg/service/datastore/datastore.go @@ -2613,17 +2613,17 @@ type Settings struct { TTSVolume int `json:"tts_volume,omitempty"` // TrustForwardedHeaders enables proxy-aware client IP resolution: when the - // immediate TCP peer is one of the TrustedProxyCIDRs, the X-Real-IP / - // X-Forwarded-For / True-Client-IP headers are honoured and replace - // r.RemoteAddr. Required when the service is fronted by nginx, Caddy, or - // any other reverse proxy. Default false — direct LAN deployments must - // not enable this, otherwise a malicious LAN-resident client could spoof - // its source IP via these headers. + // immediate TCP peer is one of the TrustedProxyCIDRs, the client IP is + // resolved from the X-Forwarded-For header (read via the request context; + // it does not rewrite r.RemoteAddr). Required when the service is fronted + // by nginx, Caddy, or any other reverse proxy. Default false - direct LAN + // deployments must not enable this, otherwise a malicious LAN-resident + // client could spoof its source IP via the X-Forwarded-For header. TrustForwardedHeaders bool `json:"trust_forwarded_headers,omitempty"` // TrustedProxyCIDRs is the list of CIDR blocks whose immediate TCP peers - // are allowed to set X-Forwarded-* headers when TrustForwardedHeaders is - // true. Defaults to loopback (127.0.0.0/8 and ::1/128) — i.e. only a + // are allowed to set X-Forwarded-For headers when TrustForwardedHeaders is + // true. Defaults to loopback (127.0.0.0/8 and ::1/128) - i.e. only a // reverse proxy on the same host. Override only if the proxy lives on a // different host within a known-good private subnet. TrustedProxyCIDRs []string `json:"trusted_proxy_cidrs,omitempty"`