diff --git a/README.md b/README.md index 9b5b418..0cad260 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ TTY detection, and security headers are always applied. | `RETENTION_SWEEP_INTERVAL` | How often the retention reaper and archive sweeper run (Go duration, must be positive) | `1h` | | `SESSION_IDLE_TIMEOUT` | Idle session timeout (Go duration) | `24h` | | `RECEIVER_RATE_LIMIT` | Receiver requests/minute per IP per entrypoint (10x that per IP across the route) | `120` | -| `TRUSTED_PROXIES` | CIDRs whose forwarded headers are trusted. A set value replaces the default. Under the default, any client with a private address, whether it connects directly or through the proxy, can choose its own rate-limit key by sending its own `X-Forwarded-For`; if any clients have private addresses, set it to the proxy's address alone. See [Trusted proxies](#trusted-proxies) | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` (RFC 1918) | +| `TRUSTED_PROXIES` | CIDRs whose forwarded headers are trusted. A set value replaces the default. Under the default, any client with a private address, whether it connects directly or through a trusted proxy, can choose its own rate-limit key by sending its own `X-Forwarded-For`; if any clients have private addresses, set it to the proxy's address alone. See [Trusted proxies](#trusted-proxies) | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` (RFC 1918) | | `ALLOWED_EGRESS_CIDRS` | CIDRs that delivery targets may reach despite the SSRF blocklist. Read [Allowing egress to your own network](#allowing-egress-to-your-own-network) before setting it | `""` (none) | #### Allowing egress to your own network @@ -442,8 +442,8 @@ Two operator requirements follow: it can name a different address on every request to get a fresh bucket each time, or name another client's address to drain that client's bucket. A block that also covers clients — the default, on - a network where clients have private addresses — makes all three - limits, including the unauthenticated webhook receiver, silently + a network where clients have private addresses — makes every rate + limit, including the unauthenticated webhook receiver's, silently bypassable by every client in the block. #### Sessions @@ -2549,12 +2549,12 @@ the tree is checked out: four checkouts have reported 3,959, 3,961, client-supplied field was cut, and that the shipped chain's stack arrived uncut — never the numbers. -Every limiter here — receiver, login, and password change — identifies -the client the same way, through one shared key function: the -connection's own address, unless the peer is inside -`TRUSTED_PROXIES`, in which case the forwarded client address is used -instead. That address becomes a bucket by family: IPv4 keys on the full -address, IPv6 on its `/64` prefix. A routed `/64` is the normal +Every limiter here — receiver, login, password change, delivery replay +and event resubmit — identifies the client the same way, through one +shared key function: the connection's own address, unless the peer is +inside `TRUSTED_PROXIES`, in which case the forwarded client address is +used instead. That address becomes a bucket by family: IPv4 keys on +the full address, IPv6 on its `/64` prefix. A routed `/64` is the normal residential and mobile IPv6 allocation, so keying IPv6 per address would let one subscriber rotate source addresses and mint a fresh bucket per request, evading these limits at the network layer without spoofing diff --git a/internal/config/config.go b/internal/config/config.go index 00bf0a0..7b4b6c9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -182,9 +182,9 @@ type Config struct { // Other peers' forwarded headers are ignored and they are // identified by the connection's own address. Under the // default any client with a private address, directly or - // through a proxy, can choose its own rate-limit key, so - // where any clients have private addresses this must be set - // to the proxy hosts alone. + // through a trusted proxy, can choose its own rate-limit + // key, so where any clients have private addresses this must + // be set to the proxy hosts alone. TrustedProxies []netip.Prefix // AllowedEgressCIDRs is the set of networks a delivery target