def __init__(self, host=None, sock=None, announcing=False): # pylint: disable=bad-super-call super(BMProto, self).__init__(sock=sock) self.verackReceived = True self.verackSent = True # .. todo:: sort out streams self.streams = [1] self.fullyEstablished = True self.connectedAt = 0 self.skipUntil = 0 if sock is None: if host is None: host = '' self.create_socket( socket.AF_INET6 if ":" in host else socket.AF_INET, socket.SOCK_DGRAM) self.set_socket_reuse() logger.info("Binding UDP socket to %s:%i", host, self.port) self.socket.bind((host, self.port)) else: self.socket = sock self.set_socket_reuse() self.listening = Peer(*self.socket.getsockname()) self.destination = Peer(*self.socket.getsockname()) ObjectTracker.__init__(self) self.connecting = False self.connected = True self.announcing = announcing self.set_state("bm_header", expectBytes=protocol.Header.size)
def bm_command_addr(self): addresses = self._decode_addr() # only allow peer discovery from private IPs in order to avoid # attacks from random IPs on the internet if not self.local: return True remoteport = False for seenTime, stream, _, ip, port in addresses: decodedIP = protocol.checkIPAddress(str(ip)) if stream not in state.streamsInWhichIAmParticipating: continue if (seenTime < time.time() - self.maxTimeOffset or seenTime > time.time() + self.maxTimeOffset): continue if decodedIP is False: # if the address isn't local, interpret it as # the host's own announcement remoteport = port if remoteport is False: return True logger.debug("received peer discovery from %s:%i (port %i):", self.destination.host, self.destination.port, remoteport) if self.local: state.discoveredPeers[Peer(self.destination.host, remoteport)] = \ time.time() return True
def handle_accept(self): """Incoming connection callback""" try: sock = self.accept()[0] except (TypeError, IndexError): return state.ownAddresses[Peer(*sock.getsockname())] = True if ( len(connectionpool.BMConnectionPool()) > BMConfigParser().safeGetInt( 'bitmessagesettings', 'maxtotalconnections') + BMConfigParser().safeGetInt( 'bitmessagesettings', 'maxbootstrapconnections') + 10 ): # 10 is a sort of buffer, in between it will go through # the version handshake and return an error to the peer logger.warning("Server full, dropping connection") sock.close() return try: connectionpool.BMConnectionPool().addConnection( TCPConnection(sock=sock)) except socket.error: pass
def announceSelf(): """Announce our presence""" for connection in BMConnectionPool().udpSockets.values(): if not connection.announcing: continue for stream in state.streamsInWhichIAmParticipating: addr = ( stream, Peer( '127.0.0.1', BMConfigParser().safeGetInt( 'bitmessagesettings', 'port')), time.time()) connection.append_write_buf(assemble_addr([addr]))
def handle_read(self): try: (recdata, addr) = self.socket.recvfrom(self._buf_len) except socket.error as e: logger.error("socket error: %s", e) return self.destination = Peer(*addr) encodedAddr = protocol.encodeHost(addr[0]) self.local = bool(protocol.checkIPAddress(encodedAddr, True)) # overwrite the old buffer to avoid mixing data and so that # self.local works correctly self.read_buf[0:] = recdata self.bm_proto_reset() receiveDataQueue.put(self.listening)
def __init__(self, address=None, sock=None): BMProto.__init__(self, address=address, sock=sock) self.verackReceived = False self.verackSent = False self.streams = [0] self.fullyEstablished = False self.connectedAt = 0 self.skipUntil = 0 if address is None and sock is not None: self.destination = Peer(*sock.getpeername()) self.isOutbound = False TLSDispatcher.__init__(self, sock, server_side=True) self.connectedAt = time.time() logger.debug( 'Received connection from %s:%i', self.destination.host, self.destination.port) self.nodeid = randomBytes(8) elif address is not None and sock is not None: TLSDispatcher.__init__(self, sock, server_side=False) self.isOutbound = True logger.debug( 'Outbound proxy connection to %s:%i', self.destination.host, self.destination.port) else: self.destination = address self.isOutbound = True self.create_socket( socket.AF_INET6 if ":" in address.host else socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) TLSDispatcher.__init__(self, sock, server_side=False) self.connect(self.destination) logger.debug( 'Connecting to %s:%i', self.destination.host, self.destination.port) try: self.local = ( protocol.checkIPAddress( protocol.encodeHost(self.destination.host), True) and not protocol.checkSocksIP(self.destination.host) ) except socket.error: # it's probably a hostname pass self.network_group = protocol.network_group(self.destination.host) ObjectTracker.__init__(self) # pylint: disable=non-parent-init-called self.bm_proto_reset() self.set_state("bm_header", expectBytes=protocol.Header.size)
def removeConnection(self, connection): """Remove a connection from our internal dict""" if isinstance(connection, UDPSocket): del self.udpSockets[connection.listening.host] elif isinstance(connection, TCPServer): del self.listeningSockets[Peer(connection.destination.host, connection.destination.port)] elif connection.isOutbound: try: del self.outboundConnections[connection.destination] except KeyError: pass else: try: del self.inboundConnections[connection.destination] except KeyError: try: del self.inboundConnections[connection.destination.host] except KeyError: pass connection.handle_close()
def bm_command_addr(self): """Incoming addresses, process them""" # pylint: disable=redefined-outer-name addresses = self._decode_addr() for seenTime, stream, _, ip, port in addresses: decodedIP = protocol.checkIPAddress(str(ip)) if stream not in state.streamsInWhichIAmParticipating: continue if (decodedIP and time.time() - seenTime > 0 and seenTime > time.time() - ADDRESS_ALIVE and port > 0): peer = Peer(decodedIP, port) with knownnodes.knownNodesLock: # isnew = knownnodes.addKnownNode(stream, peer, seenTime) # since we don't track peers outside of knownnodes, # only spread if in knownnodes to prevent flood # DISABLED TO WORKAROUND FLOOD/LEAK # if isnew: # addrQueue.put(( # stream, peer, seenTime, self.destination)) return True
def __init__(self): asyncore.set_rates( BMConfigParser().safeGetInt("bitmessagesettings", "maxdownloadrate"), BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate")) self.outboundConnections = {} self.inboundConnections = {} self.listeningSockets = {} self.udpSockets = {} self.streams = [] self._lastSpawned = 0 self._spawnWait = 2 self._bootstrapped = False trustedPeer = BMConfigParser().safeGet('bitmessagesettings', 'trustedpeer') try: if trustedPeer: host, port = trustedPeer.split(':') self.trustedPeer = Peer(host, int(port)) except ValueError: sys.exit('Bad trustedpeer config setting! It should be set as' ' trustedpeer=<hostname>:<portnumber>')
def __init__(self, host='127.0.0.1', port=8444): if not hasattr(self, '_map'): AdvancedDispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() for attempt in range(50): try: if attempt > 0: logger.warning('Failed to bind on port %s', port) port = random.randint(32767, 65535) self.bind((host, port)) except socket.error as e: if e.errno in (asyncore.EADDRINUSE, asyncore.WSAEADDRINUSE): continue else: if attempt > 0: logger.warning('Setting port to %s', port) BMConfigParser().set( 'bitmessagesettings', 'port', str(port)) BMConfigParser().save() break self.destination = Peer(host, port) self.bound = True self.listen(5)
def __init__(self, host, port): self._connection_base.__init__(self, Peer(host, port)) self.close_reason = self._succeed = False
def __init__(self): super(BMStringParser, self).__init__() self.destination = Peer('127.0.0.1', 8444) self.payload = None ObjectTracker.__init__(self)
def peerValidityChecks(self): """Check the validity of the peer""" if self.remoteProtocolVersion < 3: self.append_write_buf( protocol.assembleErrorMessage( errorText= "Your is using an old protocol. Closing connection.", fatal=2)) logger.debug( 'Closing connection to old protocol version %s, node: %s', self.remoteProtocolVersion, self.destination) return False if self.timeOffset > MAX_TIME_OFFSET: self.append_write_buf( protocol.assembleErrorMessage( errorText="Your time is too far in the future" " compared to mine. Closing connection.", fatal=2)) logger.info( "%s's time is too far in the future (%s seconds)." " Closing connection to it.", self.destination, self.timeOffset) BMProto.timeOffsetWrongCount += 1 return False elif self.timeOffset < -MAX_TIME_OFFSET: self.append_write_buf( protocol.assembleErrorMessage( errorText= "Your time is too far in the past compared to mine." " Closing connection.", fatal=2)) logger.info( "%s's time is too far in the past (timeOffset %s seconds)." " Closing connection to it.", self.destination, self.timeOffset) BMProto.timeOffsetWrongCount += 1 return False else: BMProto.timeOffsetWrongCount = 0 if not self.streams: self.append_write_buf( protocol.assembleErrorMessage( errorText="We don't have shared stream interests." " Closing connection.", fatal=2)) logger.debug( 'Closed connection to %s because there is no overlapping' ' interest in streams.', self.destination) return False if self.destination in connectionpool.BMConnectionPool( ).inboundConnections: try: if not protocol.checkSocksIP(self.destination.host): self.append_write_buf( protocol.assembleErrorMessage( errorText="Too many connections from your IP." " Closing connection.", fatal=2)) logger.debug( 'Closed connection to %s because we are already' ' connected to that IP.', self.destination) return False except Exception: pass if not self.isOutbound: # incoming from a peer we're connected to as outbound, # or server full report the same error to counter deanonymisation if (Peer(self.destination.host, self.peerNode.port) in connectionpool.BMConnectionPool().inboundConnections or len(connectionpool.BMConnectionPool()) > BMConfigParser().safeGetInt('bitmessagesettings', 'maxtotalconnections') + BMConfigParser().safeGetInt('bitmessagesettings', 'maxbootstrapconnections')): self.append_write_buf( protocol.assembleErrorMessage( errorText="Server full, please try again later.", fatal=2)) logger.debug( 'Closed connection to %s due to server full' ' or duplicate inbound/outbound.', self.destination) return False if connectionpool.BMConnectionPool().isAlreadyConnected(self.nonce): self.append_write_buf( protocol.assembleErrorMessage( errorText="I'm connected to myself. Closing connection.", fatal=2)) logger.debug( "Closed connection to %s because I'm connected to myself.", self.destination) return False return True
def bm_command_portcheck(self): """Incoming port check request, queue it.""" portCheckerQueue.put(Peer(self.destination, self.peerNode.port)) return True