Enforce a timeout on peer disconnect (#3757)

On heavily crowded networks, we are seeing many attempted connections to our node every second. 

Often these connections come from peers that have just been disconnected. This can be for a number of reasons including: 
- We have deemed them to be not as useful as other peers
- They have performed poorly
- They have dropped the connection with us
- The connection was spontaneously lost
- They were randomly removed because we have too many peers

In all of these cases, if we have reached or exceeded our target peer limit, there is no desire to accept new connections immediately after the disconnect from these peers. In fact, it often costs us resources to handle the established connections and defeats some of the logic of dropping them in the first place. 

This PR adds a timeout, that prevents recently disconnected peers from reconnecting to us.

Technically we implement a ban at the swarm layer to prevent immediate re connections for at least 10 minutes. I decided to keep this light, and use a time-based LRUCache which only gets updated during the peer manager heartbeat to prevent added stress of polling a delay map for what could be a large number of peers.

This cache is bounded in time. An extra space bound could be added should people consider this a risk.

Co-authored-by: Diva M <divma@protonmail.com>
This commit is contained in:
Age Manning
2023-02-14 03:25:42 +00:00
parent fa1d4c7054
commit 8dd9249177
6 changed files with 154 additions and 29 deletions

View File

@@ -844,8 +844,12 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
.collect::<Vec<_>>();
return Some(BanOperation::ReadyToBan(banned_ips));
}
PeerConnectionStatus::Disconnecting { .. }
| PeerConnectionStatus::Unknown
PeerConnectionStatus::Disconnecting { .. } => {
// The peer has been disconnected but not banned. Inform the peer manager
// that this peer could be eligible for a temporary ban.
return Some(BanOperation::TemporaryBan);
}
PeerConnectionStatus::Unknown
| PeerConnectionStatus::Connected { .. }
| PeerConnectionStatus::Dialing { .. } => {
self.disconnected_peers += 1;
@@ -1177,6 +1181,9 @@ impl From<Option<BanOperation>> for ScoreUpdateResult {
/// When attempting to ban a peer provides the peer manager with the operation that must be taken.
pub enum BanOperation {
/// Optionally temporarily ban this peer to prevent instantaneous reconnection.
/// The peer manager will decide if temporary banning is required.
TemporaryBan,
// The peer is currently connected. Perform a graceful disconnect before banning at the swarm
// level.
DisconnectThePeer,