From 331b26dfe94b6a07462a6eeb16c2540fbaf4622f Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Tue, 19 Dec 2023 03:08:04 +0200 Subject: [PATCH 1/4] Don't connect to nodes with the same nonce --- minode/connection.py | 6 ++++++ minode/manager.py | 4 ++++ minode/shared.py | 1 + 3 files changed, 11 insertions(+) diff --git a/minode/connection.py b/minode/connection.py index b7f9a75..169568d 100644 --- a/minode/connection.py +++ b/minode/connection.py @@ -380,10 +380,16 @@ class ConnectionBase(threading.Thread): if ( version.protocol_version != shared.protocol_version or version.nonce == shared.nonce + or version.nonce in shared.nonce_pool.values() ): + logging.warning( + 'Disconnecting v%s node %s with nonce %s', + version.protocol_version, self.host_print, + base64.b16encode(version.nonce)) self.status = 'disconnecting' self.send_queue.put(None) else: + shared.nonce_pool[self.host] = version.nonce logging.info( '%s:%s claims to be %s', self.host_print, self.port, version.user_agent) diff --git a/minode/manager.py b/minode/manager.py index a03f9d6..f40d49d 100644 --- a/minode/manager.py +++ b/minode/manager.py @@ -76,6 +76,10 @@ class Manager(threading.Thread): if not c.is_alive() or c.status == 'disconnected': with shared.connections_lock: shared.connections.remove(c) + try: + del shared.nonce_pool[c.host] + except KeyError: + pass else: hosts.add(structure.NetAddrNoPrefix.network_group(c.host)) if not c.server: diff --git a/minode/shared.py b/minode/shared.py index 72864ec..d5ac8f4 100644 --- a/minode/shared.py +++ b/minode/shared.py @@ -54,6 +54,7 @@ core_nodes = set() node_pool = set() unchecked_node_pool = set() +nonce_pool = {} i2p_core_nodes = set() i2p_node_pool = set() -- 2.45.1 From afd259d03114652f28605ec70a511be243c04f04 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Wed, 24 Jan 2024 00:03:39 +0200 Subject: [PATCH 2/4] Log also nonce when processing the version message --- minode/connection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/minode/connection.py b/minode/connection.py index 169568d..c32da05 100644 --- a/minode/connection.py +++ b/minode/connection.py @@ -391,8 +391,9 @@ class ConnectionBase(threading.Thread): else: shared.nonce_pool[self.host] = version.nonce logging.info( - '%s:%s claims to be %s', - self.host_print, self.port, version.user_agent) + '%s:%s claims to be %s (%s)', + self.host_print, self.port, version.user_agent, + base64.b16encode(version.nonce)) self.send_queue.put(message.Message(b'verack', b'')) self.verack_sent = True self.remote_version = version -- 2.45.1 From 77125b9d5985590cc39fa3e993beaeb5608c4bf9 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Wed, 24 Jan 2024 00:20:41 +0200 Subject: [PATCH 3/4] Generate new nonce for the I2P connections and improve nonce handling: - make tuple (host, port) a key for shared.nonce_pool to differentiate incoming tor connections, - reserve 127.0.0.1, 8448 for self, - convert nonce to string for logging. --- minode/connection.py | 24 +++++++++++++++++------- minode/manager.py | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/minode/connection.py b/minode/connection.py index c32da05..42a1db4 100644 --- a/minode/connection.py +++ b/minode/connection.py @@ -4,6 +4,7 @@ import base64 import errno import logging import math +import os import random import select import socket @@ -80,7 +81,8 @@ class ConnectionBase(threading.Thread): if self.network == 'ip': self.send_queue.put(message.Version(self.host, self.port)) else: - self.send_queue.put(message.Version('127.0.0.1', 7656)) + self.send_queue.put(message.Version( + '127.0.0.1', 7656, nonce=self._get_nonce())) while True: if ( self.on_connection_fully_established_scheduled @@ -149,6 +151,14 @@ class ConnectionBase(threading.Thread): break time.sleep(0.2) + def _get_nonce(self): + nonce = shared.nonce_pool.get(('127.0.0.1', 8448)) + if nonce is None: + nonce = os.urandom(8) + shared.nonce_pool[('127.0.0.1', 8448)] = nonce + + return nonce + def _connect(self): peer_str = '{0.host_print}:{0.port}'.format(self) logging.debug('Connecting to %s', peer_str) @@ -377,6 +387,7 @@ class ConnectionBase(threading.Thread): if shared.stream not in version.streams: raise ValueError('message not for stream %i' % shared.stream) logging.debug('%s:%s -> %s', self.host_print, self.port, version) + nonce_print = base64.b16encode(version.nonce).decode() if ( version.protocol_version != shared.protocol_version or version.nonce == shared.nonce @@ -384,16 +395,14 @@ class ConnectionBase(threading.Thread): ): logging.warning( 'Disconnecting v%s node %s with nonce %s', - version.protocol_version, self.host_print, - base64.b16encode(version.nonce)) + version.protocol_version, self.host_print, nonce_print) self.status = 'disconnecting' self.send_queue.put(None) else: - shared.nonce_pool[self.host] = version.nonce + shared.nonce_pool[(self.host, self.port)] = version.nonce logging.info( '%s:%s claims to be %s (%s)', - self.host_print, self.port, version.user_agent, - base64.b16encode(version.nonce)) + self.host_print, self.port, version.user_agent, nonce_print) self.send_queue.put(message.Message(b'verack', b'')) self.verack_sent = True self.remote_version = version @@ -412,7 +421,8 @@ class ConnectionBase(threading.Thread): if self.network == 'ip': self.send_queue.put(message.Version(self.host, self.port)) else: - self.send_queue.put(message.Version('127.0.0.1', 7656)) + self.send_queue.put(message.Version( + '127.0.0.1', 7656, nonce=self._get_nonce())) def _process_msg_addr(self, m): addr = message.Addr.from_message(m) diff --git a/minode/manager.py b/minode/manager.py index f40d49d..d1cbf2d 100644 --- a/minode/manager.py +++ b/minode/manager.py @@ -77,7 +77,7 @@ class Manager(threading.Thread): with shared.connections_lock: shared.connections.remove(c) try: - del shared.nonce_pool[c.host] + del shared.nonce_pool[(c.host, c.port)] except KeyError: pass else: -- 2.45.1 From 958f202cef1a104b5f5d791f56f1eabec46ced16 Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Sat, 7 Sep 2024 19:10:37 +0300 Subject: [PATCH 4/4] Discard disconnected node from unchecked_node_pool --- minode/connection.py | 1 + 1 file changed, 1 insertion(+) diff --git a/minode/connection.py b/minode/connection.py index 42a1db4..34455dd 100644 --- a/minode/connection.py +++ b/minode/connection.py @@ -396,6 +396,7 @@ class ConnectionBase(threading.Thread): logging.warning( 'Disconnecting v%s node %s with nonce %s', version.protocol_version, self.host_print, nonce_print) + shared.unchecked_node_pool.discard((self.host, self.port)) self.status = 'disconnecting' self.send_queue.put(None) else: -- 2.45.1