Resolve real client IP behind trusted proxies (closes #94) #127

Merged
clawbot merged 10 commits from issue-94-trusted-proxies into next 2026-09-22 10:25:42 +02:00
3 changed files with 32 additions and 0 deletions
Showing only changes of commit 518e84ce67 - Show all commits
+9
View File
@@ -126,6 +126,15 @@ Configured via YAML file (`--config`). Key settings:
added to the always-enforced built-in ranges (loopback, private, added to the always-enforced built-in ranges (loopback, private,
link-local, CGNAT, benchmark, NAT64, and the like); an invalid CIDR link-local, CGNAT, benchmark, NAT64, and the like); an invalid CIDR
aborts startup aborts startup
- `trusted_proxies` — list of CIDR ranges of the reverse proxies in front
of pixa. `X-Forwarded-For` is believed only when the direct peer falls
inside one of these ranges; the logged and login-recorded client
address is then the rightmost forwarded entry that is not itself a
trusted proxy. Otherwise the direct peer address is used and the header
is ignored, so a client connecting directly cannot spoof its address.
Omitted or empty trusts no one; an invalid CIDR aborts startup. Set
this to your proxy's address range when deploying behind a reverse
proxy
- `upstream_fetch_timeout` — timeout for origin requests - `upstream_fetch_timeout` — timeout for origin requests
- `upstream_max_response_size` — max origin response size - `upstream_max_response_size` — max origin response size
- `downstream_timeout` — client response timeout - `downstream_timeout` — client response timeout
+11
View File
@@ -30,6 +30,17 @@ exhaustion
# Completed Steps # Completed Steps
- 2026-09-21 trusted-proxy client IP resolution (closes #94): a
`trusted_proxies` config key taking a list of CIDRs, parsed by the same
`net/netip` list parser as `blocked_networks` (an invalid entry aborts
startup naming the key and value; omitted or empty trusts no one); a new
`internal/clientip` package resolves the client address by honoring
`X-Forwarded-For` only when the direct peer is a trusted proxy, walking
the chain right-to-left to the rightmost non-proxy entry, so a client
connecting directly cannot spoof its address; the resolved address is
stored in the request context by a new middleware and used by the
request-logging middleware and the login-attempt logs in place of the
raw peer address; documented in `README.md` and `config.example.yml`.
- 2026-09-21 blocked networks configuration extending SSRF protection: a - 2026-09-21 blocked networks configuration extending SSRF protection: a
`blocked_networks` config key taking a list of CIDRs (parsed with `blocked_networks` config key taking a list of CIDRs (parsed with
`net/netip`, an invalid entry aborts startup naming the key and value), `net/netip`, an invalid entry aborts startup naming the key and value),
+12
View File
@@ -31,6 +31,18 @@ allowlist_hosts:
# - 100.64.0.0/10 # - 100.64.0.0/10
# - 2001:db8::/32 # - 2001:db8::/32
# CIDR ranges of the reverse proxies in front of pixa. X-Forwarded-For
# is believed only when the direct peer is inside one of these ranges;
# the client address in the access log and login records is then the
# rightmost forwarded entry that is not itself a trusted proxy. A client
# connecting directly (peer outside these ranges) cannot spoof its
# address: the header is ignored and the peer address is used. Omitted or
# empty trusts no one; an invalid CIDR aborts startup. Set this when
# deploying behind a proxy.
# trusted_proxies:
# - 10.0.0.0/8
# - 2001:db8::/32
# Allow HTTP upstream (only for testing, always use HTTPS in production) # Allow HTTP upstream (only for testing, always use HTTPS in production)
allow_http: false allow_http: false