Esempio n. 1
0
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"))
Esempio n. 2
0
    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}
Esempio n. 3
0
    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()
Esempio n. 4
0
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,
    ]
Esempio n. 5
0
 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)
Esempio n. 6
0
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()))
Esempio n. 7
0
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)))