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), ]
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()
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()
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)
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)