Support for upstream proxy connections in Local mode by vitaly-ps · Pull Request #7985 · mitmproxy/mitmproxy
Description
Enable handling of CONNECT requests in transparent mode for upstream proxy scenarios. Removes artificial validation blocking CONNECT and adds proper tunnel establishment.
Adds a new (optional) boolean cmdline option allow_transparent_tunnel_inspection to choose between passthrough (default) and full MitM/TLS decryption/interception modes.
Fixes: #3845
Potentially fixes: #6309
Addresses: #2813
Addresses: #6786
The new (PROXY CONNECT in transparent mode) sequence diagram
sequenceDiagram
participant Client
participant HttpStream
participant UpstreamProxy
participant ChildLayer
Note over HttpStream: handle_connect_transparent()
Client->>HttpStream: CONNECT
Note over HttpStream: HttpConnectHook (addon event)
HttpStream->>UpstreamProxy: RequestHeaders(end_stream=True)
HttpStream->>UpstreamProxy: RequestEndOfMessage
HttpStream->>ChildLayer: Create child_layer (not started)<br/>(NextLayer if inspection, TCPLayer if passthrough)
Note over HttpStream: server_state = state_wait_for_tunnel_connect_response_headers
Note over HttpStream: state_wait_for_tunnel_connect_response_headers()
UpstreamProxy->>HttpStream: ResponseHeaders
HttpStream->>Client: ResponseHeaders (forwarded)
alt end_stream=True
Note over HttpStream: → handle_tunnel_response_complete()
else end_stream=False
Note over HttpStream: → state_consume_tunnel_connect_response_body
end
Note over HttpStream: state_consume_tunnel_connect_response_body()
UpstreamProxy->>HttpStream: ResponseData
HttpStream->>Client: ResponseData (forwarded)
Note right of HttpStream: (captured in response_body_buf)
UpstreamProxy->>HttpStream: ResponseEndOfMessage
Note right of HttpStream: (captures full body to flow.response.data.content)
Note over HttpStream: → handle_tunnel_response_complete()
Note over HttpStream: handle_tunnel_response_complete()
alt SUCCESS (200-299)
Note over HttpStream: HttpConnectedHook (addon event)
Note over HttpStream: Activate passthrough mode (_handle_event = passthrough)
Note over HttpStream: client_state = state_done
Note over HttpStream: server_state = state_done
HttpStream->>ChildLayer: Start child_layer (tunnel active)<br/>(TCPLayer for passthrough OR NextLayer for TLS inspection)
HttpStream->>Client: ResponseEndOfMessage
Note over Client,ChildLayer: TUNNEL ESTABLISHED - Traffic flows through child layer
else ERROR (4xx/5xx)
Note over HttpStream: HttpConnectErrorHook (addon event)
Note over HttpStream: client_state = state_errored
Note over HttpStream: server_state = state_errored
Note over HttpStream: flow.live = False
HttpStream->>Client: ResponseEndOfMessage
Note over Client,ChildLayer: TUNNEL FAILED - child_layer created but never started
end
Checklist
-
Tested with direct connections (no proxy)
-
Tested with proxy, proxy+basic Auth, proxy+Kerberos
-
I have updated tests where applicable.
-
I have added an entry to the CHANGELOG.