package surf import ( "net/http" "net/http/httptest" "net/netip" "testing" ) func TestClientIPEmptyTrustedUsesRemoteAddr(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "203.0.113.9:1234" req.Header.Set("X-Forwarded-For", "198.51.100.1") got := ClientIP(req, nil) if got != "203.0.113.9" { t.Fatalf("got %q", got) } } func TestClientIPRejectsSpoofedXFF(t *testing.T) { trusted := []netip.Prefix{mustPrefix("10.0.0.0/8")} req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "203.0.113.9:1234" req.Header.Set("X-Forwarded-For", "198.51.100.1") got := ClientIP(req, trusted) if got != "203.0.113.9" { t.Fatalf("untrusted RemoteAddr must ignore X-Forwarded-For, got %q", got) } } func TestClientIPRightmostUntrustedHop(t *testing.T) { trusted := []netip.Prefix{mustPrefix("10.0.0.0/8")} req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "10.0.0.1:443" req.Header.Set("X-Forwarded-For", "198.51.100.7, 203.0.113.10, 10.0.0.2") got := ClientIP(req, trusted) if got != "203.0.113.10" { t.Fatalf("rightmost untrusted hop = %q", got) } } func TestClientIPAllHopsTrustedFallsBack(t *testing.T) { trusted := []netip.Prefix{mustPrefix("10.0.0.0/8")} req := httptest.NewRequest(http.MethodGet, "/", nil) req.RemoteAddr = "10.0.0.1:443" req.Header.Set("X-Forwarded-For", "10.0.0.8, 10.0.0.9") got := ClientIP(req, trusted) if got != "10.0.0.1" { t.Fatalf("fallback RemoteAddr = %q", got) } } func mustPrefix(s string) netip.Prefix { p, err := netip.ParsePrefix(s) if err != nil { panic(err) } return p }