fix(proxy): handle bare IPs in isTrustedSource RemoteAddr
When r.RemoteAddr lacks a port (bare IP from Unix sockets or certain proxy setups), net.SplitHostPort fails. Previously this returned false, silently treating trusted proxies as untrusted. Now falls back to using RemoteAddr directly, stripping IPv6 brackets if present.
- commit
- 01d3159d6bbd55c8d486abad50c4ec1ace6f9c80
- author
- brice · · 2026-04-03 18:17 UTC
- parent
- f9f7402
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +24 -1
M internal/adapters/in/http/proxy/forwarder.go +3 -1
| @@ -219,7 +219,9 @@ func isTrustedSource(r *http.Request, trustedNets []*net.IPNet) bool { | |||
| 219 | 219 | } | |
| 220 | 220 | host, _, err := net.SplitHostPort(r.RemoteAddr) | |
| 221 | 221 | if err != nil { | |
| 222 | - | return false | |
| 222 | + | // RemoteAddr may be a bare IP without a port (e.g. from Unix sockets | |
| 223 | + | // or certain proxy setups). Fall back to using it directly. | |
| 224 | + | host = strings.TrimSuffix(strings.TrimPrefix(r.RemoteAddr, "["), "]") | |
| 223 | 225 | } | |
| 224 | 226 | return middleware.IsTrustedProxy(host, trustedNets) | |
| 225 | 227 | } | |
| @@ -219,7 +219,9 @@ func isTrustedSource(r *http.Request, trustedNets []*net.IPNet) bool { | |||||
| 219 | } | 219 | } | ||
| 220 | host, _, err := net.SplitHostPort(r.RemoteAddr) | 220 | host, _, err := net.SplitHostPort(r.RemoteAddr) | ||
| 221 | if err != nil { | 221 | if err != nil { | ||
| 222 | - | return false | 222 | + | // RemoteAddr may be a bare IP without a port (e.g. from Unix sockets |
| 223 | + | // or certain proxy setups). Fall back to using it directly. | |||
| 224 | + | host = strings.TrimSuffix(strings.TrimPrefix(r.RemoteAddr, "["), "]") | |||
| 223 | } | 225 | } | ||
| 224 | return middleware.IsTrustedProxy(host, trustedNets) | 226 | return middleware.IsTrustedProxy(host, trustedNets) | ||
| 225 | } | 227 | } | ||
M internal/adapters/in/http/proxy/forwarder_test.go +21 -0
| @@ -238,6 +238,27 @@ func TestNewReverseProxy_XForwardedProto(t *testing.T) { | |||
| 238 | 238 | wantProto: "http", | |
| 239 | 239 | nets: nil, | |
| 240 | 240 | }, | |
| 241 | + | { | |
| 242 | + | name: "bare IPv4 no port trusted source preserves proto", | |
| 243 | + | remoteAddr: "10.0.0.1", | |
| 244 | + | incomingProto: "https", | |
| 245 | + | wantProto: "https", | |
| 246 | + | nets: trustedNets, | |
| 247 | + | }, | |
| 248 | + | { | |
| 249 | + | name: "bare IPv6 with brackets trusted source preserves proto", | |
| 250 | + | remoteAddr: "[::1]", | |
| 251 | + | incomingProto: "https", | |
| 252 | + | wantProto: "https", | |
| 253 | + | nets: middleware.ParseTrustedProxies([]string{"::1/128"}), | |
| 254 | + | }, | |
| 255 | + | { | |
| 256 | + | name: "bare IPv4 no port untrusted source strips proto", | |
| 257 | + | remoteAddr: "1.2.3.4", | |
| 258 | + | incomingProto: "https", | |
| 259 | + | wantProto: "http", | |
| 260 | + | nets: trustedNets, | |
| 261 | + | }, | |
| 241 | 262 | } | |
| 242 | 263 | ||
| 243 | 264 | for _, tt := range tests { | |
| @@ -238,6 +238,27 @@ func TestNewReverseProxy_XForwardedProto(t *testing.T) { | |||||
| 238 | wantProto: "http", | 238 | wantProto: "http", | ||
| 239 | nets: nil, | 239 | nets: nil, | ||
| 240 | }, | 240 | }, | ||
| 241 | + | { | |||
| 242 | + | name: "bare IPv4 no port trusted source preserves proto", | |||
| 243 | + | remoteAddr: "10.0.0.1", | |||
| 244 | + | incomingProto: "https", | |||
| 245 | + | wantProto: "https", | |||
| 246 | + | nets: trustedNets, | |||
| 247 | + | }, | |||
| 248 | + | { | |||
| 249 | + | name: "bare IPv6 with brackets trusted source preserves proto", | |||
| 250 | + | remoteAddr: "[::1]", | |||
| 251 | + | incomingProto: "https", | |||
| 252 | + | wantProto: "https", | |||
| 253 | + | nets: middleware.ParseTrustedProxies([]string{"::1/128"}), | |||
| 254 | + | }, | |||
| 255 | + | { | |||
| 256 | + | name: "bare IPv4 no port untrusted source strips proto", | |||
| 257 | + | remoteAddr: "1.2.3.4", | |||
| 258 | + | incomingProto: "https", | |||
| 259 | + | wantProto: "http", | |||
| 260 | + | nets: trustedNets, | |||
| 261 | + | }, | |||
| 241 | } | 262 | } | ||
| 242 | 263 | ||||
| 243 | for _, tt := range tests { | 264 | for _, tt := range tests { | ||