Problem
Tunnel::new(proxy_uri, connector) at src/client/hyper.rs:741 layers TLS inside the CONNECT tunnel instead of outside it. hyper-util's Tunnel calls the inner connector with the proxy URI (tunnel.rs:135, type Response = C::Response), so OpenSslConnector::call sees scheme http, takes the non-TLS branch at src/client/hyper.rs:525, and hands the pooled Client a raw TCP stream for the target. SocksV5::new at :750 has the same shape.
The result is that an https:// request through a proxy speaks plaintext HTTP to the target inside the tunnel. Against a CONNECT proxy, https://secret-target.example/admin?token=hunter2 goes out as:
CONNECT secret-target.example:443 HTTP/1.1
--- inside the tunnel ---
GET /admin?token=hunter2 HTTP/1.1
host: secret-target.example
is TLS ClientHello = false
Knock-on effects:
alpn_protocols, verify_certs, cipher_string, min_tls_version and max_tls_version are all no-ops on proxied HTTPS. That also makes the TlsKey inside ConnMode::Tunnel and ConnMode::Socks5 a cache key over settings that have no effect.
- Cookies marked
Secure go out in the clear on proxied redirect chains, since header_for decides Secure from uri.scheme_str() == "https" and the scheme still reads as https at that layer.
This predates 0.10.0. The same probe run against stable produces the same bytes.
Proposed Solution
Invert the layering so TLS wraps the tunnel rather than sitting inside it: establish the CONNECT (or SOCKS5) connection first, then run the TLS handshake for the target host over that stream.
There is currently no end-to-end proxy test in the repo, so the fix should come with one that asserts a TLS ClientHello appears inside the tunnel and that certificate verification really applies to the target.
Found by @en0f while reviewing #86.
Problem
Tunnel::new(proxy_uri, connector)atsrc/client/hyper.rs:741layers TLS inside the CONNECT tunnel instead of outside it. hyper-util'sTunnelcalls the inner connector with the proxy URI (tunnel.rs:135,type Response = C::Response), soOpenSslConnector::callsees schemehttp, takes the non-TLS branch atsrc/client/hyper.rs:525, and hands the pooledClienta raw TCP stream for the target.SocksV5::newat:750has the same shape.The result is that an
https://request through a proxy speaks plaintext HTTP to the target inside the tunnel. Against a CONNECT proxy,https://secret-target.example/admin?token=hunter2goes out as:Knock-on effects:
alpn_protocols,verify_certs,cipher_string,min_tls_versionandmax_tls_versionare all no-ops on proxied HTTPS. That also makes theTlsKeyinsideConnMode::TunnelandConnMode::Socks5a cache key over settings that have no effect.Securego out in the clear on proxied redirect chains, sinceheader_fordecidesSecurefromuri.scheme_str() == "https"and the scheme still reads as https at that layer.This predates 0.10.0. The same probe run against
stableproduces the same bytes.Proposed Solution
Invert the layering so TLS wraps the tunnel rather than sitting inside it: establish the CONNECT (or SOCKS5) connection first, then run the TLS handshake for the target host over that stream.
There is currently no end-to-end proxy test in the repo, so the fix should come with one that asserts a TLS ClientHello appears inside the tunnel and that certificate verification really applies to the target.
Found by @en0f while reviewing #86.