[proxy] Optionally refuse private addresses on direct-upstream dials (#7913)

Direct-upstream targets are dialled on the proxy host's network stack,
outside the embedded client's LAN blocking. A proxy that serves
untrusted accounts lets them reach the host's loopback, its LAN or
cluster, and the cloud metadata service through such a target.

NB_PROXY_DIRECT_UPSTREAM_BLOCK_PRIVATE adds a dialer control that
refuses addresses that are not globally reachable. It checks each
socket's resolved address just before connect, so hostnames and DNS
rebinding are covered, and IPv4 embedded in IPv6 addresses is checked
as IPv4. Refused dials are served as a 502. The setting defaults to
off for private and self-hosted proxies; an unparsable value turns it
on.
This commit is contained in:
Brad Ison
2026-10-02 12:02:06 +02:00
committed by GitHub
parent 5ceca6e500
commit f400f4bee8
6 changed files with 329 additions and 1 deletions
+6
View File
@@ -809,6 +809,12 @@ func classifyProxyError(err error) (title, message string, code int, status web.
http.StatusBadGateway,
web.ErrorStatus{Proxy: false, Destination: false}
case errors.Is(err, roundtrip.ErrDirectUpstreamBlocked):
return "Destination Not Allowed",
"This proxy does not connect to private or internal addresses. Please contact your administrator.",
http.StatusBadGateway,
web.ErrorStatus{Proxy: false, Destination: false}
case errors.Is(err, roundtrip.ErrTooManyInflight):
return "Service Overloaded",
"The service is currently handling too many requests. Please try again shortly.",
+11
View File
@@ -1053,6 +1053,17 @@ func TestClassifyProxyError(t *testing.T) {
wantCode: http.StatusBadGateway,
wantStatus: web.ErrorStatus{Proxy: true, Destination: false},
},
{
name: "direct upstream blocked by dial guard",
err: &net.OpError{
Op: "dial",
Net: "tcp",
Err: roundtrip.ErrDirectUpstreamBlocked,
},
wantTitle: "Destination Not Allowed",
wantCode: http.StatusBadGateway,
wantStatus: web.ErrorStatus{Proxy: false, Destination: false},
},
{
name: "unknown error falls to default",
err: errors.New("something unexpected"),