Trust reverse proxies at private addresses by default (closes #198) #205

Merged
clawbot merged 1 commits from issue-198-trusted-proxy-default into next 2026-10-27 19:18:35 +01:00
Collaborator

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
clawbot added the needs-review label 2026-10-27 18:52:19 +01:00
clawbot self-assigned this 2026-10-27 18:52:19 +01:00
Author
Collaborator

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

**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
clawbot added needs-rework and removed needs-review labels 2026-10-27 19:05:43 +01:00
clawbot added 1 commit 2026-10-27 19:07:59 +01:00
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
clawbot force-pushed issue-198-trusted-proxy-default from a78c1f5d49 to 355ea53b32 2026-10-27 19:07:59 +01:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-27 19:08:06 +01:00
Author
Collaborator
  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

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
Author
Collaborator

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 next 2026-10-27 19:18:35 +01:00
clawbot deleted branch issue-198-trusted-proxy-default 2026-10-27 19:18:35 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/routewatch#205