diff --git a/src/advertiser.py b/src/advertiser.py index 2a1be76..97aa0c4 100644 --- a/src/advertiser.py +++ b/src/advertiser.py @@ -22,7 +22,7 @@ class Advertiser(threading.Thread): vectors_to_advertise.add(shared.vector_advertise_queue.get()) if len(vectors_to_advertise) > 0: for c in shared.connections.copy(): - if c.status == 'verack_received': + if c.status == 'fully_established': c.send_queue.put(message.Inv(vectors_to_advertise)) @staticmethod @@ -32,5 +32,5 @@ class Advertiser(threading.Thread): addresses_to_advertise.add(shared.address_advertise_queue.get()) if len(addresses_to_advertise) > 0: for c in shared.connections.copy(): - if c.status == 'verack_received': + if c.status == 'fully_established': c.send_queue.put(message.Addr(addresses_to_advertise)) diff --git a/src/connection.py b/src/connection.py index 8802cc9..3bde616 100644 --- a/src/connection.py +++ b/src/connection.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- import logging +import os import random +import select import socket +import ssl import threading import queue import time @@ -53,17 +56,19 @@ class Connection(threading.Thread): while True: data = True try: - data = self.s.recv(1014) + data = self.s.recv(1024) self.buffer += data - except socket.timeout: + except socket.timeout or ssl.SSLError: if time.time() - self.last_message_received > shared.timeout: + logging.debug('Disconnecting from {};{}. Reason: time.time() - self.last_message_received > shared.timeout'.format(self.host, self.port)) data = None - if time.time() - self.last_message_received > 20 and self.status != 'verack_received': + if time.time() - self.last_message_received > 30 and self.status != 'fully_established': + logging.debug('Disconnecting from {};{}. Reason: time.time() - self.last_message_received > 30 and self.status != \'verack_received\''.format(self.host, self.port)) data = None - if time.time() - self.last_message_sent > 300 and self.status == 'verack_received': + if time.time() - self.last_message_sent > 300 and self.status == 'fully_established': self.send_queue.put(message.Message(b'pong', b'')) if not self.sent_big_inv_message and self.status == 'verack_received' and self.sent_verack: - self._send_big_inv() + self._on_connection_fully_established() except ConnectionResetError: data = None self._process_buffer() @@ -95,12 +100,39 @@ class Connection(threading.Thread): logging.debug('{}:{} <- {}'.format(self.host, self.port, structure.Object.from_message(m))) else: logging.debug('{}:{} <- {}'.format(self.host, self.port, m)) + self.s.settimeout(60) self.s.sendall(m.to_bytes()) + self.s.settimeout(0.5) - def _send_big_inv(self): + def _on_connection_fully_established(self): + if self.remote_version.services & 2: # NODE_SSL + self.s.settimeout(30) + logging.debug('Initializing TLS connection with {}:{}'.format(self.host, self.port)) + self.s = ssl.wrap_socket(self.s, keyfile=os.path.join(shared.source_directory, 'tls', 'key.pem'), + certfile=os.path.join(shared.source_directory, 'tls', 'cert.pem'), + server_side=self.server, ssl_version=ssl.PROTOCOL_TLSv1, do_handshake_on_connect=False, + ciphers='AECDH-AES256-SHA') + if hasattr(self.s, "context"): + self.s.context.set_ecdh_curve("secp256k1") + while True: + try: + self.s.do_handshake() + break + except ssl.SSLError as e: + if e.errno == 2: + select.select([self.s], [self.s], []) + else: + break + except Exception as e: + print(e) + break + self.s.settimeout(0.5) + logging.debug('Established TLS connection with {}:{}'.format(self.host, self.port)) + self.status = 'fully_established' + time.sleep(2) with shared.objects_lock: self.send_queue.put(message.Inv({vector for vector in shared.objects.keys() if shared.objects[vector].expires_time > time.time()})) - addr = {structure.NetAddr(1, c.host, c.port) for c in shared.connections.copy() if not c.server and c.status == 'verack_received'} + addr = {structure.NetAddr(1, c.host, c.port) for c in shared.connections.copy() if not c.server and c.status == 'fully_established'} if len(addr) != 0: self.send_queue.put(message.Addr(addr)) self.sent_big_inv_message = True diff --git a/src/main.py b/src/main.py index b5e39ff..2d12c15 100644 --- a/src/main.py +++ b/src/main.py @@ -34,7 +34,7 @@ def main(): logging.warning('Error while loading nodes from disk.') logging.warning(e) - with open(os.path.dirname(os.path.realpath(__file__)) + '/core_nodes.csv', mode='r', newline='') as f: + with open(os.path.join(shared.source_directory, 'core_nodes.csv'), mode='r', newline='') as f: reader = csv.reader(f) shared.core_nodes = {tuple(row) for row in reader} shared.node_pool.update(shared.core_nodes) diff --git a/src/shared.py b/src/shared.py index cd681d1..4f32e6a 100644 --- a/src/shared.py +++ b/src/shared.py @@ -7,15 +7,16 @@ import threading listening_port = 8444 send_outgoing_connections = True data_directory = 'minode_data/' +source_directory = os.path.dirname(os.path.realpath(__file__)) log_level = logging.DEBUG magic_bytes = b'\xe9\xbe\xb4\xd9' protocol_version = 3 -services = 1 # NODE_NETWORK +services = 3 # NODE_NETWORK, NODE_SSL stream = 1 nonce = os.urandom(8) -user_agent = b'MiNode-v0.0.1' +user_agent = b'MiNode-v0.1.0' timeout = 600 header_length = 24 diff --git a/src/tls/cert.pem b/src/tls/cert.pem new file mode 100644 index 0000000..4dc1bdf --- /dev/null +++ b/src/tls/cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWDCCAcGgAwIBAgIJAJs5yni/cDh5MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTEzMDk1NTU3WhcNMTUxMTE0MDk1NTU3WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCg8XkFpIAYsTSBealTubvu4dzpMnnAOwANG5K9TJeclG9O65cmKWpH8k3hNDif +xagIAI8UanBsQo6SQrK1Iby2kz6DCKmySO1OwoNOOF0Ok31N+5aWsQvYF1wLbk2m +Ti/CSLWBgL25ywCCiP3Mgr+krapT4TrfvF4gCchUdcxMQQIDAQABo1AwTjAdBgNV +HQ4EFgQUWuFUJQC6zu6OTDgHZzhfZxsgJOMwHwYDVR0jBBgwFoAUWuFUJQC6zu6O +TDgHZzhfZxsgJOMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAT1I/x +GbsYAE4pM4sVQrcuz7jLwr3k5Zve0z4WKR41W17Nc44G3DyLbkTWYESLfAYsivkx +tRRtYTtJm1qmTPtedXQJK+wJGNHCWRfwSB2CYwmO7+C2rYYzkFndN68kB6RJmyOr +eCX+9vkbQqgh7KfiNquJxCfMSDfhA2RszU43jg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/src/tls/key.pem b/src/tls/key.pem new file mode 100644 index 0000000..ee5caad --- /dev/null +++ b/src/tls/key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKDxeQWkgBixNIF5 +qVO5u+7h3OkyecA7AA0bkr1Ml5yUb07rlyYpakfyTeE0OJ/FqAgAjxRqcGxCjpJC +srUhvLaTPoMIqbJI7U7Cg044XQ6TfU37lpaxC9gXXAtuTaZOL8JItYGAvbnLAIKI +/cyCv6StqlPhOt+8XiAJyFR1zExBAgMBAAECgYEAmd2hpQpayMCJgQsOHhRgnoXi +jDOMgIInj2CADmguPi0OqTXEoGBR0ozNdfNV+zGdbmESaSNFbcrHwP7xGQgzABlv +5ANLgBYrHnW/oFCCuw4Lj/CAAHRA4its+2wzf13BYoVitDiYBt3JMRqwLV03aHyy +Oqhvt2nVicz85+HERj0CQQDMJAPUIyOQLO+BPC5MsuxyQFJgie0aB5swumxanOv4 +J8GIvulNEJMG/dq+h/x4paV2LGDlUAOsBUmjXfTPMQAHAkEAydQtYorqYqhFZWWD +3lUMAoa8pGb6BfNXUqxdH0H8fk6B7OxYPpvwm7ce1lD1Oje3/+rMnn8i6A1p9HUy +l9wvdwJAdhxIUs7Z3qsBD8bgCuRixV/NyalDk5HfCnxyAKNWK8fkw9ehaEM0rhDm +JOLNAojkiND4ZvS6iyasCmdsIwx4tQJAAV+eR3NmkPFQN5ZvRU4S3NmJ4xyISw4S +5A8kOxg53aovHCunlhV9l7GxVggLAzBp4iX46oM2+5lLxUwe4gWvlQJBAK0IR8bB +85bKZ+M/O8rbs9kQHjx6GCbbDxH+qbIKkNcvLUvMgwwIFKiwqX+Tedtu2xET0mQM +9tEE5eMBOJ8GrxQ= +-----END PRIVATE KEY----- \ No newline at end of file