Name every rate limit that shares the client key

"Trusted proxies" now says a block covering clients makes every rate
limit bypassable, not "all three"; Rate Limiting lists delivery replay
and event resubmit among the limiters sharing the key. The
Configuration table and the TrustedProxies comment say a private
client behind a trusted proxy chooses its key, not behind any proxy.

Model: opus-5-5
This commit is contained in:
2026-10-01 21:50:35 +00:00
parent 1c2b09f283
commit 364ce11500
2 changed files with 12 additions and 12 deletions
+9 -9
View File
@@ -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
@@ -2550,12 +2550,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
+3 -3
View File
@@ -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