Be stricter accepting add_peer requests
- rate-limit onion add_peer requests - for clearnet peers only accept if the peer resolves to the source address
This commit is contained in:
parent
84c201f665
commit
7a2f29aabe
@ -49,7 +49,6 @@ class Controller(util.LoggedClass):
|
|||||||
self.executor = ThreadPoolExecutor()
|
self.executor = ThreadPoolExecutor()
|
||||||
self.loop.set_default_executor(self.executor)
|
self.loop.set_default_executor(self.executor)
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
self.next_add_peer_time = self.start_time
|
|
||||||
self.coin = env.coin
|
self.coin = env.coin
|
||||||
self.daemon = Daemon(env.coin.daemon_urls(env.daemon_url))
|
self.daemon = Daemon(env.coin.daemon_urls(env.daemon_url))
|
||||||
self.bp = BlockProcessor(env, self, self.daemon)
|
self.bp = BlockProcessor(env, self, self.daemon)
|
||||||
@ -136,15 +135,6 @@ class Controller(util.LoggedClass):
|
|||||||
def is_deprioritized(self, session):
|
def is_deprioritized(self, session):
|
||||||
return self.session_priority(session) > self.BANDS
|
return self.session_priority(session) > self.BANDS
|
||||||
|
|
||||||
def permit_add_peer(self):
|
|
||||||
'''To prevent lots of add_peer requests filling up the peer
|
|
||||||
table, accept only one per random time interval.'''
|
|
||||||
now = time.time()
|
|
||||||
if now < self.next_add_peer_time:
|
|
||||||
return False
|
|
||||||
self.next_add_peer_time = now + random.randrange(0, 1800)
|
|
||||||
return True
|
|
||||||
|
|
||||||
async def run_in_executor(self, func, *args):
|
async def run_in_executor(self, func, *args):
|
||||||
'''Wait whilst running func in the executor.'''
|
'''Wait whilst running func in the executor.'''
|
||||||
return await self.loop.run_in_executor(None, func, *args)
|
return await self.loop.run_in_executor(None, func, *args)
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import ssl
|
|||||||
import time
|
import time
|
||||||
from collections import defaultdict, Counter
|
from collections import defaultdict, Counter
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from socket import SOCK_STREAM
|
||||||
|
|
||||||
from lib.jsonrpc import JSONSession
|
from lib.jsonrpc import JSONSession
|
||||||
from lib.peer import Peer
|
from lib.peer import Peer
|
||||||
@ -221,6 +222,7 @@ class PeerManager(util.LoggedClass):
|
|||||||
# any other peers with the same host name or IP address.
|
# any other peers with the same host name or IP address.
|
||||||
self.peers = set()
|
self.peers = set()
|
||||||
self.onion_peers = []
|
self.onion_peers = []
|
||||||
|
self.permit_onion_peer_time = time.time()
|
||||||
self.last_tor_retry_time = 0
|
self.last_tor_retry_time = 0
|
||||||
self.tor_proxy = SocksProxy(env.tor_proxy_host, env.tor_proxy_port,
|
self.tor_proxy = SocksProxy(env.tor_proxy_host, env.tor_proxy_port,
|
||||||
loop=self.loop)
|
loop=self.loop)
|
||||||
@ -302,15 +304,43 @@ class PeerManager(util.LoggedClass):
|
|||||||
if retry:
|
if retry:
|
||||||
self.retry_event.set()
|
self.retry_event.set()
|
||||||
|
|
||||||
def on_add_peer(self, features, source):
|
def permit_new_onion_peer(self):
|
||||||
'''Add peers from an incoming connection.'''
|
'''Accept a new onion peer only once per random time interval.'''
|
||||||
|
now = time.time()
|
||||||
|
if now < self.permit_onion_peer_time:
|
||||||
|
return False
|
||||||
|
self.permit_onion_peer_time = now + random.randrange(0, 1200)
|
||||||
|
return True
|
||||||
|
|
||||||
|
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:
|
||||||
|
return False
|
||||||
|
source = source_info[0]
|
||||||
peers = Peer.peers_from_features(features, source)
|
peers = Peer.peers_from_features(features, source)
|
||||||
if peers:
|
if not peers:
|
||||||
hosts = [peer.host for peer in peers]
|
return False
|
||||||
self.log_info('add_peer request from {} for {}'
|
|
||||||
.format(source, ', '.join(hosts)))
|
# Just look at the first peer, require it
|
||||||
self.add_peers(peers, check_ports=True)
|
peer = peers[0]
|
||||||
return bool(peers)
|
host = peer.host
|
||||||
|
if peer.is_tor:
|
||||||
|
permit = self.permit_new_onion_peer()
|
||||||
|
reason = 'rate limiting'
|
||||||
|
else:
|
||||||
|
infos = await self.loop.getaddrinfo(host, 80, type=SOCK_STREAM)
|
||||||
|
permit = any(source == info[-1][0] for info in infos)
|
||||||
|
reason = 'source-destination mismatch'
|
||||||
|
|
||||||
|
if permit:
|
||||||
|
self.log_info('accepted add_peer request from {} for {}'
|
||||||
|
.format(source, host))
|
||||||
|
self.add_peers([peer], check_ports=True)
|
||||||
|
else:
|
||||||
|
self.log_warning('rejected add_peer request from {} for {} ({})'
|
||||||
|
.format(source, host, reason))
|
||||||
|
|
||||||
|
return permit
|
||||||
|
|
||||||
def on_peers_subscribe(self, is_tor):
|
def on_peers_subscribe(self, is_tor):
|
||||||
'''Returns the server peers as a list of (ip, host, details) tuples.
|
'''Returns the server peers as a list of (ip, host, details) tuples.
|
||||||
|
|||||||
@ -193,14 +193,10 @@ class ElectrumX(SessionBase):
|
|||||||
self.subscribe_height = True
|
self.subscribe_height = True
|
||||||
return self.height()
|
return self.height()
|
||||||
|
|
||||||
def add_peer(self, features):
|
async def add_peer(self, features):
|
||||||
'''Add a peer.'''
|
'''Add a peer (but only if the peer resolves to the source).'''
|
||||||
if not self.controller.permit_add_peer():
|
|
||||||
return False
|
|
||||||
peer_mgr = self.controller.peer_mgr
|
peer_mgr = self.controller.peer_mgr
|
||||||
peer_info = self.peer_info()
|
return await peer_mgr.on_add_peer(features, self.peer_info())
|
||||||
source = peer_info[0] if peer_info else 'unknown'
|
|
||||||
return peer_mgr.on_add_peer(features, source)
|
|
||||||
|
|
||||||
def peers_subscribe(self):
|
def peers_subscribe(self):
|
||||||
'''Return the server peers as a list of (ip, host, details) tuples.'''
|
'''Return the server peers as a list of (ip, host, details) tuples.'''
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user