Allow separate proxy for onions

- new options in network section: onionsocksproxytype,
onionsockshostname and onionsocksport. These allow to separate
connectivity types for onion and non-onion addresses, e.g. connect to
clear nodes over clearnet and onions over tor
- also remove some obsolete imports
This commit is contained in:
Peter Šurda 2018-02-04 21:03:54 +01:00
parent fd1a6c1fa1
commit a646ec4902
Signed by: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
2 changed files with 46 additions and 6 deletions

View File

@ -1,3 +1,4 @@
from ConfigParser import NoOptionError, NoSectionError
import errno import errno
import socket import socket
import time import time
@ -8,8 +9,6 @@ from bmconfigparser import BMConfigParser
from debug import logger from debug import logger
import helper_bootstrap import helper_bootstrap
from network.proxy import Proxy from network.proxy import Proxy
from network.bmproto import BMProto
from network.dandelion import Dandelion
from network.tcp import TCPServer, Socks5BMConnection, Socks4aBMConnection, TCPConnection from network.tcp import TCPServer, Socks5BMConnection, Socks4aBMConnection, TCPConnection
from network.udp import UDPSocket from network.udp import UDPSocket
from network.connectionchooser import chooseConnection from network.connectionchooser import chooseConnection
@ -143,6 +142,15 @@ class BMConnectionPool(object):
self.bootstrapped = True self.bootstrapped = True
Proxy.proxy = (BMConfigParser().safeGet("bitmessagesettings", "sockshostname"), Proxy.proxy = (BMConfigParser().safeGet("bitmessagesettings", "sockshostname"),
BMConfigParser().safeGetInt("bitmessagesettings", "socksport")) BMConfigParser().safeGetInt("bitmessagesettings", "socksport"))
# TODO AUTH
# TODO reset based on GUI settings changes
try:
if not BMConfigParser().get("network", "onionsocksproxytype").beginswith("SOCKS"):
raise NoOptionError
Proxy.onionproxy = (BMConfigParser().get("network", "onionsockshostname"),
BMConfigParser().getint("network", "onionsocksport"))
except (NoOptionError, NoSectionError):
Proxy.onionproxy = None
established = sum(1 for c in self.outboundConnections.values() if (c.connected and c.fullyEstablished)) established = sum(1 for c in self.outboundConnections.values() if (c.connected and c.fullyEstablished))
pending = len(self.outboundConnections) - established pending = len(self.outboundConnections) - established
if established < BMConfigParser().safeGetInt("bitmessagesettings", "maxoutboundconnections"): if established < BMConfigParser().safeGetInt("bitmessagesettings", "maxoutboundconnections"):
@ -166,15 +174,23 @@ class BMConnectionPool(object):
# if chosen.host == c.destination.host: # if chosen.host == c.destination.host:
# continue # continue
try: try:
if (BMConfigParser().safeGet("bitmessagesettings", "socksproxytype") == "SOCKS5"): if chosen.host.endswith(".onion") and Proxy.onionproxy is not None:
if BMConfigParser().get("network", "onionsocksproxytype") == "SOCKS5":
self.addConnection(Socks5BMConnection(chosen))
elif BMConfigParser().get("network", "onionsocksproxytype") == "SOCKS4a":
self.addConnection(Socks4aBMConnection(chosen))
elif BMConfigParser().safeGet("bitmessagesettings", "socksproxytype") == "SOCKS5":
self.addConnection(Socks5BMConnection(chosen)) self.addConnection(Socks5BMConnection(chosen))
elif (BMConfigParser().safeGet("bitmessagesettings", "socksproxytype") == "SOCKS4a"): elif BMConfigParser().safeGet("bitmessagesettings", "socksproxytype") == "SOCKS4a":
self.addConnection(Socks4aBMConnection(chosen)) self.addConnection(Socks4aBMConnection(chosen))
elif not chosen.host.endswith(".onion"): else:
self.addConnection(TCPConnection(chosen)) self.addConnection(TCPConnection(chosen))
except socket.error as e: except socket.error as e:
if e.errno == errno.ENETUNREACH: if e.errno == errno.ENETUNREACH:
continue continue
except (NoSectionError, NoOptionError):
# shouldn't happen
pass
self.lastSpawned = time.time() self.lastSpawned = time.time()
else: else:

View File

@ -37,6 +37,8 @@ class Proxy(AdvancedDispatcher):
# instances should change too # instances should change too
_proxy = ("127.0.0.1", 9050) _proxy = ("127.0.0.1", 9050)
_auth = None _auth = None
_onion_proxy = None
_onion_auth = None
_remote_dns = True _remote_dns = True
@property @property
@ -58,6 +60,25 @@ class Proxy(AdvancedDispatcher):
def auth(self, authTuple): def auth(self, authTuple):
self.__class__._auth = authTuple self.__class__._auth = authTuple
@property
def onion_proxy(self):
return self.__class__._onion_proxy
@onion_proxy.setter
def onion_proxy(self, address):
if address is not None and (not isinstance(address, tuple) or (len(address) < 2) or \
(not isinstance(address[0], str) or not isinstance(address[1], int))):
raise ValueError
self.__class__._onion_proxy = address
@property
def onion_auth(self):
return self.__class__._onion_auth
@onion_auth.setter
def onion_auth(self, authTuple):
self.__class__._onion_auth = authTuple
def __init__(self, address): def __init__(self, address):
if not isinstance(address, state.Peer): if not isinstance(address, state.Peer):
raise ValueError raise ValueError
@ -66,7 +87,10 @@ class Proxy(AdvancedDispatcher):
self.isOutbound = True self.isOutbound = True
self.fullyEstablished = False self.fullyEstablished = False
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect(self.proxy) if address.host.endswith(".onion") and self.onion_proxy is not None:
self.connect(self.onion_proxy)
else:
self.connect(self.proxy)
def handle_connect(self): def handle_connect(self):
self.set_state("init") self.set_state("init")