From 1ada2e26e81916409261ddb476e520e364b1d3be Mon Sep 17 00:00:00 2001 From: Seth Barrios Date: Mon, 18 Nov 2019 14:51:25 -0800 Subject: [PATCH] Add support for IPv6-only environments Previously, the proxy would attempt to bind to an IPv6 + IPv4 enabled socket. On failure, it would try to bind to an IPv4 only socket. If that failed, the proxy would fail to start. This update makes it so that the proxy also tries to bind to an IPv6-only socket, which is necessary in environments where IPv4 is disabled. In short, the proxy will try binding in the following order, only moving to the next step when binding fails: IPv6 + IPv4 -> IPv4 only -> IPv6 only -> proxy fails to start. --- mitmproxy/net/tcp.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py index 2496d47c7..07cee466e 100644 --- a/mitmproxy/net/tcp.py +++ b/mitmproxy/net/tcp.py @@ -558,7 +558,7 @@ class TCPServer: self.socket = None try: - # First try to bind an IPv6 socket, with possible IPv4 if the OS supports it. + # First try to bind an IPv6 socket, attempting to enable IPv4 support 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) @@ -572,8 +572,20 @@ class TCPServer: 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) + try: + # Binding to an IPv6 + IPv4 socket failed, lets fall back to IPv4 only. + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + self.socket.bind(self.address) + except socket.error: + if self.socket: + self.socket.close() + self.socket = None + + if not self.socket: + # Binding to an IPv4 only socket failed, lets fall back to IPv6 only. + self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) self.socket.bind(self.address)