Skip to content

proxy: a SOCKS CONNECT to a mitmProxy host goes through the MITM socket - #764

Merged
ig-ant merged 1 commit into
anthropics:mainfrom
felixrieseberg:socks-honours-mitm-proxy
Oct 23, 2026
Merged

ig-ant merged 1 commit into
anthropics:mainfrom
felixrieseberg:socks-honours-mitm-proxy

Conversation

@felixrieseberg

Copy link
Copy Markdown
Contributor

The proxy port speaks both HTTP and SOCKS5. With network.mitmProxy configured, an HTTP CONNECT to one of its domains is tunnelled into the MITM proxy's unix socket, but a SOCKS5 CONNECT to the same host was dialed directly (or through parentProxy), so the MITM proxy never saw that connection.

What this changes

  • createSocksProxyServer takes an optional getMitmSocketPath(host), the hook createHttpProxyServer already has, and SandboxManager passes the same function to both servers.
  • In the SOCKS connection handler, a host that hook covers is tunnelled with openConnectTunnel into the unix socket: an HTTP CONNECT carrying the canonical host and the requested port, the same call http-proxy.ts makes for a CONNECT.
  • The route order is now the same on both legs: MITM socket, then parent proxy, then direct dial. The lookup is made on the canonical host, so upper-case, trailing-dot and inet_aton spellings of a MITM host all take the MITM route.
  • If the MITM socket cannot be reached, or the proxy behind it refuses the CONNECT, the SOCKS client gets "host unreachable". No other route is tried.

What does not change: the allow and deny rules still run first (in the ruleset validator), so no host outside the allow rules becomes reachable. refuseOpaqueTunnels still refuses every SOCKS CONNECT before any of this runs. Hosts outside mitmProxy.domains take the routes they took before.

The resolved-address check is not applied on the MITM route, as on the HTTP leg. That covers its built-in set (loopback, link-local, this host's addresses, cloud metadata) as well as deniedResolvedAddresses. The README's "Resolved-address check" section already says so for mitmProxy: that hop resolves the name and owns its own address policy.

No README or schema text needed editing: neither describes mitmProxy as HTTP-only, and the schema's "Routes matching domains through an upstream proxy via Unix socket" is now true of both legs.

Behaviour change for existing users

Only configurations that set network.mitmProxy are affected. For those, a SOCKS connection to a mitmProxy.domains host now arrives at the MITM socket as CONNECT host:port:

  • A TLS client on that connection is shown the MITM proxy's certificate, so it has to trust that proxy's CA, as clients using the HTTP leg already do.
  • A non-TLS protocol to such a host (SSH over SOCKS, say) works only if the MITM proxy is willing to tunnel it. If it refuses, the client gets a SOCKS failure where it used to get a connection.
  • Before, a SOCKS CONNECT to an allowed mitmProxy name that resolved into the denied address set was refused by the library. Now that connection goes to the MITM proxy, which makes that call.

Alternative not taken

Refuse SOCKS CONNECTs to mitmProxy.domains hosts instead of routing them. That is a few lines smaller, but it breaks any client that can only speak SOCKS to those hosts, and it makes the two legs of one port behave differently. Routing mirrors the HTTP leg and keeps those clients working.

The proxy port serves HTTP and SOCKS5. With network.mitmProxy set, an HTTP
CONNECT to one of its domains is tunnelled into the MITM proxy's unix
socket, but a SOCKS CONNECT to the same host was dialed directly, or
through parentProxy, so the MITM proxy never saw it.

createSocksProxyServer now takes the same getMitmSocketPath hook as the
HTTP proxy, and the manager passes it. For a host the hook covers, the
SOCKS tunnel is opened with an HTTP CONNECT into that socket, carrying the
canonical host and the requested port. That route comes before parentProxy
and the direct dial, and nothing else is tried when it fails: the client
gets "host unreachable". The allow and deny rules and refuseOpaqueTunnels
are applied first, as before.
@ig-ant
ig-ant merged commit c66fb77 into anthropics:main Oct 23, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants