Trust reverse proxies at private addresses by default (closes #198)
check / check (push) Canceled after 0s

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
This commit was merged in pull request #205.
This commit is contained in:
2026-10-27 19:18:34 +01:00
parent 281d162e27
commit fb5e98feab
5 changed files with 241 additions and 26 deletions
+22 -4
View File
@@ -30,6 +30,14 @@ const (
maxPort = 65535
)
// The private address ranges of RFC 1918. The HTTP server trusts a reverse
// proxy in any of them when TRUSTED_PROXIES is not set.
const (
privateRange10 = "10.0.0.0/8"
privateRange172 = "172.16.0.0/12"
privateRange192 = "192.168.0.0/16"
)
var (
errRelativeXDGDataHome = errors.New("XDG_DATA_HOME must be an absolute path")
errUnsupportedOS = errors.New("unsupported operating system")
@@ -159,11 +167,21 @@ func getPort() (int, error) {
return int(port), nil
}
// getTrustedProxies returns the addresses and CIDR ranges listed in
// TRUSTED_PROXIES, such as "10.0.0.0/8,192.0.2.1", or none when it is not set.
// An address is returned as a range holding only that address.
// getTrustedProxies returns the reverse proxies the HTTP server trusts. When
// TRUSTED_PROXIES is not set, they are the private ranges of RFC 1918. When it
// is set, they are the addresses and CIDR ranges it lists, such as
// "10.0.0.0/8,192.0.2.1", and none when it is empty. An address is returned as
// a range holding only that address.
func getTrustedProxies() ([]netip.Prefix, error) {
value := os.Getenv("TRUSTED_PROXIES")
value, set := os.LookupEnv("TRUSTED_PROXIES")
if !set {
return []netip.Prefix{
netip.MustParsePrefix(privateRange10),
netip.MustParsePrefix(privateRange172),
netip.MustParsePrefix(privateRange192),
}, nil
}
if value == "" {
return nil, nil
}