Files
webhooker/internal/middleware
sneak 9826cc600f
All checks were successful
check / check (push) Successful in 2m53s
Bucket IPv6 rate-limit keys by /64 (closes #125)
Rate-limit keys were per-address, i.e. per /128 for IPv6. A routed /64
is the normal residential and mobile IPv6 allocation, so a client could
rotate source addresses inside its own prefix and mint a fresh bucket
per request, evading every limiter here at the network layer with no
spoofing and nothing to detect.

The shared key function now reduces the client address to a bucket by
family: IPv4 keys on the full address, IPv6 on its /64 prefix. All four
limiter instances (login, password change, and the receiver's
per-entrypoint and aggregate limits) go through that one function, so
all of them are covered.

Both branches of that function are covered by tests: the direct-peer
branch, and the trusted-proxy branch that takes the client address out
of X-Forwarded-For. The second is the one a production deployment
takes, since it is required to run behind a reverse proxy with
TRUSTED_PROXIES set.

IPv4-mapped addresses (::ffff:1.2.3.4) key as the IPv4 address they
carry rather than being masked, which would otherwise collapse every
IPv4 client behind a mapping proxy into the ::ffff:0:0/96 bucket. An
unparseable RemoteAddr still keys on its raw value, so those stay in
distinct buckets instead of collapsing together.

No new configuration surface.
2026-08-17 21:38:21 +00:00
..