From e783206ec7e8b186eb7ebe15768391c24b3e6dc8 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 25 Apr 2024 22:48:56 +0000 Subject: [PATCH] network: re-detect is_proxy_tor every time we connect to a server This avoids some false negatives for is_proxy_tor. (previously we only set is_proxy_tor when the proxy settings were changed) In particular, consider scenario: - Tor browser not running - user sets "localhost:9150" as proxy - detection sets network.is_proxy_tor to False - user starts Tor browser - network, due to retries, finds proxy working and connects to some servers - network.is_proxy_tor remains False --- electrum/network.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/electrum/network.py b/electrum/network.py index ddef1aa8f..6ef23d57a 100644 --- a/electrum/network.py +++ b/electrum/network.py @@ -648,24 +648,27 @@ class Network(Logger, NetworkRetryManager[ServerAddr]): self.logger.info(f'setting proxy {proxy}') self.proxy = proxy + + # reset is_proxy_tor to unknown, and re-detect it: self.is_proxy_tor = None - - def tor_probe_task(p): - assert p is not None - tor_proxy = util.is_tor_socks_port(p['host'], int(p['port'])) - if self.proxy == p: # is this the proxy we probed? - self.logger.info(f'Proxy is {"" if tor_proxy else "not "}TOR') - self._tor_probe_done(tor_proxy) - - if proxy and proxy['mode'] == 'socks5': - t = threading.Thread(target=tor_probe_task, args=(proxy,), daemon=True) - t.start() + self._detect_if_proxy_is_tor() util.trigger_callback('proxy_set', self.proxy) - def _tor_probe_done(self, is_tor: bool): - self.is_proxy_tor = is_tor - util.trigger_callback('tor_probed', is_tor) + def _detect_if_proxy_is_tor(self) -> None: + def tor_probe_task(p): + assert p is not None + is_tor = util.is_tor_socks_port(p['host'], int(p['port'])) + if self.proxy == p: # is this the proxy we probed? + if self.is_proxy_tor != is_tor: + self.logger.info(f'Proxy is {"" if is_tor else "not "}TOR') + self.is_proxy_tor = is_tor + util.trigger_callback('tor_probed', is_tor) + + proxy = self.proxy + if proxy and proxy['mode'] == 'socks5': + t = threading.Thread(target=tor_probe_task, args=(proxy,), daemon=True) + t.start() @log_exceptions async def set_parameters(self, net_params: NetworkParameters): @@ -904,6 +907,9 @@ class Network(Logger, NetworkRetryManager[ServerAddr]): self._has_ever_managed_to_connect_to_server = True self._add_recent_server(server) util.trigger_callback('network_updated') + # When the proxy settings were set, the proxy (if any) might have been unreachable, + # resulting in a false-negative for Tor-detection. Given we just connected to a server, re-test now. + self._detect_if_proxy_is_tor() def check_interface_against_healthy_spread_of_connected_servers(self, iface_to_check: Interface) -> bool: # main interface is exempt. this makes switching servers easier