MITM: serve the intercepted session with net/http #43

Merged
mikluko merged 1 commit from refactor/mitm-net-http into main 2026-10-26 22:00:38 +00:00
Owner

Candidate 1 of the architecture review.

The MITM handler served HTTP/1.1 by hand, and got it wrong in three ways. Each now has a test that fails against the old code:

  • its response writer buffered every body until the handler returned, so intercepted responses never streamed (TestMITMHandler_streams)
  • each request got a fresh bufio.Reader, dropping read-ahead, so pipelined requests after the first were lost (TestMITMHandler_pipelining)
  • bytes buffered by the hijack never reached the TLS handshake, so a client that handshakes before reading the CONNECT response stalled (TestMITMHandler_handshakeBeforeConnectResponse)

After the handshake, an http.Server serves the connection through a one-connection listener. The session ends when the connection closes, whether the server or a hijacking inner handler closes it. Inner requests keep the CONNECT request's context, so logging and tracing are unchanged. The response writer, the no-op-close conn and the request loop are deleted.

One trap, noted in a symbol doc: reads after the hijack-time buffer must go to the raw conn. Read through the outer server's reader, the inner server's deadline aborts cancel the CONNECT request's context.

The suite passes three times in a row under -race.

Candidate 1 of the architecture review. The MITM handler served HTTP/1.1 by hand, and got it wrong in three ways. Each now has a test that fails against the old code: - its response writer buffered every body until the handler returned, so intercepted responses never streamed (`TestMITMHandler_streams`) - each request got a fresh `bufio.Reader`, dropping read-ahead, so pipelined requests after the first were lost (`TestMITMHandler_pipelining`) - bytes buffered by the hijack never reached the TLS handshake, so a client that handshakes before reading the `CONNECT` response stalled (`TestMITMHandler_handshakeBeforeConnectResponse`) After the handshake, an `http.Server` serves the connection through a one-connection listener. The session ends when the connection closes, whether the server or a hijacking inner handler closes it. Inner requests keep the `CONNECT` request's context, so logging and tracing are unchanged. The response writer, the no-op-close conn and the request loop are deleted. One trap, noted in a symbol doc: reads after the hijack-time buffer must go to the raw conn. Read through the outer server's reader, the inner server's deadline aborts cancel the `CONNECT` request's context. The suite passes three times in a row under `-race`.
MITM: serve the intercepted session with net/http
All checks were successful
CI / changelog (pull_request) Successful in 6s
CI / test (pull_request) Successful in 52s
6091837493
The MITM handler parsed requests and serialised responses itself. Its
response writer buffered every body until the handler returned, each request
got a fresh bufio.Reader so pipelined bytes were dropped, and bytes buffered
at hijack never reached the TLS handshake. An http.Server over a
one-connection listener replaces the loop, the response writer and the
no-op-close conn.

Reads go to the raw conn after the hijack-time buffer: reading on through
the hijacking server's reader lets the inner server's deadline aborts cancel
the CONNECT request context.
mikluko deleted branch refactor/mitm-net-http 2026-10-26 22:00:38 +00:00
Sign in to join this conversation.
No description provided.