Skip to content

Commit 262c1eb

Browse files
committed
lnpeer: add some rate-limiting against ping flood
A remote peer could send us lots of small ping messages, requesting large pong responses. This is cheap for them but potentially expensive for us. Does not seem too serious, but I think we could add some rate-limiting. note: There are many ways for a remote peer to inflate our incoming traffic usage, but the cost of that is usually shared between them and us (they need to send the data, we receive it).
1 parent fd070a9 commit 262c1eb

1 file changed

Lines changed: 13 additions & 1 deletion

File tree

electrum/lnpeer.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ def __init__(
140140
self._num_gossip_messages_forwarded = 0
141141
self._processed_onion_cache = LRUCache(maxsize=100) # type: LRUCache[bytes, ProcessedOnionPacket]
142142
self._last_commitsig_sent_time = time.monotonic()
143+
self._last_ping_recv_time = min(0, time.monotonic())
143144

144145
def send_message(self, message_name: str, **kwargs):
145146
assert util.get_running_loop() == util.get_asyncio_loop(), f"this must be run on the asyncio thread!"
@@ -372,7 +373,18 @@ def send_error(self, channel_id: bytes, message: str = None, *, force_close_chan
372373
self.schedule_force_closing(cid)
373374
raise GracefulDisconnect
374375

375-
def on_ping(self, payload):
376+
async def on_ping(self, payload):
377+
elapsed_since_last = time.monotonic() - self._last_ping_recv_time
378+
min_delay = 1.0 # seconds
379+
if elapsed_since_last < min_delay:
380+
self.logger.debug("remote sending PINGs too often, sleeping a bit")
381+
# note: This rate-limiting helps limit our outbound traffic usage.
382+
# (max inc msg size 65 KB, max out msg size 65 KB, decoupled)
383+
# Does not really help for inbound traffic-usage:
384+
# there are many other ways for the peer to flood us, e.g. unknown 'odd' message types.
385+
# note: this blocks processing *any* further incoming message from this peer
386+
await asyncio.sleep(min_delay - elapsed_since_last)
387+
self._last_ping_recv_time = time.monotonic()
376388
l = payload['num_pong_bytes']
377389
self.send_message('pong', byteslen=l)
378390

0 commit comments

Comments
 (0)