def socks_connect(self, connect_to): try: client_greet = socks.ClientGreeting( socks.VERSION.SOCKS5, [socks.METHOD.NO_AUTHENTICATION_REQUIRED]) client_greet.to_file(self.wfile) self.wfile.flush() server_greet = socks.ServerGreeting.from_file(self.rfile) server_greet.assert_socks5() if server_greet.method != socks.METHOD.NO_AUTHENTICATION_REQUIRED: raise socks.SocksError( socks.METHOD.NO_ACCEPTABLE_METHODS, "pathoc only supports SOCKS without authentication") connect_request = socks.Message(socks.VERSION.SOCKS5, socks.CMD.CONNECT, socks.ATYP.DOMAINNAME, tcp.Address.wrap(connect_to)) connect_request.to_file(self.wfile) self.wfile.flush() connect_reply = socks.Message.from_file(self.rfile) connect_reply.assert_socks5() if connect_reply.msg != socks.REP.SUCCEEDED: raise socks.SocksError(connect_reply.msg, "SOCKS server error") except (socks.SocksError, TcpDisconnect) as e: raise PathocError(str(e))
def __call__(self): try: # Parse Client Greeting client_greet = socks.ClientGreeting.from_file(self.client_conn.rfile, fail_early=True) client_greet.assert_socks5() if socks.METHOD.NO_AUTHENTICATION_REQUIRED not in client_greet.methods: raise socks.SocksError( socks.METHOD.NO_ACCEPTABLE_METHODS, "mitmproxy only supports SOCKS without authentication" ) # Send Server Greeting server_greet = socks.ServerGreeting( socks.VERSION.SOCKS5, socks.METHOD.NO_AUTHENTICATION_REQUIRED ) server_greet.to_file(self.client_conn.wfile) self.client_conn.wfile.flush() # Parse Connect Request connect_request = socks.Message.from_file(self.client_conn.rfile) connect_request.assert_socks5() if connect_request.msg != socks.CMD.CONNECT: raise socks.SocksError( socks.REP.COMMAND_NOT_SUPPORTED, "mitmproxy only supports SOCKS5 CONNECT." ) # We always connect lazily, but we need to pretend to the client that we connected. connect_reply = socks.Message( socks.VERSION.SOCKS5, socks.REP.SUCCEEDED, connect_request.atyp, # dummy value, we don't have an upstream connection yet. connect_request.addr ) connect_reply.to_file(self.client_conn.wfile) self.client_conn.wfile.flush() except (socks.SocksError, TcpException) as e: raise Socks5ProtocolException("SOCKS5 mode failure: %s" % repr(e)) # https://github.com/mitmproxy/mitmproxy/issues/839 address_bytes = (connect_request.addr.host.encode("idna"), connect_request.addr.port) self.server_conn.address = tcp.Address(address_bytes, connect_request.addr.use_ipv6) layer = self.ctx.next_layer(self) try: layer() finally: if self.server_conn: self.disconnect()
def get_upstream_server(self, client_conn): try: # Parse Client Greeting client_greet = socks.ClientGreeting.from_file(client_conn.rfile) self._assert_socks5(client_greet) if socks.METHOD.NO_AUTHENTICATION_REQUIRED not in client_greet.methods: raise socks.SocksError( socks.METHOD.NO_ACCEPTABLE_METHODS, "mitmproxy only supports SOCKS without authentication") # Send Server Greeting server_greet = socks.ServerGreeting( socks.VERSION.SOCKS5, socks.METHOD.NO_AUTHENTICATION_REQUIRED) server_greet.to_file(client_conn.wfile) client_conn.wfile.flush() # Parse Connect Request connect_request = socks.Message.from_file(client_conn.rfile) self._assert_socks5(connect_request) if connect_request.msg != socks.CMD.CONNECT: raise socks.SocksError( socks.REP.COMMAND_NOT_SUPPORTED, "mitmproxy only supports SOCKS5 CONNECT.") # We do not connect here yet, as the clientconnect event has not been handled yet. connect_reply = socks.Message( socks.VERSION.SOCKS5, socks.REP.SUCCEEDED, socks.ATYP.DOMAINNAME, client_conn. address # dummy value, we don't have an upstream connection yet. ) connect_reply.to_file(client_conn.wfile) client_conn.wfile.flush() ssl = bool(connect_request.addr.port in self.sslports) return ssl, ssl, connect_request.addr.host, connect_request.addr.port except socks.SocksError as e: msg = socks.Message(5, e.code, socks.ATYP.DOMAINNAME, repr(e)) try: msg.to_file(client_conn.wfile) except: pass raise ProxyError(502, "SOCKS5 mode failure: %s" % str(e))
def _assert_socks5(msg): if msg.ver != socks.VERSION.SOCKS5: if msg.ver == ord("G") and len(msg.methods) == ord("E"): guess = "Probably not a SOCKS request but a regular HTTP request. " else: guess = "" raise socks.SocksError( socks.REP.GENERAL_SOCKS_SERVER_FAILURE, guess + "Invalid SOCKS version. Expected 0x05, got 0x%x" % msg.ver)