diff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py index 1987c8dc5..3d21b13c3 100644 --- a/mitmproxy/proxy/root_context.py +++ b/mitmproxy/proxy/root_context.py @@ -70,8 +70,16 @@ class RootContext: top_layer.server_tls, top_layer.server_conn.address[0] ) - if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer): + if isinstance(top_layer, protocol.ServerConnectionMixin): return protocol.TlsLayer(top_layer, client_tls, client_tls) + if isinstance(top_layer, protocol.UpstreamConnectLayer): + # if the user manually sets a scheme for connect requests, we use this to decide if we + # want TLS or not. + if top_layer.connect_request.scheme: + tls = top_layer.connect_request.scheme == "https" + else: + tls = client_tls + return protocol.TlsLayer(top_layer, client_tls, tls) # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. if isinstance(top_layer, protocol.TlsLayer): diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py index b4bb46bb3..8381e511f 100644 --- a/test/mitmproxy/proxy/test_server.py +++ b/test/mitmproxy/proxy/test_server.py @@ -1009,6 +1009,40 @@ class TestUpstreamProxySSL( assert len(self.chain[0].tmaster.state.flows) == 0 assert len(self.chain[1].tmaster.state.flows) == 1 + def test_connect_https_to_http(self): + """ + https://github.com/mitmproxy/mitmproxy/issues/2329 + + Client <- HTTPS -> Proxy <- HTTP -> Proxy <- HTTPS -> Server + """ + self.proxy.tmaster.addons.add(RewriteToHttp()) + self.chain[1].tmaster.addons.add(RewriteToHttps()) + p = self.pathoc() + with p.connect(): + resp = p.request("get:'/p/418'") + + assert self.proxy.tmaster.state.flows[0].client_conn.tls_established + assert not self.proxy.tmaster.state.flows[0].server_conn.tls_established + assert not self.chain[1].tmaster.state.flows[0].client_conn.tls_established + assert self.chain[1].tmaster.state.flows[0].server_conn.tls_established + assert resp.status_code == 418 + + +class RewriteToHttp: + def http_connect(self, f): + f.request.scheme = "http" + + def request(self, f): + f.request.scheme = "http" + + +class RewriteToHttps: + def http_connect(self, f): + f.request.scheme = "https" + + def request(self, f): + f.request.scheme = "https" + class UpstreamProxyChanger: def __init__(self, addr):