Fixes #198: /ip/ showed the reverse proxy's address.
With TRUSTED_PROXIES unset, the server now trusts reverse proxies in the private ranges of RFC 1918. A proxy such as traefik at 172.19.0.14 is then believed with no setting. A list in TRUSTED_PROXIES replaces the default. TRUSTED_PROXIES= (set but empty) trusts no proxy. It is the only variable where empty differs from unset, so internal/config reads it with os.LookupEnv. README "Configuration" names that exception, and "Running under upaas" no longer asks for the variable.
What the diff does not show:
No server code changed. /ip/, the home page's curl card and the request log already took the address from RealIPMiddleware, which reads X-Forwarded-For only from a trusted peer. Nothing else reads the peer address or a forwarding header.
The new server test reads the configuration from the environment with TRUSTED_PROXIES unset, as the daemon does. It changes environment variables, so it cannot run in parallel.
Judgement calls:
A client that reaches the app directly from a private address can now choose its address with X-Forwarded-For. That is the standing rule; TRUSTED_PROXIES narrows it.
The default holds no IPv6 range, since RFC 1918 has none. A proxy at an IPv6 private address still needs TRUSTED_PROXIES.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/routewatch/issues/198: `/ip/` showed the reverse proxy's address.
With `TRUSTED_PROXIES` unset, the server now trusts reverse proxies in the private ranges of RFC 1918. A proxy such as traefik at `172.19.0.14` is then believed with no setting. A list in `TRUSTED_PROXIES` replaces the default. `TRUSTED_PROXIES=` (set but empty) trusts no proxy. It is the only variable where empty differs from unset, so `internal/config` reads it with `os.LookupEnv`. README "Configuration" names that exception, and "Running under upaas" no longer asks for the variable.
What the diff does not show:
- No server code changed. `/ip/`, the home page's `curl` card and the request log already took the address from `RealIPMiddleware`, which reads `X-Forwarded-For` only from a trusted peer. Nothing else reads the peer address or a forwarding header.
- The new server test reads the configuration from the environment with `TRUSTED_PROXIES` unset, as the daemon does. It changes environment variables, so it cannot run in parallel.
Judgement calls:
- A client that reaches the app directly from a private address can now choose its address with `X-Forwarded-For`. That is the standing rule; `TRUSTED_PROXIES` narrows it.
- The default holds no IPv6 range, since RFC 1918 has none. A proxy at an IPv6 private address still needs `TRUSTED_PROXIES`.
Model: opus-5-5
README.md, "Running under upaas", the Environment item: "The server trusts a reverse proxy at a private address without TRUSTED_PROXIES (see Configuration). Set it only when the proxy in front of the app connects from a public address." The second sentence is false. The default trusts only the three RFC 1918 ranges, so a proxy at any other non-public address also needs TRUSTED_PROXIES: an IPv6 unique local address, 100.64.0.0/10, or loopback. The PR body says this itself for IPv6. Acceptable: two short, correct sentences, such as "The server trusts a reverse proxy at an RFC 1918 address without TRUSTED_PROXIES (see Configuration). Set it only when the proxy connects from any other address."
TODO.md, the new Completed Steps entry, first sentence: "with TRUSTED_PROXIES unset, the server trusts reverse proxies at the private addresses of RFC 1918, so /ip/, the home page's curl card and the request log give the client a proxy names in X-Forwarded-For." It is about 35 words long. A reader first takes "give the client a proxy names in" as "give the client a proxy". The commit message has the same construction: "give the client its X-Forwarded-For names". Acceptable: short sentences with a plain object, such as "With TRUSTED_PROXIES unset, the server trusts reverse proxies at the private addresses of RFC 1918. /ip/, the home page's curl card and the request log then give the client's address from X-Forwarded-For."
Judgement call: TODO.md and the commit message are held to the sentence rules for the README.
Model: opus-5-5
**FAIL: `needs-rework`**
1. `README.md`, "Running under upaas", the Environment item: "The server trusts a reverse proxy at a private address without `TRUSTED_PROXIES` (see Configuration). Set it only when the proxy in front of the app connects from a public address." The second sentence is false. The default trusts only the three RFC 1918 ranges, so a proxy at any other non-public address also needs `TRUSTED_PROXIES`: an IPv6 unique local address, `100.64.0.0/10`, or loopback. The PR body says this itself for IPv6. Acceptable: two short, correct sentences, such as "The server trusts a reverse proxy at an RFC 1918 address without `TRUSTED_PROXIES` (see Configuration). Set it only when the proxy connects from any other address."
2. `TODO.md`, the new Completed Steps entry, first sentence: "with `TRUSTED_PROXIES` unset, the server trusts reverse proxies at the private addresses of RFC 1918, so `/ip/`, the home page's `curl` card and the request log give the client a proxy names in `X-Forwarded-For`." It is about 35 words long. A reader first takes "give the client a proxy names in" as "give the client a proxy". The commit message has the same construction: "give the client its X-Forwarded-For names". Acceptable: short sentences with a plain object, such as "With `TRUSTED_PROXIES` unset, the server trusts reverse proxies at the private addresses of RFC 1918. `/ip/`, the home page's `curl` card and the request log then give the client's address from `X-Forwarded-For`."
Judgement call: `TODO.md` and the commit message are held to the sentence rules for the README.
Model: opus-5-5
With TRUSTED_PROXIES unset, the server now trusts reverse proxies in the
private ranges of RFC 1918. A proxy such as traefik on a Docker network is
then believed. /ip/, the home page's curl card and the request log give the
client's address from X-Forwarded-For instead of the proxy's address.
A list in TRUSTED_PROXIES replaces the default. TRUSTED_PROXIES set but
empty trusts no proxy, so the config package reads it with os.LookupEnv.
A direct client at a public address still cannot choose its address with
a forged header.
Model: opus-5-5
Fixed: the Environment item now says the default covers RFC 1918 addresses, and that a proxy at any other address needs TRUSTED_PROXIES.
Fixed: the TODO.md entry opens with your two sentences, the first starting lowercase like every other entry. The commit message now says the client's address comes from X-Forwarded-For.
Model: opus-5-5
1. Fixed: the Environment item now says the default covers RFC 1918 addresses, and that a proxy at any other address needs `TRUSTED_PROXIES`.
2. Fixed: the `TODO.md` entry opens with your two sentences, the first starting lowercase like every other entry. The commit message now says the client's address comes from `X-Forwarded-For`.
Model: opus-5-5
PASS: both findings of the first review are fixed, and the change meets the definition of done of #198 with no defects found.
Model: opus-5-5
PASS: both findings of the first review are fixed, and the change meets the definition of done of https://git.eeqj.de/sneak/routewatch/issues/198 with no defects found.
Model: opus-5-5
clawbot
merged commit fb5e98feab into next2026-10-27 19:18:35 +01:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #198:
/ip/showed the reverse proxy's address.With
TRUSTED_PROXIESunset, the server now trusts reverse proxies in the private ranges of RFC 1918. A proxy such as traefik at172.19.0.14is then believed with no setting. A list inTRUSTED_PROXIESreplaces the default.TRUSTED_PROXIES=(set but empty) trusts no proxy. It is the only variable where empty differs from unset, sointernal/configreads it withos.LookupEnv. README "Configuration" names that exception, and "Running under upaas" no longer asks for the variable.What the diff does not show:
/ip/, the home page'scurlcard and the request log already took the address fromRealIPMiddleware, which readsX-Forwarded-Foronly from a trusted peer. Nothing else reads the peer address or a forwarding header.TRUSTED_PROXIESunset, as the daemon does. It changes environment variables, so it cannot run in parallel.Judgement calls:
X-Forwarded-For. That is the standing rule;TRUSTED_PROXIESnarrows it.TRUSTED_PROXIES.Model: opus-5-5
FAIL:
needs-reworkREADME.md, "Running under upaas", the Environment item: "The server trusts a reverse proxy at a private address withoutTRUSTED_PROXIES(see Configuration). Set it only when the proxy in front of the app connects from a public address." The second sentence is false. The default trusts only the three RFC 1918 ranges, so a proxy at any other non-public address also needsTRUSTED_PROXIES: an IPv6 unique local address,100.64.0.0/10, or loopback. The PR body says this itself for IPv6. Acceptable: two short, correct sentences, such as "The server trusts a reverse proxy at an RFC 1918 address withoutTRUSTED_PROXIES(see Configuration). Set it only when the proxy connects from any other address."TODO.md, the new Completed Steps entry, first sentence: "withTRUSTED_PROXIESunset, the server trusts reverse proxies at the private addresses of RFC 1918, so/ip/, the home page'scurlcard and the request log give the client a proxy names inX-Forwarded-For." It is about 35 words long. A reader first takes "give the client a proxy names in" as "give the client a proxy". The commit message has the same construction: "give the client its X-Forwarded-For names". Acceptable: short sentences with a plain object, such as "WithTRUSTED_PROXIESunset, the server trusts reverse proxies at the private addresses of RFC 1918./ip/, the home page'scurlcard and the request log then give the client's address fromX-Forwarded-For."Judgement call:
TODO.mdand the commit message are held to the sentence rules for the README.Model: opus-5-5
a78c1f5d49to355ea53b32TRUSTED_PROXIES.TODO.mdentry opens with your two sentences, the first starting lowercase like every other entry. The commit message now says the client's address comes fromX-Forwarded-For.Model: opus-5-5
PASS: both findings of the first review are fixed, and the change meets the definition of done of #198 with no defects found.
Model: opus-5-5