srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/PLAN.md
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-06-24 14:40:00 +0200
committersrdusr <[email protected]>2026-06-24 14:40:00 +0200
commite01afcbf0de00af52fe90959ba77288679e3303d (patch)
tree073ff1430af629e28556a6f651ee47f6989376da /PLAN.md
parent23c8ab359c2108654d57176e233d2c099b398f31 (diff)
downloadmitmux-e01afcbf0de00af52fe90959ba77288679e3303d.tar.gz
mitmux-e01afcbf0de00af52fe90959ba77288679e3303d.zip
SOCKS5 upstream proxy chaining
Extends -upstream-proxy to accept a socks5://[user:pass@]host:port prefix, using golang.org/x/net/proxy (already an indirect dependency via http2, so no new module) rather than hand-rolling the client side of RFC 1928/1929. parseSOCKS5 is the single place that decides which kind of upstream a given UpstreamProxy string names; dialViaProxy (CONNECT/TLS path) and dialUpstreamPlain (plain-HTTP path) both check it first and fall through to the existing HTTP CONNECT behavior otherwise. SOCKS5 needs no absolute-form request adjustment on the plain-HTTP path the way HTTP-proxy chaining does, since it tunnels straight to the target rather than expecting a proxy-aware request. Tested against a real, minimal SOCKS5 server built for the test suite (exercises dialSOCKS5's actual wire behavior, not a mock of the client library), plus live against a real standalone SOCKS5 relay process: both a plain HTTP and an HTTPS request through mitmux were confirmed, via the relay's own log, to have actually traversed it.
Diffstat (limited to 'PLAN.md')
-rw-r--r--PLAN.md18
1 files changed, 16 insertions, 2 deletions
diff --git a/PLAN.md b/PLAN.md
index 16a8599..073c52e 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -190,7 +190,17 @@ Upstream proxy chaining: `-upstream-proxy host:port` (optional
`http://` prefix, stripped) routes every outbound connection through
another HTTP CONNECT proxy instead of dialing origins directly -
chaining mitmux into Burp, a corporate proxy, or any other
-CONNECT-speaking proxy. SOCKS5 upstreams aren't implemented. For the
+CONNECT-speaking proxy. A `socks5://[user:pass@]host:port` prefix
+routes through a SOCKS5 proxy instead (Tor, `ssh -D`, any other SOCKS5
+relay), via golang.org/x/net/proxy - already an indirect dependency
+through http2, so no new module. parseSOCKS5 is the single place that
+decides which kind of upstream a given UpstreamProxy string names;
+dialViaProxy (CONNECT/TLS path) and dialUpstreamPlain (plain-HTTP
+path) both check it first and fall through to the existing HTTP-proxy
+behavior otherwise. SOCKS5 is transport-level and protocol-agnostic -
+the tunnel it hands back behaves exactly like a direct connection to
+the target, so unlike HTTP-proxy chaining it needs no absolute-form
+request adjustment on the plain-HTTP path either. For the
CONNECT/HTTPS path, chaining is transparent below the tunnel: once the
CONNECT handshake to the upstream proxy succeeds, TLS and the
request/response on top of it are identical to a direct connection, so
@@ -210,7 +220,11 @@ genuine passthrough CONNECT proxy (tunnels raw bytes, no MITM) works
correctly for both plain HTTP and HTTPS; chaining through a second
mitmuxd instance correctly fails with a clear
"certificate signed by unknown authority" error recorded in history,
-rather than hanging or crashing.
+rather than hanging or crashing. SOCKS5 chaining verified the same
+way, live, against a real standalone SOCKS5 relay process (not an
+in-test mock): both a plain HTTP request and an HTTPS request through
+mitmux were confirmed - via the relay's own log, not just mitmux's
+success response - to have actually traversed it end to end.
This closes every item from the original "worth considering" list.