def _next_layer(self, top_layer): try: d = top_layer.client_conn.rfile.peek(3) except exceptions.TcpException as e: raise exceptions.ProtocolException(str(e)) client_tls = protocol.is_tls_record_magic(d) # 1. check for --ignore if self.config.check_ignore: ignore = self.config.check_ignore(top_layer.server_conn.address) if not ignore and client_tls: try: client_hello = protocol.TlsClientHello.from_client_conn( self.client_conn) except exceptions.TlsProtocolException as e: self.log("Cannot parse Client Hello: %s" % repr(e), "error") else: ignore = self.config.check_ignore((client_hello.sni, 443)) if ignore: return protocol.RawTCPLayer(top_layer, ignore=True) # 2. Always insert a TLS layer, even if there's neither client nor server tls. # An inline script may upgrade from http to https, # in which case we need some form of TLS layer. if isinstance(top_layer, modes.ReverseProxy): return protocol.TlsLayer(top_layer, client_tls, top_layer.server_tls, top_layer.server_conn.address.host) if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance( top_layer, protocol.UpstreamConnectLayer): return protocol.TlsLayer(top_layer, client_tls, client_tls) # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. if isinstance(top_layer, protocol.TlsLayer): if isinstance(top_layer.ctx, modes.HttpProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.regular) if isinstance(top_layer.ctx, modes.HttpUpstreamProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.upstream) # 4. Check for other TLS cases (e.g. after CONNECT). if client_tls: return protocol.TlsLayer(top_layer, True, True) # 4. Check for --tcp if self.config.check_tcp(top_layer.server_conn.address): return protocol.RawTCPLayer(top_layer) # 5. Check for TLS ALPN (HTTP1/HTTP2) if isinstance(top_layer, protocol.TlsLayer): alpn = top_layer.client_conn.get_alpn_proto_negotiated() if alpn == b'h2': return protocol.Http2Layer(top_layer, http.HTTPMode.transparent) if alpn == b'http/1.1': return protocol.Http1Layer(top_layer, http.HTTPMode.transparent) # 6. Assume HTTP1 by default return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)
def _next_layer(self, top_layer): try: d = top_layer.client_conn.rfile.peek(3) except exceptions.TcpException as e: raise exceptions.ProtocolException(str(e)) client_tls = tls.is_tls_record_magic(d) # 1. check for filter skipped_url = "" is_filtered = False if True: #self.config.check_filter: if not top_layer.server_conn.address is None: is_filtered = (self.config.check_filter( top_layer.server_conn.address) or selfc.SelfCShared.isTrusted( top_layer.server_conn.address[0])) if is_filtered: skipped_url = top_layer.server_conn.address[0] if not is_filtered and client_tls: try: client_hello = tls.ClientHello.from_file( self.client_conn.rfile) except exceptions.TlsProtocolException as e: self.log("Cannot parse Client Hello: %s" % repr(e), "error") else: sni_str = client_hello.sni and client_hello.sni.decode( "idna") if not sni_str is None: is_filtered = self.config.check_filter( (sni_str, 443)) or selfc.SelfCShared.isTrusted(sni_str) if is_filtered: skipped_url = sni_str if is_filtered: print("####### MITM Skip, Trusted: " + skipped_url) return protocol.RawTCPLayer(top_layer, ignore=True) # 2. Always insert a TLS layer, even if there's neither client nor server tls. # An inline script may upgrade from http to https, # in which case we need some form of TLS layer. if isinstance(top_layer, modes.ReverseProxy): return protocol.TlsLayer(top_layer, client_tls, top_layer.server_tls, top_layer.server_conn.address[0]) if isinstance(top_layer, protocol.ServerConnectionMixin): return protocol.TlsLayer(top_layer, client_tls, client_tls) if isinstance(top_layer, protocol.UpstreamConnectLayer): # if the user manually sets a scheme for connect requests, we use this to decide if we # want TLS or not. if top_layer.connect_request.scheme: server_tls = top_layer.connect_request.scheme == "https" else: server_tls = client_tls return protocol.TlsLayer(top_layer, client_tls, server_tls) # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. if isinstance(top_layer, protocol.TlsLayer): if isinstance(top_layer.ctx, modes.HttpProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.regular) if isinstance(top_layer.ctx, modes.HttpUpstreamProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.upstream) # 4. Check for other TLS cases (e.g. after CONNECT). if client_tls: return protocol.TlsLayer(top_layer, True, True) # 4. Check for --tcp if self.config.check_tcp(top_layer.server_conn.address): return protocol.RawTCPLayer(top_layer) # 5. Check for TLS ALPN (HTTP1/HTTP2) if isinstance(top_layer, protocol.TlsLayer): alpn = top_layer.client_conn.get_alpn_proto_negotiated() if alpn == b'h2': return protocol.Http2Layer(top_layer, http.HTTPMode.transparent) if alpn == b'http/1.1': return protocol.Http1Layer(top_layer, http.HTTPMode.transparent) # 6. Check for raw tcp mode is_ascii = ( len(d) == 3 and # expect A-Za-z all(65 <= x <= 90 or 97 <= x <= 122 for x in d)) if self.config.options.rawtcp and not is_ascii: return protocol.RawTCPLayer(top_layer) # 7. Assume HTTP1 by default return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)
def _next_layer(self, top_layer): logging.info('root_context._next_layer(%s)', top_layer) try: d = top_layer.client_conn.rfile.peek(3) except exceptions.TcpException as e: logging.info('ignoring protocol: %s', e) raise exceptions.ProtocolException(str(e)) client_tls = tls.is_tls_record_magic(d) host, port = '(unknown)', '(unknown)' # 1. check for filter if self.config.check_filter: if top_layer.server_conn.address: host, port = top_layer.server_conn.address is_filtered = self.config.check_filter( top_layer.server_conn.address) logging.info('_next_layer: %s is_filtered: %s', vars(top_layer.server_conn), is_filtered) if not is_filtered and client_tls: try: client_hello = tls.ClientHello.from_file( self.client_conn.rfile) except exceptions.TlsProtocolException as e: self.log("Cannot parse Client Hello: %s" % repr(e), "error") else: sni_str = client_hello.sni and client_hello.sni.decode( "idna") host, port = (sni_str, 443) is_filtered = self.config.check_filter((host, port)) logging.info('is_filtered: %s', is_filtered) if is_filtered: if self.config.options.block_not_ignore: self.log( '-> {}:{} {} blocked'.format(host, port, datetime.now()), 'info') raise exceptions.Kill( f'blocked https request to filtered host {host}') else: return protocol.RawTCPLayer(top_layer, ignore=True) else: self.log( '-> {}:{} {} allowed'.format(host, port, datetime.now()), 'info') # 2. Always insert a TLS layer, even if there's neither client nor server tls. # An inline script may upgrade from http to https, # in which case we need some form of TLS layer. if isinstance(top_layer, modes.ReverseProxy): return protocol.TlsLayer(top_layer, client_tls, top_layer.server_tls, top_layer.server_conn.address[0]) if isinstance(top_layer, protocol.ServerConnectionMixin): return protocol.TlsLayer(top_layer, client_tls, client_tls) if isinstance(top_layer, protocol.UpstreamConnectLayer): # if the user manually sets a scheme for connect requests, we use this to decide if we # want TLS or not. if top_layer.connect_request.scheme: server_tls = top_layer.connect_request.scheme == "https" else: server_tls = client_tls return protocol.TlsLayer(top_layer, client_tls, server_tls) # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. if isinstance(top_layer, protocol.TlsLayer): if isinstance(top_layer.ctx, modes.HttpProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.regular) if isinstance(top_layer.ctx, modes.HttpUpstreamProxy): return protocol.Http1Layer(top_layer, http.HTTPMode.upstream) # 4. Check for other TLS cases (e.g. after CONNECT). if client_tls: return protocol.TlsLayer(top_layer, True, True) # 4. Check for --tcp if self.config.check_tcp(top_layer.server_conn.address): return protocol.RawTCPLayer(top_layer) # 5. Check for TLS ALPN (HTTP1/HTTP2) if isinstance(top_layer, protocol.TlsLayer): alpn = top_layer.client_conn.get_alpn_proto_negotiated() if alpn == b'h2': return protocol.Http2Layer(top_layer, http.HTTPMode.transparent) if alpn == b'http/1.1': return protocol.Http1Layer(top_layer, http.HTTPMode.transparent) # 6. Check for raw tcp mode is_ascii = ( len(d) == 3 and # expect A-Za-z all(65 <= x <= 90 or 97 <= x <= 122 for x in d)) if self.config.options.rawtcp and not is_ascii: return protocol.RawTCPLayer(top_layer) # 7. Assume HTTP1 by default return protocol.Http1Layer(top_layer, http.HTTPMode.transparent)