def test_upstream_https(tctx): """ Test mitmproxy in HTTPS upstream mode with another mitmproxy instance upstream. In other words: mitmdump --mode upstream:https://localhost:8081 --ssl-insecure mitmdump -p 8081 curl -x localhost:8080 -k http://example.com """ tctx1 = Context(Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), copy.deepcopy(tctx.options)) tctx1.options.mode = "upstream:https://example.mitmproxy.org:8081" tctx2 = Context(Client(("client", 4321), ("127.0.0.1", 8080), 1605699329), copy.deepcopy(tctx.options)) assert tctx2.options.mode == "regular" del tctx proxy1 = Playbook(modes.HttpProxy(tctx1), hooks=False) proxy2 = Playbook(modes.HttpProxy(tctx2), hooks=False) upstream = Placeholder(Server) server = Placeholder(Server) clienthello = Placeholder(bytes) serverhello = Placeholder(bytes) request = Placeholder(bytes) tls_finished = Placeholder(bytes) response = Placeholder(bytes) assert ( proxy1 >> DataReceived( tctx1.client, b"GET http://example.com/ HTTP/1.1\r\nHost: example.com\r\n\r\n") << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer(lambda ctx: http.HttpLayer(ctx, HTTPMode.upstream)) << OpenConnection(upstream) >> reply(None) << TlsStartServerHook( Placeholder()) >> reply_tls_start_server(alpn=b"http/1.1") << SendData(upstream, clienthello)) assert upstream().address == ("example.mitmproxy.org", 8081) assert upstream().sni == "example.mitmproxy.org" assert (proxy2 >> DataReceived( tctx2.client, clienthello()) << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer(ClientTLSLayer) << TlsStartClientHook( Placeholder()) >> reply_tls_start_client(alpn=b"http/1.1") << SendData(tctx2.client, serverhello)) assert (proxy1 >> DataReceived(upstream, serverhello()) << SendData( upstream, request)) assert (proxy2 >> DataReceived(tctx2.client, request()) << SendData( tctx2.client, tls_finished) << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer(lambda ctx: http.HttpLayer(ctx, HTTPMode.regular)) << OpenConnection(server) >> reply(None) << SendData( server, b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n') >> DataReceived(server, b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << SendData(tctx2.client, response)) assert server().address == ("example.com", 80) assert (proxy1 >> DataReceived( upstream, tls_finished() + response()) << SendData( tctx1.client, b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"))
def __init__(self, context: Context, mode: HTTPMode): super().__init__(context) self.mode = mode self.waiting_for_establishment = collections.defaultdict(list) self.streams = {} self.command_sources = {} http_conn: HttpConnection if self.context.client.alpn == b"h2": http_conn = Http2Server(context.fork()) else: http_conn = Http1Server(context.fork()) self.connections = {context.client: http_conn}
def __init__(self, flow: http.HTTPFlow, options: Options) -> None: client = flow.client_conn.copy() client.state = ConnectionState.OPEN context = Context(client, options) context.server = Server((flow.request.host, flow.request.port)) context.server.tls = flow.request.scheme == "https" if options.mode.startswith("upstream:"): context.server.via = server_spec.parse_with_mode(options.mode)[1] super().__init__(context) self.layer = layers.HttpLayer(context, HTTPMode.transparent) self.layer.connections[client] = MockServer(flow, context.fork()) self.flow = flow self.done = asyncio.Event()
def test_request_trailers(tctx: Context, open_h2_server_conn: Server, stream): playbook, cff = start_h2_client(tctx) tctx.server = open_h2_server_conn def enable_streaming(flow: HTTPFlow): flow.request.stream = bool(stream) flow = Placeholder(HTTPFlow) server_data1 = Placeholder(bytes) server_data2 = Placeholder(bytes) (playbook >> DataReceived( tctx.client, cff.build_headers_frame(example_request_headers).serialize() + cff.build_data_frame(b"Hello, World!").serialize()) << http.HttpRequestHeadersHook(flow) >> reply(side_effect=enable_streaming)) if stream: playbook << SendData(tctx.server, server_data1) assert (playbook >> DataReceived( tctx.client, cff.build_headers_frame(example_request_trailers, flags=[ "END_STREAM" ]).serialize()) << http.HttpRequestHook(flow) >> reply() << SendData( tctx.server, server_data2)) frames = decode_frames(server_data1.setdefault(b"") + server_data2()) assert [type(x) for x in frames] == [ hyperframe.frame.SettingsFrame, hyperframe.frame.HeadersFrame, hyperframe.frame.DataFrame, hyperframe.frame.HeadersFrame, ]
def __init__(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter, options: moptions.Options) -> None: client = Client( writer.get_extra_info('peername'), writer.get_extra_info('sockname'), time.time(), ) context = Context(client, options) super().__init__(context) self.transports[client] = ConnectionIO(handler=None, reader=reader, writer=writer)
def test_response_trailers(tctx: Context, open_h2_server_conn: Server, stream): playbook, cff = start_h2_client(tctx) tctx.server = open_h2_server_conn sff = FrameFactory() def enable_streaming(flow: HTTPFlow): flow.response.stream = bool(stream) flow = Placeholder(HTTPFlow) ( playbook >> DataReceived(tctx.client, cff.build_headers_frame(example_request_headers, flags=["END_STREAM"]).serialize()) << http.HttpRequestHeadersHook(flow) >> reply() << http.HttpRequestHook(flow) >> reply() << SendData(tctx.server, Placeholder(bytes)) # a conforming h2 server would send settings first, we disregard this for now. >> DataReceived(tctx.server, sff.build_headers_frame(example_response_headers).serialize() + sff.build_data_frame(b"Hello, World!").serialize()) << http.HttpResponseHeadersHook(flow) >> reply(side_effect=enable_streaming) ) if stream: playbook << SendData( tctx.client, cff.build_headers_frame(example_response_headers).serialize() + cff.build_data_frame(b"Hello, World!").serialize() ) assert ( playbook >> DataReceived(tctx.server, sff.build_headers_frame(example_response_trailers, flags=["END_STREAM"]).serialize()) << http.HttpResponseHook(flow) ) assert flow().response.trailers del flow().response.trailers["resp-trailer-a"] if stream: assert ( playbook >> reply() << SendData(tctx.client, cff.build_headers_frame(example_response_trailers[1:], flags=["END_STREAM"]).serialize()) ) else: assert ( playbook >> reply() << SendData(tctx.client, cff.build_headers_frame(example_response_headers).serialize() + cff.build_data_frame(b"Hello, World!").serialize() + cff.build_headers_frame(example_response_trailers[1:], flags=["END_STREAM"]).serialize()))
from hypothesis import given from hypothesis.strategies import binary from mitmproxy import options from mitmproxy.connection import Client from mitmproxy.proxy.context import Context from mitmproxy.proxy.events import DataReceived from mitmproxy.proxy.layers.modes import Socks5Proxy opts = options.Options() tctx = Context(Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), opts) @given(binary()) def test_socks5_fuzz(data): layer = Socks5Proxy(tctx) list(layer.handle_event(DataReceived(tctx.client, data)))