def test_transparent_tcp(tctx: Context, monkeypatch, connection_strategy): monkeypatch.setattr(platform, "original_addr", lambda sock: ("address", 22)) flow = Placeholder(TCPFlow) tctx.options.connection_strategy = connection_strategy sock = object() playbook = Playbook(modes.TransparentProxy(tctx)) ( playbook << GetSocket(tctx.client) >> reply(sock) ) if connection_strategy == "lazy": assert playbook else: assert ( playbook << OpenConnection(tctx.server) >> reply(None) >> DataReceived(tctx.server, b"hello") << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer(tcp.TCPLayer) << TcpStartHook(flow) >> reply() << TcpMessageHook(flow) >> reply() << SendData(tctx.client, b"hello") ) assert flow().messages[0].content == b"hello" assert not flow().messages[0].from_client assert tctx.server.address == ("address", 22)
def test_upgrade(tctx, proto): """Test a HTTP -> WebSocket upgrade with different protocols enabled""" if proto != "websocket": tctx.options.websocket = False if proto != "tcp": tctx.options.rawtcp = False tctx.server.address = ("example.com", 80) tctx.server.state = ConnectionState.OPEN http_flow = Placeholder(HTTPFlow) playbook = Playbook(http.HttpLayer(tctx, HTTPMode.transparent)) ( playbook >> DataReceived(tctx.client, b"GET / HTTP/1.1\r\n" b"Connection: upgrade\r\n" b"Upgrade: websocket\r\n" b"Sec-WebSocket-Version: 13\r\n" b"\r\n") << http.HttpRequestHeadersHook(http_flow) >> reply() << http.HttpRequestHook(http_flow) >> reply() << SendData(tctx.server, b"GET / HTTP/1.1\r\n" b"Connection: upgrade\r\n" b"Upgrade: websocket\r\n" b"Sec-WebSocket-Version: 13\r\n" b"\r\n") >> DataReceived(tctx.server, b"HTTP/1.1 101 Switching Protocols\r\n" b"Upgrade: websocket\r\n" b"Connection: Upgrade\r\n" b"\r\n") << http.HttpResponseHeadersHook(http_flow) >> reply() << http.HttpResponseHook(http_flow) >> reply() << SendData(tctx.client, b"HTTP/1.1 101 Switching Protocols\r\n" b"Upgrade: websocket\r\n" b"Connection: Upgrade\r\n" b"\r\n") ) if proto == "websocket": assert playbook << WebsocketStartHook(Placeholder(WebSocketFlow)) elif proto == "tcp": assert playbook << TcpStartHook(Placeholder(TCPFlow)) else: assert ( playbook << Log("Sent HTTP 101 response, but no protocol is enabled to upgrade to.", "warn") << CloseConnection(tctx.client) )
def test_reverse_proxy_tcp_over_tls(tctx: Context, monkeypatch, patch, connection_strategy): """ Test client --TCP-- mitmproxy --TCP over TLS-- server reverse proxying. """ if patch: monkeypatch.setattr(tls, "ServerTLSLayer", tls.MockTLSLayer) flow = Placeholder(TCPFlow) data = Placeholder(bytes) tctx.options.mode = "reverse:https://localhost:8000" tctx.options.connection_strategy = connection_strategy playbook = Playbook(modes.ReverseProxy(tctx)) if connection_strategy == "eager": (playbook << OpenConnection(tctx.server) >> DataReceived( tctx.client, b"\x01\x02\x03") >> reply( None, to=OpenConnection(tctx.server))) else: (playbook >> DataReceived(tctx.client, b"\x01\x02\x03")) if patch: (playbook << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer( tcp.TCPLayer) << TcpStartHook(flow) >> reply()) if connection_strategy == "lazy": (playbook << OpenConnection(tctx.server) >> reply(None)) assert (playbook << TcpMessageHook(flow) >> reply() << SendData( tctx.server, data)) assert data() == b"\x01\x02\x03" else: if connection_strategy == "lazy": (playbook << NextLayerHook(Placeholder(NextLayer)) >> reply_next_layer(tcp.TCPLayer) << TcpStartHook(flow) >> reply() << OpenConnection(tctx.server) >> reply(None)) assert (playbook << TlsStartHook(Placeholder()) >> reply_tls_start() << SendData(tctx.server, data)) assert tls.parse_client_hello(data()).sni == "localhost"
def test_http_proxy_tcp(tctx, mode, close_first): """Test TCP over HTTP CONNECT.""" server = Placeholder(Server) f = Placeholder(TCPFlow) tctx.options.connection_strategy = "lazy" if mode == "upstream": tctx.options.mode = "upstream:http://proxy:8080" toplayer = http.HttpLayer(tctx, HTTPMode.upstream) else: tctx.options.mode = "regular" toplayer = http.HttpLayer(tctx, HTTPMode.regular) playbook = Playbook(toplayer, hooks=False) assert (playbook >> DataReceived( tctx.client, b"CONNECT example:443 HTTP/1.1\r\n\r\n") << SendData( tctx.client, b"HTTP/1.1 200 Connection established\r\n\r\n") >> DataReceived(tctx.client, b"this is not http") << layer.NextLayerHook(Placeholder()) >> reply_next_layer(lambda ctx: TCPLayer(ctx, ignore=False)) << TcpStartHook(f) >> reply() << OpenConnection(server)) playbook >> reply(None) if mode == "upstream": playbook << SendData(server, b"CONNECT example:443 HTTP/1.1\r\n\r\n") playbook >> DataReceived( server, b"HTTP/1.1 200 Connection established\r\n\r\n") assert (playbook << SendData(server, b"this is not http") >> DataReceived( server, b"true that") << SendData(tctx.client, b"true that")) if mode == "regular": assert server().address == ("example", 443) else: assert server().address == ("proxy", 8080) assert (playbook >> TcpMessageInjected( f, TCPMessage(False, b"fake news from your friendly man-in-the-middle")) << SendData(tctx.client, b"fake news from your friendly man-in-the-middle")) if close_first == "client": a, b = tctx.client, server else: a, b = server, tctx.client assert (playbook >> ConnectionClosed(a) << CloseConnection(b) >> ConnectionClosed(b) << CloseConnection(a))