From f242d409fdad02cd72d939762f3d4d82c5f28cfc Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Fri, 10 Jun 2016 10:44:42 +0200 Subject: [PATCH] Tor hidden service fixes - will send the correct combination of hostname and port - if proxyhostname is a hostname and an IP address, it will now allow multiple parallel connections for hidden service --- src/class_receiveDataThread.py | 5 +++-- src/class_singleListener.py | 3 +-- src/shared.py | 22 ++++++++++++++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/class_receiveDataThread.py b/src/class_receiveDataThread.py index 6ac89f66..9ee1d176 100644 --- a/src/class_receiveDataThread.py +++ b/src/class_receiveDataThread.py @@ -605,14 +605,15 @@ class receiveDataThread(threading.Thread): sentOwn = False for i in range(500): # if current connection is over a proxy, sent our own onion address at a random position - if ownPosition == i and ".onion" in shared.config.get("bitmessagesettings", "onionhostname") and self.sock.getproxytype() != 0 and not sentOwn: + if ownPosition == i and ".onion" in shared.config.get("bitmessagesettings", "onionhostname") and \ + hasattr(self.sock, "getproxytype") and self.sock.getproxytype() != "none" and not sentOwn: peer = shared.Peer(shared.config.get("bitmessagesettings", "onionhostname"), shared.config.getint("bitmessagesettings", "onionport")) else: # still may contain own onion address, but we don't change it peer, = random.sample(shared.knownNodes[self.streamNumber], 1) if isHostInPrivateIPRange(peer.host): continue - if shared.config.get("bitmessagesettings", "onionhostname") == peer.host: + if peer.host == shared.config.get("bitmessagesettings", "onionhostname") and peer.port == shared.config.getint("bitmessagesettings", "onionport") : sentOwn = True addrsInMyStream[peer] = shared.knownNodes[ self.streamNumber][peer] diff --git a/src/class_singleListener.py b/src/class_singleListener.py index 0ae079f6..68cc374b 100644 --- a/src/class_singleListener.py +++ b/src/class_singleListener.py @@ -123,8 +123,7 @@ class singleListener(threading.Thread, StoppableThread): # share the same external IP. This is here to prevent # connection flooding. # permit repeated connections from Tor - # FIXME: sockshostname may be a hostname rather than IP, in such a case this will break - if HOST in shared.connectedHostsList and (".onion" not in shared.config.get('bitmessagesettings', 'onionhostname') or HOST != shared.config.get('bitmessagesettings', 'sockshostname')): + if HOST in shared.connectedHostsList and (".onion" not in shared.config.get('bitmessagesettings', 'onionhostname') or shared.checkSocksIP(HOST)): socketObject.close() logger.info('We are already connected to ' + str(HOST) + '. Ignoring connection.') else: diff --git a/src/shared.py b/src/shared.py index 9388ebdd..2665c4de 100644 --- a/src/shared.py +++ b/src/shared.py @@ -123,6 +123,9 @@ trustedPeer = None # For UPnP extPort = None +# for Tor hidden service +socksIP = None + #Compiled struct for packing/unpacking headers #New code should use CreatePacket instead of Header.pack Header = Struct('!L12sL4s') @@ -243,6 +246,14 @@ def haveSSL(server = False): elif sys.version_info >= (2,7,9): return True return False + +def checkSocksIP(host): + try: + if socksIP is None or not socksIP: + socksIP = socket.gethostbyname(config.get("bitmessagesettings", "sockshostname")) + except NameError: + socksIP = socket.gethostbyname(config.get("bitmessagesettings", "sockshostname")) + return socksIP == host def assembleVersionMessage(remoteHost, remotePort, myStreamNumber, server = False): payload = '' @@ -258,9 +269,16 @@ def assembleVersionMessage(remoteHost, remotePort, myStreamNumber, server = Fals payload += pack('>q', 1) # bitflags of the services I offer. payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( '>L', 2130706433) # = 127.0.0.1. This will be ignored by the remote host. The actual remote connected IP will be used. - if safeConfigGetBoolean('bitmessagesettings', 'upnp') and extPort: + # we have a separate extPort and + # incoming over clearnet or + # outgoing through clearnet + if safeConfigGetBoolean('bitmessagesettings', 'upnp') and extPort \ + and ((server and not checkSocksIP(remoteHost)) or \ + (config.get("bitmessagesettings", "socksproxytype") == "none" and not server)): payload += pack('>H', extPort) - else: + elif checkSocksIP(remoteHost) and server: # incoming connection over Tor + payload += pack('>H', shared.config.getint('bitmessagesettings', 'onionport')) + else: # no extPort and not incoming over Tor payload += pack('>H', shared.config.getint('bitmessagesettings', 'port')) random.seed()