示例#1
0
 def __init__(self):
     self.flows = []
     self.layers = [
         lambda ctx: layers.modes.HttpProxy(ctx),
         lambda ctx: layers.HttpLayer(ctx, HTTPMode.regular),
         lambda ctx: layers.TCPLayer(ctx),
     ]
示例#2
0
    async def handle(reader, writer):
        layer_stack = [
            # lambda ctx: layers.ServerTLSLayer(ctx),
            # lambda ctx: layers.HttpLayer(ctx, HTTPMode.regular),
            # lambda ctx: setattr(ctx.server, "tls", True) or layers.ServerTLSLayer(ctx),
            # lambda ctx: layers.ClientTLSLayer(ctx),
            lambda ctx: layers.modes.ReverseProxy(ctx),
            lambda ctx: layers.HttpLayer(ctx, HTTPMode.transparent)
        ]

        def next_layer(nl: layer.NextLayer):
            l = layer_stack.pop(0)(nl.context)
            l.debug = "  " * len(nl.context.layers)
            nl.layer = l

        def request(flow: http.HTTPFlow):
            if "cached" in flow.request.path:
                flow.response = http.Response.make(
                    418, f"(cached) {flow.request.text}")
            if "toggle-tls" in flow.request.path:
                if flow.request.url.startswith("https://"):
                    flow.request.url = flow.request.url.replace(
                        "https://", "http://")
                else:
                    flow.request.url = flow.request.url.replace(
                        "http://", "https://")
            if "redirect" in flow.request.path:
                flow.request.host = "httpbin.org"

        def tls_start_client(tls_start: tls.TlsData):
            # INSECURE
            ssl_context = SSL.Context(SSL.SSLv23_METHOD)
            ssl_context.use_privatekey_file(
                pkg_data.path(
                    "../test/mitmproxy/data/verificationcerts/trusted-leaf.key"
                ))
            ssl_context.use_certificate_chain_file(
                pkg_data.path(
                    "../test/mitmproxy/data/verificationcerts/trusted-leaf.crt"
                ))
            tls_start.ssl_conn = SSL.Connection(ssl_context)
            tls_start.ssl_conn.set_accept_state()

        def tls_start_server(tls_start: tls.TlsData):
            # INSECURE
            ssl_context = SSL.Context(SSL.SSLv23_METHOD)
            tls_start.ssl_conn = SSL.Connection(ssl_context)
            tls_start.ssl_conn.set_connect_state()
            if tls_start.context.client.sni is not None:
                tls_start.ssl_conn.set_tlsext_host_name(
                    tls_start.context.client.sni.encode())

        await SimpleConnectionHandler(
            reader, writer, opts, {
                "next_layer": next_layer,
                "request": request,
                "tls_start_client": tls_start_client,
                "tls_start_server": tls_start_server,
            }).handle_client()
示例#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 = flow.server_conn.via = server_spec.parse_with_mode(
                options.mode)[1]

        super().__init__(context)

        if options.mode.startswith("upstream:"):
            self.layer = layers.HttpLayer(context, HTTPMode.upstream)
        else:
            self.layer = layers.HttpLayer(context, HTTPMode.transparent)
        self.layer.connections[client] = MockServer(flow, context.fork())
        self.flow = flow
        self.done = asyncio.Event()
示例#4
0
    def _next_layer(self, context: context.Context, data_client: bytes,
                    data_server: bytes) -> Optional[layer.Layer]:
        if len(context.layers) == 0:
            return self.make_top_layer(context)

        if len(data_client) < 3 and not data_server:
            return None  # not enough data yet to make a decision

        # helper function to quickly check if the existing layer stack matches a particular configuration.
        def s(*layers):
            return stack_match(context, layers)

        # 1. check for --ignore/--allow
        ignore = self.ignore_connection(context.server.address, data_client)
        if ignore is True:
            return layers.TCPLayer(context, ignore=True)
        if ignore is None:
            return None

        # 2. Check for TLS
        client_tls = is_tls_record_magic(data_client)
        if client_tls:
            # client tls usually requires a server tls layer as parent layer, except:
            #  - a secure web proxy doesn't have a server part.
            #  - reverse proxy mode manages this itself.
            if (s(modes.HttpProxy) or s(modes.ReverseProxy)
                    or s(modes.ReverseProxy, layers.ServerTLSLayer)):
                return layers.ClientTLSLayer(context)
            else:
                # We already assign the next layer here os that ServerTLSLayer
                # knows that it can safely wait for a ClientHello.
                ret = layers.ServerTLSLayer(context)
                ret.child_layer = layers.ClientTLSLayer(context)
                return ret

        # 3. Setup the HTTP layer for a regular HTTP proxy or an upstream proxy.
        if (s(modes.HttpProxy) or
                # or a "Secure Web Proxy", see https://www.chromium.org/developers/design-documents/secure-web-proxy
                s(modes.HttpProxy, layers.ClientTLSLayer)):
            if ctx.options.mode == "regular":
                return layers.HttpLayer(context, HTTPMode.regular)
            else:
                return layers.HttpLayer(context, HTTPMode.upstream)

        # 4. Check for --tcp
        if any(
            (context.server.address and rex.search(context.server.address[0]))
                or (context.client.sni and rex.search(context.client.sni))
                for rex in self.tcp_hosts):
            return layers.TCPLayer(context)

        # 5. Check for raw tcp mode.
        very_likely_http = (context.client.alpn
                            and context.client.alpn in HTTP_ALPNS)
        probably_no_http = not very_likely_http and (
            not data_client[:3].isalpha(
            )  # the first three bytes should be the HTTP verb, so A-Za-z is expected.
            or data_server  # a server greeting would be uncharacteristic.
        )
        if ctx.options.rawtcp and probably_no_http:
            return layers.TCPLayer(context)

        # 6. Assume HTTP by default.
        return layers.HttpLayer(context, HTTPMode.transparent)
示例#5
0
    def _next_layer(self, context: context.Context, data_client: bytes,
                    data_server: bytes) -> Optional[layer.Layer]:
        if len(context.layers) == 0:
            return self.make_top_layer(context)

        if len(data_client) < 3 and not data_server:
            return None

        client_tls = is_tls_record_magic(data_client)

        def s(*layers):
            return stack_match(context, layers)

        top_layer = context.layers[-1]

        # 1. check for --ignore/--allow
        ignore = self.ignore_connection(context.server.address, data_client)
        if ignore is True:
            return layers.TCPLayer(context, ignore=True)
        if ignore is None:
            return None

        # 2. Check for TLS
        if client_tls:
            # client tls requires a server tls layer as parent layer
            # reverse proxy mode manages this itself.
            # a secure web proxy doesn't have a server part.
            if isinstance(top_layer, layers.ServerTLSLayer) or s(
                    modes.ReverseProxy) or s(modes.HttpProxy):
                return layers.ClientTLSLayer(context)
            else:
                return layers.ServerTLSLayer(context)

        # 3. Setup the HTTP layer for a regular HTTP proxy or an upstream proxy.
        if any([
                s(modes.HttpProxy),
                # or a "Secure Web Proxy", see https://www.chromium.org/developers/design-documents/secure-web-proxy
                s(modes.HttpProxy, layers.ClientTLSLayer),
        ]):
            if ctx.options.mode == "regular":
                return layers.HttpLayer(context, HTTPMode.regular)
            else:
                return layers.HttpLayer(context, HTTPMode.upstream)

        # 4. Check for --tcp
        if any(
            (context.server.address and rex.search(context.server.address[0]))
                or (context.client.sni and rex.search(context.client.sni))
                for rex in self.tcp_hosts):
            return layers.TCPLayer(context)

        # 5. Check for raw tcp mode.
        very_likely_http = (context.client.alpn
                            and context.client.alpn in HTTP_ALPNS)
        probably_no_http = not very_likely_http and (
            not data_client[:3].isalpha(
            )  # the first three bytes should be the HTTP verb, so A-Za-z is expected.
            or data_server  # a server greeting would be uncharacteristic.
        )
        if ctx.options.rawtcp and probably_no_http:
            return layers.TCPLayer(context)

        # 6. Assume HTTP by default.
        return layers.HttpLayer(context, HTTPMode.transparent)