Exemple #1
0
    async def on_add_peer(self, features, source_addr):
        '''Add a peer (but only if the peer resolves to the source).'''
        if self.env.peer_discovery != self.env.PD_ON:
            return False
        if not source_addr:
            self.logger.info('ignored add_peer request: no source info')
            return False
        source = str(source_addr.host)
        peers = Peer.peers_from_features(features, source)
        if not peers:
            self.logger.info('ignored add_peer request: no peers given')
            return False

        # Just look at the first peer, require it
        peer = peers[0]
        host = peer.host
        now = time.time()

        # Rate limit peer adds by domain to one every 10 minutes
        if peer.ip_address is not None:
            bucket = 'ip_addr'
        else:
            bucket = '.'.join(host.lower().split('.')[-2:])
        last = self.recent_peer_adds.get(bucket, 0)
        self.recent_peer_adds[bucket] = now
        if last + PEER_ADD_PAUSE >= now:
            return False

        if peer.is_tor:
            permit = self._permit_new_onion_peer(now)
            reason = 'rate limiting'
        else:
            getaddrinfo = asyncio.get_event_loop().getaddrinfo
            try:
                infos = await getaddrinfo(host, 80, type=socket.SOCK_STREAM)
            except socket.gaierror:
                permit = False
                reason = 'address resolution failure'
            else:
                permit = any(source == info[-1][0] for info in infos)
                reason = 'source-destination mismatch'

        if permit:
            self.logger.info(
                f'accepted add_peer request from {source} for {host}')
            await self._note_peers([peer], check_ports=True)
        else:
            self.logger.warning(f'rejected add_peer request from {source} '
                                f'for {host} ({reason})')

        return permit
Exemple #2
0
    async def on_add_peer(self, features, source_info):
        '''Add a peer (but only if the peer resolves to the source).'''
        if not source_info:
            self.logger.info('ignored add_peer request: no source info')
            return False
        source = source_info[0]
        peers = Peer.peers_from_features(features, source)
        if not peers:
            self.logger.info('ignored add_peer request: no peers given')
            return False

        # Just look at the first peer, require it
        peer = peers[0]
        host = peer.host
        if peer.is_tor:
            permit, reason = self._permit_new_onion_peer()  # check if peer_discovery_tor is enabled and also if sufficient time has passed since we added tor peers (we rate limit tor even if discovery is enabled)
        else:
            getaddrinfo = asyncio.get_event_loop().getaddrinfo
            try:
                infos = await getaddrinfo(host, 80, type=socket.SOCK_STREAM)
            except socket.gaierror:
                permit = False
                reason = 'address resolution failure'
            else:
                permit = any(source == info[-1][0] for info in infos)
                reason = 'source-destination mismatch'
                if permit:
                    permit = not any(ip_address(info[-1][0]) in self.session_mgr.banned_ips for info in infos)
                    reason = 'banned IP'
                if permit:
                    permit = not any(self._dupes_for_peer(info[-1][0]) for info in infos)
                    reason = 'dupe peer'
                if permit:
                    notok = self.session_mgr.does_peer_match_hostname_ban(peer)
                    if notok:
                        permit = False
                        reason = f'banned hostname suffix: {notok}'

        if permit:
            self.logger.info(f'accepted add_peer request from {source} '
                             f'for {host}')
            await self._note_peers([peer], check_ports=True)
        else:
            self.logger.warning(f'rejected add_peer request from {source} '
                                f'for {host} ({reason})')

        return permit
Exemple #3
0
    async def on_add_peer(self, features, source_info):
        '''Add a peer (but only if the peer resolves to the source).'''
        if not source_info:
            self.logger.info('ignored add_peer request: no source info')
            return False
        source = source_info[0]
        peers = Peer.peers_from_features(features, source)
        if not peers:
            self.logger.info('ignored add_peer request: no peers given')
            return False

        # Just look at the first peer, require it
        peer = peers[0]
        host = peer.host
        if peer.is_tor:
            permit = self.permit_new_onion_peer()
            reason = 'rate limiting'
        else:
            try:
                infos = await self.loop.getaddrinfo(host,
                                                    80,
                                                    type=socket.SOCK_STREAM)
            except socket.gaierror:
                permit = False
                reason = 'address resolution failure'
            else:
                permit = any(source == info[-1][0] for info in infos)
                reason = 'source-destination mismatch'

        if permit:
            self.logger.info('accepted add_peer request from {} for {}'.format(
                source, host))
            self.add_peers([peer], check_ports=True)
        else:
            self.logger.warning(
                'rejected add_peer request from {} for {} ({})'.format(
                    source, host, reason))

        return permit