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
Loading

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.