diff --git a/bearer_auth.go b/bearer_auth.go index 591799c..08f7ed4 100644 --- a/bearer_auth.go +++ b/bearer_auth.go @@ -558,9 +558,10 @@ func clientIPForBearer(req *http.Request) string { } host, _, err := net.SplitHostPort(req.RemoteAddr) if err != nil { - return req.RemoteAddr + host = req.RemoteAddr } - return host + // One IPv6 /64 shares a key, so a single host cannot mint 2^64 entries. + return limiterKey(host) } // --- Bearer auth entrypoint --- diff --git a/bearer_failure_ipv6_test.go b/bearer_failure_ipv6_test.go new file mode 100644 index 0000000..131280c --- /dev/null +++ b/bearer_failure_ipv6_test.go @@ -0,0 +1,24 @@ +package traefikoidc + +import ( + "net/http/httptest" + "testing" +) + +// Addresses in one IPv6 /64 must share one failure-tracker key. +func TestClientIPForBearerCollapsesIPv6Prefix(t *testing.T) { + key := func(addr string) string { + r := httptest.NewRequest("GET", "/", nil) + r.RemoteAddr = addr + return clientIPForBearer(r) + } + if a, b := key("[2001:db8:1:2::1]:1"), key("[2001:db8:1:2:ffff::9]:2"); a != b { + t.Fatalf("same /64 got different keys: %q vs %q", a, b) + } + if a, b := key("[2001:db8:1:2::1]:1"), key("[2001:db8:1:3::1]:1"); a == b { + t.Fatalf("different /64 shared key %q", a) + } + if got := key("192.0.2.7:80"); got != "192.0.2.7" { + t.Fatalf("ipv4 key = %q", got) + } +}