From 7b168b7041bdbd82609af6a316ed73362e5ff7b4 Mon Sep 17 00:00:00 2001 From: George McCandless <5fk7echy8@riseup.net> Date: Mon, 7 Dec 2020 22:54:44 +0000 Subject: [PATCH 1/2] Closes #1538. Changes 'onionservicesonly=true' to 'onlynet=onion'. Old-style 'onionservicesonly' is deprecated but still accepted. The configuration option will be upgraded upon the first GUI settings update. --- src/bitmessageqt/settings.py | 21 ++++++++++++++++++--- src/network/connectionchooser.py | 5 ++++- src/tests/core.py | 28 ++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py index f1c1a11f..6c3eee27 100644 --- a/src/bitmessageqt/settings.py +++ b/src/bitmessageqt/settings.py @@ -358,6 +358,11 @@ class SettingsDialog(QtGui.QDialog): if proxytype_index > 2: # last literal proxytype in ui start_proxyconfig() + onionOnly_deprecated = BMConfigParser().safeGetBoolean( + "bitmessagesettings", "onionservicesonly") + onionOnly = BMConfigParser().safeGet( + "bitmessagesettings", "onlynet") == "onion" + onionOnly = onionOnly or onionOnly_deprecated self.config.set('bitmessagesettings', 'socksauthentication', str( self.checkBoxAuthentication.isChecked())) self.config.set('bitmessagesettings', 'sockshostname', str( @@ -371,10 +376,20 @@ class SettingsDialog(QtGui.QDialog): self.config.set('bitmessagesettings', 'sockslisten', str( self.checkBoxSocksListen.isChecked())) if self.checkBoxOnionOnly.isChecked() \ - and not self.config.safeGetBoolean('bitmessagesettings', 'onionservicesonly'): + and not onionOnly: self.net_restart_needed = True - self.config.set('bitmessagesettings', 'onionservicesonly', str( - self.checkBoxOnionOnly.isChecked())) + if self.checkBoxOnionOnly.isChecked(): + self.config.set('bitmessagesettings', 'onlynet', 'onion') + else: + try: + return self.config.remove_option('bitmessagesettings', 'onlynet') + except ConfigParser.NoOptionError: + pass + # Remove deprecated onionservicesonly option if it exists: + try: + return self.config.remove_option('bitmessagesettings', 'onionservicesonly') + except ConfigParser.NoOptionError: + pass try: # Rounding to integers just for aesthetics self.config.set('bitmessagesettings', 'maxdownloadrate', str( diff --git a/src/network/connectionchooser.py b/src/network/connectionchooser.py index badd98b7..c3a11616 100644 --- a/src/network/connectionchooser.py +++ b/src/network/connectionchooser.py @@ -31,8 +31,11 @@ def chooseConnection(stream): """Returns an appropriate connection""" haveOnion = BMConfigParser().safeGet( "bitmessagesettings", "socksproxytype")[0:5] == 'SOCKS' - onionOnly = BMConfigParser().safeGetBoolean( + onionOnly_deprecated = BMConfigParser().safeGetBoolean( "bitmessagesettings", "onionservicesonly") + onionOnly = BMConfigParser().safeGet( + "bitmessagesettings", "onlynet") == "onion" + onionOnly = onionOnly or onionOnly_deprecated try: retval = portCheckerQueue.get(False) portCheckerQueue.task_done() diff --git a/src/tests/core.py b/src/tests/core.py index 3d8ac983..711e0e1a 100644 --- a/src/tests/core.py +++ b/src/tests/core.py @@ -194,14 +194,7 @@ class TestCore(unittest.TestCase): start_proxyconfig() self._check_bootstrap() - @unittest.skipUnless(stem_version, 'No stem, skipping tor dependent test') - def test_onionservicesonly(self): # this should start after bootstrap - """ - set onionservicesonly, wait for 3 connections and check them all - are onions - """ - BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5') - BMConfigParser().set('bitmessagesettings', 'onionservicesonly', 'true') + def _check_exclusively_onion_networking(self): self._initiate_bootstrap() BMConfigParser().remove_option('bitmessagesettings', 'dontconnect') for _ in range(360): @@ -218,6 +211,25 @@ class TestCore(unittest.TestCase): % peer.host) self.fail('Failed to connect to at least 3 nodes within 360 sec') + @unittest.skipUnless(stem_version, 'No stem, skipping tor dependent test') + def test_onionservicesonly(self): # this should start after bootstrap + """ + set onionservicesonly (deprecated), wait for 3 connections and check + that all are onions + """ + BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5') + BMConfigParser().set('bitmessagesettings', 'onionservicesonly', 'true') + self._check_exclusively_onion_networking() + + @unittest.skipUnless(stem_version, 'No stem, skipping tor dependent test') + def test_onlynetonion(self): # this should start after bootstrap + """ + set onlynet=onion, wait for 3 connections and check that all are onions + """ + BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5') + BMConfigParser().set('bitmessagesettings', 'onlynet', 'onion') + self._check_exclusively_onion_networking() + @staticmethod def _decode_msg(data, pattern): proto = BMProto() -- 2.47.2 From 3b58e1f251dcc7be9bffb849d15e7dbfd178a35f Mon Sep 17 00:00:00 2001 From: George McCandless <5fk7echy8@riseup.net> Date: Tue, 8 Dec 2020 00:58:50 +0000 Subject: [PATCH 2/2] bootstrap: Respect 'onlynet=onion' and, when a trusted peer is set, connect only to that trusted peer. --- src/network/connectionpool.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/network/connectionpool.py b/src/network/connectionpool.py index fffc0bc3..4d913978 100644 --- a/src/network/connectionpool.py +++ b/src/network/connectionpool.py @@ -51,6 +51,12 @@ class BMConnectionPool(object): BMConfigParser().safeGetInt( "bitmessagesettings", "maxuploadrate") ) + onionOnly_deprecated = BMConfigParser().safeGetBoolean( + "bitmessagesettings", "onionservicesonly") + onionOnly = BMConfigParser().safeGet( + "bitmessagesettings", "onlynet") == "onion" + + self.onionOnly = onionOnly or onionOnly_deprecated self.outboundConnections = {} self.inboundConnections = {} self.listeningSockets = {} @@ -205,17 +211,17 @@ class BMConnectionPool(object): def startBootstrappers(self): """Run the process of resolving bootstrap hostnames""" + onion_seed = 'quzwelsuziwqgpt2.onion' # FIXME onion bootstrap server is down proxy_type = BMConfigParser().safeGet( 'bitmessagesettings', 'socksproxytype') # A plugins may be added here hostname = None + port = 8444 + if not proxy_type or proxy_type == 'none': connection_base = TCPConnection elif proxy_type == 'SOCKS5': connection_base = Socks5BMConnection - hostname = helper_random.randomchoice([ - 'quzwelsuziwqgpt2.onion', None - ]) elif proxy_type == 'SOCKS4a': connection_base = Socks4aBMConnection # FIXME: I cannot test else: @@ -223,12 +229,21 @@ class BMConnectionPool(object): # is handled in bitmessagemain before starting the connectionpool return - bootstrapper = bootstrap(connection_base) - if not hostname: + if self.trustedPeer is not None: + hostname = self.trustedPeer.host + port = self.trustedPeer.port + elif proxy_type == "SOCKS5" or self.onionOnly: + if self.onionOnly: + hostname = onion_seed + else: + hostname = helper_random.randomchoice([ + onion_seed, None]) + + if hostname is None: port = helper_random.randomchoice([8080, 8444]) hostname = 'bootstrap%s.bitmessage.org' % port - else: - port = 8444 + + bootstrapper = bootstrap(connection_base) self.addConnection(bootstrapper(hostname, port)) def loop(self): # pylint: disable=too-many-branches,too-many-statements -- 2.47.2