From 3e9125a3c13084f4abb0e5b74554909f24df9454 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 21 Feb 2017 00:20:44 +0100 Subject: [PATCH] nuke tcp.Address and add proper IPv6 support --- mitmproxy/connections.py | 20 +- mitmproxy/flowfilter.py | 10 +- mitmproxy/http.py | 4 +- mitmproxy/io_compat.py | 5 + mitmproxy/master.py | 4 +- mitmproxy/net/socks.py | 18 +- mitmproxy/net/tcp.py | 195 +++++++----------- mitmproxy/net/wsgi.py | 7 +- mitmproxy/proxy/config.py | 5 +- mitmproxy/proxy/protocol/base.py | 10 +- mitmproxy/proxy/protocol/http.py | 18 +- mitmproxy/proxy/protocol/tls.py | 7 +- mitmproxy/proxy/root_context.py | 4 +- mitmproxy/proxy/server.py | 5 +- mitmproxy/test/tflow.py | 6 +- mitmproxy/tools/console/flowdetailview.py | 6 +- mitmproxy/tools/console/master.py | 8 +- mitmproxy/tools/console/statusbar.py | 8 +- mitmproxy/tools/dump.py | 2 +- mitmproxy/tools/web/master.py | 2 +- mitmproxy/tools/web/static/app.js | Bin 327708 -> 327668 bytes pathod/pathoc.py | 4 +- pathod/pathod.py | 2 +- pathod/protocols/http2.py | 6 +- pathod/test.py | 6 +- test/mitmproxy/addons/test_dumper.py | 2 +- test/mitmproxy/net/test_socks.py | 5 +- test/mitmproxy/net/test_tcp.py | 18 +- test/mitmproxy/net/tservers.py | 4 +- test/mitmproxy/proxy/protocol/test_http2.py | 26 +-- .../proxy/protocol/test_websocket.py | 8 +- test/mitmproxy/proxy/test_server.py | 9 +- test/mitmproxy/test_flow.py | 2 +- test/mitmproxy/test_flowfilter.py | 10 + test/mitmproxy/test_proxy.py | 2 +- test/mitmproxy/tservers.py | 5 +- web/src/js/components/FlowView/Details.jsx | 2 +- web/src/js/filt/filt.peg | 4 +- 38 files changed, 208 insertions(+), 251 deletions(-) diff --git a/mitmproxy/connections.py b/mitmproxy/connections.py index f914c7d27..6d7c3c769 100644 --- a/mitmproxy/connections.py +++ b/mitmproxy/connections.py @@ -60,10 +60,11 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject): ) else: alpn = "" - return "".format( + return "".format( ssl="[ssl] " if self.ssl_established else "", alpn=alpn, - address=repr(self.address) + host=self.address[0], + port=self.address[1], ) @property @@ -71,7 +72,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject): return self.ssl_established _stateobject_attributes = dict( - address=tcp.Address, + address=tuple, ssl_established=bool, clientcert=certs.SSLCert, mitmcert=certs.SSLCert, @@ -176,10 +177,11 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject): ) else: alpn = "" - return "".format( + return "".format( ssl=ssl, alpn=alpn, - address=repr(self.address) + host=self.address[0], + port=self.address[1], ) @property @@ -187,9 +189,9 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject): return self.ssl_established _stateobject_attributes = dict( - address=tcp.Address, - ip_address=tcp.Address, - source_address=tcp.Address, + address=tuple, + ip_address=tuple, + source_address=tuple, ssl_established=bool, cert=certs.SSLCert, sni=str, @@ -244,7 +246,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject): else: path = os.path.join( clientcerts, - self.address.host.encode("idna").decode()) + ".pem" + self.address[0].encode("idna").decode()) + ".pem" if os.path.exists(path): clientcert = path diff --git a/mitmproxy/flowfilter.py b/mitmproxy/flowfilter.py index 4a0eeeb10..d4c0b3eaf 100644 --- a/mitmproxy/flowfilter.py +++ b/mitmproxy/flowfilter.py @@ -348,7 +348,10 @@ class FSrc(_Rex): is_binary = False def __call__(self, f): - return f.client_conn.address and self.re.search(repr(f.client_conn.address)) + if not f.client_conn or not f.client_conn.address: + return False + r = "{}:{}".format(f.client_conn.address[0], f.client_conn.address[1]) + return f.client_conn.address and self.re.search(r) class FDst(_Rex): @@ -357,7 +360,10 @@ class FDst(_Rex): is_binary = False def __call__(self, f): - return f.server_conn.address and self.re.search(repr(f.server_conn.address)) + if not f.server_conn or not f.server_conn.address: + return False + r = "{}:{}".format(f.server_conn.address[0], f.server_conn.address[1]) + return f.server_conn.address and self.re.search(r) class _Int(_Action): diff --git a/mitmproxy/http.py b/mitmproxy/http.py index f0cabcf8e..c6b175334 100644 --- a/mitmproxy/http.py +++ b/mitmproxy/http.py @@ -5,7 +5,6 @@ from mitmproxy import flow from mitmproxy.net import http from mitmproxy import version -from mitmproxy.net import tcp from mitmproxy import connections # noqa @@ -245,9 +244,8 @@ def make_error_response( def make_connect_request(address): - address = tcp.Address.wrap(address) return HTTPRequest( - "authority", b"CONNECT", None, address.host, address.port, None, b"HTTP/1.1", + "authority", b"CONNECT", None, address[0], address[1], None, b"HTTP/1.1", http.Headers(), b"" ) diff --git a/mitmproxy/io_compat.py b/mitmproxy/io_compat.py index c12d2098d..4c840da57 100644 --- a/mitmproxy/io_compat.py +++ b/mitmproxy/io_compat.py @@ -88,6 +88,11 @@ def convert_019_100(data): def convert_100_200(data): data["version"] = (2, 0, 0) + data["client_conn"]["address"] = data["client_conn"]["address"]["address"] + data["server_conn"]["address"] = data["server_conn"]["address"]["address"] + data["server_conn"]["source_address"] = data["server_conn"]["source_address"]["address"] + if data["server_conn"]["ip_address"]: + data["server_conn"]["ip_address"] = data["server_conn"]["ip_address"]["address"] return data diff --git a/mitmproxy/master.py b/mitmproxy/master.py index 3a3f43999..633f32aa5 100644 --- a/mitmproxy/master.py +++ b/mitmproxy/master.py @@ -149,8 +149,8 @@ class Master: """ if isinstance(f, http.HTTPFlow): if self.server and self.options.mode == "reverse": - f.request.host = self.server.config.upstream_server.address.host - f.request.port = self.server.config.upstream_server.address.port + f.request.host = self.server.config.upstream_server.address[0] + f.request.port = self.server.config.upstream_server.address[1] f.request.scheme = self.server.config.upstream_server.scheme f.reply = controller.DummyReply() for e, o in eventsequence.iterate(f): diff --git a/mitmproxy/net/socks.py b/mitmproxy/net/socks.py index a972283e0..570a4afbb 100644 --- a/mitmproxy/net/socks.py +++ b/mitmproxy/net/socks.py @@ -2,7 +2,6 @@ import struct import array import ipaddress -from mitmproxy.net import tcp from mitmproxy.net import check from mitmproxy.types import bidi @@ -179,7 +178,7 @@ class Message: self.ver = ver self.msg = msg self.atyp = atyp - self.addr = tcp.Address.wrap(addr) + self.addr = addr def assert_socks5(self): if self.ver != VERSION.SOCKS5: @@ -199,37 +198,34 @@ class Message: if atyp == ATYP.IPV4_ADDRESS: # We use tnoa here as ntop is not commonly available on Windows. host = ipaddress.IPv4Address(f.safe_read(4)).compressed - use_ipv6 = False elif atyp == ATYP.IPV6_ADDRESS: host = ipaddress.IPv6Address(f.safe_read(16)).compressed - use_ipv6 = True elif atyp == ATYP.DOMAINNAME: length, = struct.unpack("!B", f.safe_read(1)) host = f.safe_read(length) if not check.is_valid_host(host): raise SocksError(REP.GENERAL_SOCKS_SERVER_FAILURE, "Invalid hostname: %s" % host) host = host.decode("idna") - use_ipv6 = False else: raise SocksError(REP.ADDRESS_TYPE_NOT_SUPPORTED, "Socks Request: Unknown ATYP: %s" % atyp) port, = struct.unpack("!H", f.safe_read(2)) - addr = tcp.Address((host, port), use_ipv6=use_ipv6) + addr = (host, port) return cls(ver, msg, atyp, addr) def to_file(self, f): f.write(struct.pack("!BBBB", self.ver, self.msg, 0x00, self.atyp)) if self.atyp == ATYP.IPV4_ADDRESS: - f.write(ipaddress.IPv4Address(self.addr.host).packed) + f.write(ipaddress.IPv4Address(self.addr[0]).packed) elif self.atyp == ATYP.IPV6_ADDRESS: - f.write(ipaddress.IPv6Address(self.addr.host).packed) + f.write(ipaddress.IPv6Address(self.addr[0]).packed) elif self.atyp == ATYP.DOMAINNAME: - f.write(struct.pack("!B", len(self.addr.host))) - f.write(self.addr.host.encode("idna")) + f.write(struct.pack("!B", len(self.addr[0]))) + f.write(self.addr[0].encode("idna")) else: raise SocksError( REP.ADDRESS_TYPE_NOT_SUPPORTED, "Unknown ATYP: %s" % self.atyp ) - f.write(struct.pack("!H", self.addr.port)) + f.write(struct.pack("!H", self.addr[1])) diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py index eabc8006e..605a11a73 100644 --- a/mitmproxy/net/tcp.py +++ b/mitmproxy/net/tcp.py @@ -19,7 +19,6 @@ from OpenSSL import SSL from mitmproxy import certs from mitmproxy.utils import version_check -from mitmproxy.types import serializable from mitmproxy import exceptions from mitmproxy.types import basethread @@ -29,6 +28,11 @@ version_check.check_pyopenssl_version() socket_fileobject = socket.SocketIO +# workaround for https://bugs.python.org/issue29515 +# Python 3.5 and 3.6 for Windows is missing a constant +if not hasattr(socket, 'IPV6_V6ONLY'): + socket.IPV6_V6ONLY = 41 + EINTR = 4 HAS_ALPN = SSL._lib.Cryptography_HAS_ALPN @@ -299,73 +303,6 @@ class Reader(_FileLike): raise NotImplementedError("Can only peek into (pyOpenSSL) sockets") -class Address(serializable.Serializable): - - """ - This class wraps an IPv4/IPv6 tuple to provide named attributes and - ipv6 information. - """ - - def __init__(self, address, use_ipv6=False): - self.address = tuple(address) - self.use_ipv6 = use_ipv6 - - def get_state(self): - return { - "address": self.address, - "use_ipv6": self.use_ipv6 - } - - def set_state(self, state): - self.address = state["address"] - self.use_ipv6 = state["use_ipv6"] - - @classmethod - def from_state(cls, state): - return Address(**state) - - @classmethod - def wrap(cls, t): - if isinstance(t, cls): - return t - else: - return cls(t) - - def __call__(self): - return self.address - - @property - def host(self): - return self.address[0] - - @property - def port(self): - return self.address[1] - - @property - def use_ipv6(self): - return self.family == socket.AF_INET6 - - @use_ipv6.setter - def use_ipv6(self, b): - self.family = socket.AF_INET6 if b else socket.AF_INET - - def __repr__(self): - return "{}:{}".format(self.host, self.port) - - def __eq__(self, other): - if not other: - return False - other = Address.wrap(other) - return (self.address, self.family) == (other.address, other.family) - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash(self.address) ^ 42 # different hash than the tuple alone. - - def ssl_read_select(rlist, timeout): """ This is a wrapper around select.select() which also works for SSL.Connections @@ -452,7 +389,7 @@ class _Connection: def __init__(self, connection): if connection: self.connection = connection - self.ip_address = Address(connection.getpeername()) + self.ip_address = connection.getpeername() self._makefile() else: self.connection = None @@ -629,28 +566,6 @@ class TCPClient(_Connection): self.sni = None self.spoof_source_address = spoof_source_address - @property - def address(self): - return self.__address - - @address.setter - def address(self, address): - if address: - self.__address = Address.wrap(address) - else: - self.__address = None - - @property - def source_address(self): - return self.__source_address - - @source_address.setter - def source_address(self, source_address): - if source_address: - self.__source_address = Address.wrap(source_address) - else: - self.__source_address = None - def close(self): # Make sure to close the real socket, not the SSL proxy. # OpenSSL is really good at screwing up, i.e. when trying to recv from a failed connection, @@ -741,34 +656,57 @@ class TCPClient(_Connection): self.rfile.set_descriptor(self.connection) self.wfile.set_descriptor(self.connection) - def makesocket(self): + def makesocket(self, family, type, proto): # some parties (cuckoo sandbox) need to hook this - return socket.socket(self.address.family, socket.SOCK_STREAM) + return socket.socket(family, type, proto) + + def create_connection(self, timeout=None): + # Based on the official socket.create_connection implementation of Python 3.6. + # https://github.com/python/cpython/blob/3cc5817cfaf5663645f4ee447eaed603d2ad290a/Lib/socket.py + + err = None + for res in socket.getaddrinfo(self.address[0], self.address[1], 0, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = self.makesocket(af, socktype, proto) + if timeout: + sock.settimeout(timeout) + if self.source_address: + sock.bind(self.source_address) + if self.spoof_source_address: + try: + if not sock.getsockopt(socket.SOL_IP, socket.IP_TRANSPARENT): + sock.setsockopt(socket.SOL_IP, socket.IP_TRANSPARENT, 1) + except Exception as e: + # socket.IP_TRANSPARENT might not be available on every OS and Python version + raise exceptions.TcpException( + "Failed to spoof the source address: " + e.strerror + ) + sock.connect(sa) + return sock + + except socket.error as _: + err = _ + if sock is not None: + sock.close() + + if err is not None: + raise err + else: + raise socket.error("getaddrinfo returns an empty list") def connect(self): try: - connection = self.makesocket() - - if self.spoof_source_address: - try: - # 19 is `IP_TRANSPARENT`, which is only available on Python 3.3+ on some OSes - if not connection.getsockopt(socket.SOL_IP, 19): - connection.setsockopt(socket.SOL_IP, 19, 1) - except socket.error as e: - raise exceptions.TcpException( - "Failed to spoof the source address: " + e.strerror - ) - if self.source_address: - connection.bind(self.source_address()) - connection.connect(self.address()) - self.source_address = Address(connection.getsockname()) + connection = self.create_connection() except (socket.error, IOError) as err: raise exceptions.TcpException( 'Error connecting to "%s": %s' % - (self.address.host, err) + (self.address[0], err) ) self.connection = connection - self.ip_address = Address(connection.getpeername()) + self.source_address = connection.getsockname() + self.ip_address = connection.getpeername() self._makefile() return ConnectionCloser(self) @@ -793,7 +731,7 @@ class BaseHandler(_Connection): def __init__(self, connection, address, server): super().__init__(connection) - self.address = Address.wrap(address) + self.address = address self.server = server self.clientcert = None @@ -915,19 +853,36 @@ class TCPServer: request_queue_size = 20 def __init__(self, address): - self.address = Address.wrap(address) + self.address = address self.__is_shut_down = threading.Event() self.__shutdown_request = False - self.socket = socket.socket(self.address.family, socket.SOCK_STREAM) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.bind(self.address()) - self.address = Address.wrap(self.socket.getsockname()) + + if self.address == 'localhost': + raise socket.error("Binding to 'localhost' is prohibited. Please use '::1' or '127.0.0.1' directly.") + + try: + # First try to bind an IPv6 socket, with possible IPv4 if the OS supports it. + # This allows us to accept connections for ::1 and 127.0.0.1 on the same socket. + # Only works if self.address == "" + self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) + self.socket.bind(self.address) + except: + self.socket = None + + if not self.socket: + # Binding to an IPv6 socket failed, lets fall back to IPv4. + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.bind(self.address) + + self.address = self.socket.getsockname() self.socket.listen(self.request_queue_size) self.handler_counter = Counter() def connection_thread(self, connection, client_address): with self.handler_counter: - client_address = Address(client_address) try: self.handle_client_connection(connection, client_address) except: @@ -954,8 +909,8 @@ class TCPServer: self.__class__.__name__, client_address[0], client_address[1], - self.address.host, - self.address.port + self.address[0], + self.address[1], ), target=self.connection_thread, args=(connection, client_address), @@ -964,7 +919,7 @@ class TCPServer: try: t.start() except threading.ThreadError: - self.handle_error(connection, Address(client_address)) + self.handle_error(connection, client_address) connection.close() finally: self.__shutdown_request = False diff --git a/mitmproxy/net/wsgi.py b/mitmproxy/net/wsgi.py index 8bc5bb89d..a40dcecaa 100644 --- a/mitmproxy/net/wsgi.py +++ b/mitmproxy/net/wsgi.py @@ -4,14 +4,13 @@ import urllib import io from mitmproxy.net import http -from mitmproxy.net import tcp from mitmproxy.utils import strutils class ClientConn: def __init__(self, address): - self.address = tcp.Address.wrap(address) + self.address = address class Flow: @@ -84,8 +83,8 @@ class WSGIAdaptor: } environ.update(extra) if flow.client_conn.address: - environ["REMOTE_ADDR"] = strutils.always_str(flow.client_conn.address.host, "latin-1") - environ["REMOTE_PORT"] = flow.client_conn.address.port + environ["REMOTE_ADDR"] = strutils.always_str(flow.client_conn.address[0], "latin-1") + environ["REMOTE_PORT"] = flow.client_conn.address[1] for key, value in flow.request.headers.items(): key = 'HTTP_' + strutils.always_str(key, "latin-1").upper().replace('-', '_') diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py index 513c0b5b9..ea2f7c7f1 100644 --- a/mitmproxy/proxy/config.py +++ b/mitmproxy/proxy/config.py @@ -23,8 +23,7 @@ class HostMatcher: def __call__(self, address): if not address: return False - address = tcp.Address.wrap(address) - host = "%s:%s" % (address.host, address.port) + host = "%s:%s" % address if any(rex.search(host) for rex in self.regexes): return True else: @@ -47,7 +46,7 @@ def parse_server_spec(spec): "Invalid server specification: %s" % spec ) host, port = p[1:3] - address = tcp.Address((host.decode("ascii"), port)) + address = (host.decode("ascii"), port) scheme = p[0].decode("ascii").lower() return ServerSpec(scheme, address) diff --git a/mitmproxy/proxy/protocol/base.py b/mitmproxy/proxy/protocol/base.py index 936191717..b10bb8f58 100644 --- a/mitmproxy/proxy/protocol/base.py +++ b/mitmproxy/proxy/protocol/base.py @@ -101,7 +101,7 @@ class ServerConnectionMixin: self.server_conn = None if self.config.options.spoof_source_address and self.config.options.upstream_bind_address == '': self.server_conn = connections.ServerConnection( - server_address, (self.ctx.client_conn.address.host, 0), True) + server_address, (self.ctx.client_conn.address[0], 0), True) else: self.server_conn = connections.ServerConnection( server_address, (self.config.options.upstream_bind_address, 0), @@ -118,8 +118,8 @@ class ServerConnectionMixin: address = self.server_conn.address if address: self_connect = ( - address.port == self.config.options.listen_port and - address.host in ("localhost", "127.0.0.1", "::1") + address[1] == self.config.options.listen_port and + address[0] in ("localhost", "127.0.0.1", "::1") ) if self_connect: raise exceptions.ProtocolException( @@ -133,7 +133,7 @@ class ServerConnectionMixin: """ if self.server_conn.connected(): self.disconnect() - self.log("Set new server address: " + repr(address), "debug") + self.log("Set new server address: {}:{}".format(address[0], address[1]), "debug") self.server_conn.address = address self.__check_self_connect() @@ -150,7 +150,7 @@ class ServerConnectionMixin: self.server_conn = connections.ServerConnection( address, - (self.server_conn.source_address.host, 0), + (self.server_conn.source_address[0], 0), self.config.options.spoof_source_address ) diff --git a/mitmproxy/proxy/protocol/http.py b/mitmproxy/proxy/protocol/http.py index a7d56f24b..16d04eeb1 100644 --- a/mitmproxy/proxy/protocol/http.py +++ b/mitmproxy/proxy/protocol/http.py @@ -8,7 +8,6 @@ from mitmproxy import http from mitmproxy import flow from mitmproxy.proxy.protocol import base from mitmproxy.proxy.protocol.websocket import WebSocketLayer -from mitmproxy.net import tcp from mitmproxy.net import websockets @@ -59,7 +58,7 @@ class ConnectServerConnection: """ def __init__(self, address, ctx): - self.address = tcp.Address.wrap(address) + self.address = address self._ctx = ctx @property @@ -112,9 +111,8 @@ class UpstreamConnectLayer(base.Layer): def set_server(self, address): if self.ctx.server_conn.connected(): self.ctx.disconnect() - address = tcp.Address.wrap(address) - self.connect_request.host = address.host - self.connect_request.port = address.port + self.connect_request.host = address[0] + self.connect_request.port = address[1] self.server_conn.address = address @@ -291,7 +289,7 @@ class HttpLayer(base.Layer): # update host header in reverse proxy mode if self.config.options.mode == "reverse": - f.request.host_header = self.config.upstream_server.address.host + f.request.host_header = self.config.upstream_server.address[0] # Determine .scheme, .host and .port attributes for inline scripts. For # absolute-form requests, they are directly given in the request. For @@ -302,8 +300,8 @@ class HttpLayer(base.Layer): # Setting request.host also updates the host header, which we want # to preserve host_header = f.request.host_header - f.request.host = self.__initial_server_conn.address.host - f.request.port = self.__initial_server_conn.address.port + f.request.host = self.__initial_server_conn.address[0] + f.request.port = self.__initial_server_conn.address[1] f.request.host_header = host_header # set again as .host overwrites this. f.request.scheme = "https" if self.__initial_server_tls else "http" self.channel.ask("request", f) @@ -453,14 +451,14 @@ class HttpLayer(base.Layer): self.set_server(address) def establish_server_connection(self, host: str, port: int, scheme: str): - address = tcp.Address((host, port)) tls = (scheme == "https") if self.mode is HTTPMode.regular or self.mode is HTTPMode.transparent: # If there's an existing connection that doesn't match our expectations, kill it. + address = (host, port) if address != self.server_conn.address or tls != self.server_tls: self.set_server(address) - self.set_server_tls(tls, address.host) + self.set_server_tls(tls, address[0]) # Establish connection is neccessary. if not self.server_conn.connected(): self.connect() diff --git a/mitmproxy/proxy/protocol/tls.py b/mitmproxy/proxy/protocol/tls.py index 08ce53d06..7d15130f8 100644 --- a/mitmproxy/proxy/protocol/tls.py +++ b/mitmproxy/proxy/protocol/tls.py @@ -545,8 +545,9 @@ class TlsLayer(base.Layer): raise exceptions.InvalidServerCertificate(str(e)) except exceptions.TlsException as e: raise exceptions.TlsProtocolException( - "Cannot establish TLS with {address} (sni: {sni}): {e}".format( - address=repr(self.server_conn.address), + "Cannot establish TLS with {host}:{port} (sni: {sni}): {e}".format( + host=self.server_conn.address[0], + port=self.server_conn.address[1], sni=self.server_sni, e=repr(e) ) @@ -567,7 +568,7 @@ class TlsLayer(base.Layer): # However, we may just want to establish TLS so that we can send an error message to the client, # in which case the address can be None. if self.server_conn.address: - host = self.server_conn.address.host.encode("idna") + host = self.server_conn.address[0].encode("idna") # Should we incorporate information from the server certificate? use_upstream_cert = ( diff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py index 180fc9ca5..1987c8dc5 100644 --- a/mitmproxy/proxy/root_context.py +++ b/mitmproxy/proxy/root_context.py @@ -68,7 +68,7 @@ class RootContext: top_layer, client_tls, top_layer.server_tls, - top_layer.server_conn.address.host + top_layer.server_conn.address[0] ) if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer): return protocol.TlsLayer(top_layer, client_tls, client_tls) @@ -104,7 +104,7 @@ class RootContext: Send a log message to the master. """ full_msg = [ - "{}: {}".format(repr(self.client_conn.address), msg) + "{}:{}: {}".format(self.client_conn.address[0], self.client_conn.address[1], msg) ] for i in subs: full_msg.append(" -> " + i) diff --git a/mitmproxy/proxy/server.py b/mitmproxy/proxy/server.py index 97018dade..8082cb649 100644 --- a/mitmproxy/proxy/server.py +++ b/mitmproxy/proxy/server.py @@ -1,4 +1,3 @@ -import socket import sys import traceback @@ -46,10 +45,10 @@ class ProxyServer(tcp.TCPServer): ) if config.options.mode == "transparent": platform.init_transparent_mode() - except socket.error as e: + except Exception as e: raise exceptions.ServerException( 'Error starting proxy server: ' + repr(e) - ) + ) from e self.channel = None def set_channel(self, channel): diff --git a/mitmproxy/test/tflow.py b/mitmproxy/test/tflow.py index ea7be4b95..4454420bc 100644 --- a/mitmproxy/test/tflow.py +++ b/mitmproxy/test/tflow.py @@ -142,7 +142,7 @@ def tclient_conn(): @return: mitmproxy.proxy.connection.ClientConnection """ c = connections.ClientConnection.from_state(dict( - address=dict(address=("address", 22), use_ipv6=True), + address=("address", 22), clientcert=None, mitmcert=None, ssl_established=False, @@ -163,8 +163,8 @@ def tserver_conn(): @return: mitmproxy.proxy.connection.ServerConnection """ c = connections.ServerConnection.from_state(dict( - address=dict(address=("address", 22), use_ipv6=True), - source_address=dict(address=("address", 22), use_ipv6=True), + address=("address", 22), + source_address=("address", 22), ip_address=None, cert=None, timestamp_start=1, diff --git a/mitmproxy/tools/console/flowdetailview.py b/mitmproxy/tools/console/flowdetailview.py index d713787aa..691f19a5e 100644 --- a/mitmproxy/tools/console/flowdetailview.py +++ b/mitmproxy/tools/console/flowdetailview.py @@ -30,8 +30,8 @@ def flowdetails(state, flow: http.HTTPFlow): if sc is not None: text.append(urwid.Text([("head", "Server Connection:")])) parts = [ - ["Address", repr(sc.address)], - ["Resolved Address", repr(sc.ip_address)], + ["Address", "{}:{}".format(sc.address[0], sc.address[1])], + ["Resolved Address", "{}:{}".format(sc.ip_address[0], sc.ip_address[1])], ] if resp: parts.append(["HTTP Version", resp.http_version]) @@ -92,7 +92,7 @@ def flowdetails(state, flow: http.HTTPFlow): text.append(urwid.Text([("head", "Client Connection:")])) parts = [ - ["Address", repr(cc.address)], + ["Address", "{}:{}".format(cc.address[0], cc.address[1])], ] if req: parts.append(["HTTP Version", req.http_version]) diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index 4ab9e1f48..d68dc93c8 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -429,9 +429,11 @@ class ConsoleMaster(master.Master): super().tcp_message(f) message = f.messages[-1] direction = "->" if message.from_client else "<-" - signals.add_log("{client} {direction} tcp {direction} {server}".format( - client=repr(f.client_conn.address), - server=repr(f.server_conn.address), + signals.add_log("{client_host}:{client_port} {direction} tcp {direction} {server_host}:{server_port}".format( + client_host=f.client_conn.address[0], + client_port=f.client_conn.address[1], + server_host=f.server_conn.address[0], + server_port=f.server_conn.address[1], direction=direction, ), "info") signals.add_log(strutils.bytes_to_escaped_str(message.content), "debug") diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py index 2c7f9efb0..d90d932be 100644 --- a/mitmproxy/tools/console/statusbar.py +++ b/mitmproxy/tools/console/statusbar.py @@ -238,8 +238,8 @@ class StatusBar(urwid.WidgetWrap): dst = self.master.server.config.upstream_server r.append("[dest:%s]" % mitmproxy.net.http.url.unparse( dst.scheme, - dst.address.host, - dst.address.port + dst.address[0], + dst.address[1], )) if self.master.options.scripts: r.append("[") @@ -272,10 +272,10 @@ class StatusBar(urwid.WidgetWrap): ] if self.master.server.bound: - host = self.master.server.address.host + host = self.master.server.address[0] if host == "0.0.0.0": host = "*" - boundaddr = "[%s:%s]" % (host, self.master.server.address.port) + boundaddr = "[%s:%s]" % (host, self.master.server.address[1]) else: boundaddr = "" t.extend(self.get_status()) diff --git a/mitmproxy/tools/dump.py b/mitmproxy/tools/dump.py index e1e40fb0e..fefbddfb9 100644 --- a/mitmproxy/tools/dump.py +++ b/mitmproxy/tools/dump.py @@ -46,7 +46,7 @@ class DumpMaster(master.Master): if not self.options.no_server: self.add_log( - "Proxy server listening at http://{}".format(server.address), + "Proxy server listening at http://{}:{}".format(server.address[0], server.address[1]), "info" ) diff --git a/mitmproxy/tools/web/master.py b/mitmproxy/tools/web/master.py index 6ebcfe47a..8c7f579d8 100644 --- a/mitmproxy/tools/web/master.py +++ b/mitmproxy/tools/web/master.py @@ -109,7 +109,7 @@ class WebMaster(master.Master): tornado.ioloop.PeriodicCallback(lambda: self.tick(timeout=0), 5).start() self.add_log( - "Proxy server listening at http://{}/".format(self.server.address), + "Proxy server listening at http://{}:{}/".format(self.server.address[0], self.server.address[1]), "info" ) diff --git a/mitmproxy/tools/web/static/app.js b/mitmproxy/tools/web/static/app.js index 480d9c71bcb9e45744c26f13491705a2d1d008a1..c21a478b422d6a0d0193166c66477228b25c8cd9 100644 GIT binary patch delta 61 zcmbQ!AoAtEaKjeH$(rr6H5q}J35c1u&(>sdtDXLG8H>tx(d8`393ZCP^wjk%!qb6# Mk?jZ8v%~}d0Q{yGzW@LL delta 61 zcmezJUwBS~NW&J!$(rrmnv6iq1jNkSyER$-YNuaZ#-cO5W<86{cERN={v05_ Address: - {conn.address.address.join(':')} + {conn.address.join(':')} {conn.sni && ( diff --git a/web/src/js/filt/filt.peg b/web/src/js/filt/filt.peg index 989bfdd3a..7122a1a55 100644 --- a/web/src/js/filt/filt.peg +++ b/web/src/js/filt/filt.peg @@ -106,7 +106,7 @@ function destination(regex){ function destinationFilter(flow){ return (!!flow.server_conn.address) && - regex.test(flow.server_conn.address.address[0] + ":" + flow.server_conn.address.address[1]); + regex.test(flow.server_conn.address[0] + ":" + flow.server_conn.address[1]); } destinationFilter.desc = "destination address matches " + regex; return destinationFilter; @@ -172,7 +172,7 @@ function source(regex){ function sourceFilter(flow){ return (!!flow.client_conn.address) && - regex.test(flow.client_conn.address.address[0] + ":" + flow.client_conn.address.address[1]); + regex.test(flow.client_conn.address[0] + ":" + flow.client_conn.address[1]); } sourceFilter.desc = "source address matches " + regex; return sourceFilter;