예제 #1
0
def next_layer(nextlayer: layer.NextLayer):
    ctx.log(f"{nextlayer.context=}\n"
            f"{nextlayer.data_client()[:70]=}\n"
            f"{nextlayer.data_server()[:70]=}\n")

    if nextlayer.context.server.address == ("example.com", 443):
        nextlayer.context.server.address = ("example.com", 80)

        # We are disabling ALPN negotiation as our curl client would otherwise agree on HTTP/2,
        # which our example server here does not accept for plaintext connections.
        nextlayer.context.client.alpn = b""

        # We know all layers that come next: First negotiate TLS with the client, then do simple TCP passthrough.
        # Setting only one layer here would also work, in that case next_layer would be called again after TLS establishment.
        nextlayer.layer = layers.ClientTLSLayer(nextlayer.context)
        nextlayer.layer.child_layer = layers.TCPLayer(nextlayer.context)
예제 #2
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)
예제 #3
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)