Remove banned peers from DHT and track IPs (#1656)

## Issue Addressed

#629 

## Proposed Changes

This removes banned peers from the DHT and informs discovery to block the node_id and the known source IP's associated with this node. It has the capabilities of un banning this peer after a period of time. 

This also corrects the logic about banning specific IP addresses. We now use seen_ip addresses from libp2p rather than those sent to us via identify (which also include local addresses).
This commit is contained in:
Age Manning
2020-09-25 01:52:39 +00:00
parent 15638d1448
commit 28b6d921c6
6 changed files with 264 additions and 182 deletions

View File

@@ -194,9 +194,9 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
// Update the PeerDB state.
if let Some(peer_id) = ban_peer.take() {
self.network_globals.peers.write().ban(&peer_id);
self.ban_peer(&peer_id);
} else if let Some(peer_id) = unban_peer.take() {
self.network_globals.peers.write().unban(&peer_id);
self.unban_peer(&peer_id);
}
}
@@ -312,19 +312,22 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
/// Sets a peer as connected as long as their reputation allows it
/// Informs if the peer was accepted
pub fn connect_ingoing(&mut self, peer_id: &PeerId) -> bool {
self.connect_peer(peer_id, ConnectingType::IngoingConnected)
pub fn connect_ingoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr) -> bool {
self.connect_peer(peer_id, ConnectingType::IngoingConnected { multiaddr })
}
/// Sets a peer as connected as long as their reputation allows it
/// Informs if the peer was accepted
pub fn connect_outgoing(&mut self, peer_id: &PeerId) -> bool {
self.connect_peer(peer_id, ConnectingType::OutgoingConnected)
pub fn connect_outgoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr) -> bool {
self.connect_peer(peer_id, ConnectingType::OutgoingConnected { multiaddr })
}
/// Updates the database informing that a peer is being disconnected.
pub fn _disconnecting_peer(&mut self, _peer_id: &PeerId) -> bool {
// TODO: implement
// This informs the database that we are in the process of disconnecting the
// peer. Currently this state only exists for a short period of time before we force the
// disconnection.
true
}
@@ -644,8 +647,12 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
peerdb.dialing_peer(peer_id);
return true;
}
ConnectingType::IngoingConnected => peerdb.connect_outgoing(peer_id),
ConnectingType::OutgoingConnected => peerdb.connect_ingoing(peer_id),
ConnectingType::IngoingConnected { multiaddr } => {
peerdb.connect_outgoing(peer_id, multiaddr)
}
ConnectingType::OutgoingConnected { multiaddr } => {
peerdb.connect_ingoing(peer_id, multiaddr)
}
}
}
@@ -683,12 +690,11 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
/// NOTE: This is experimental and will likely be adjusted
fn update_peer_scores(&mut self) {
/* Check how long have peers been in this state and update their reputations if needed */
let mut pdb = self.network_globals.peers.write();
let mut to_ban_peers = Vec::new();
let mut to_unban_peers = Vec::new();
for (peer_id, info) in pdb.peers_mut() {
for (peer_id, info) in self.network_globals.peers.write().peers_mut() {
let previous_state = info.score_state();
// Update scores
info.score_update();
@@ -780,14 +786,51 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
}
// process banning peers
for peer_id in to_ban_peers {
pdb.ban(&peer_id);
self.ban_peer(&peer_id);
}
// process unbanning peers
for peer_id in to_unban_peers {
pdb.unban(&peer_id);
self.unban_peer(&peer_id);
}
}
/// Bans a peer.
///
/// Records updates the peers connection status and updates the peer db as well as blocks the
/// peer from participating in discovery and removes them from the routing table.
fn ban_peer(&mut self, peer_id: &PeerId) {
let mut peer_db = self.network_globals.peers.write();
peer_db.ban(peer_id);
let banned_ip_addresses = peer_db
.peer_info(peer_id)
.map(|info| {
info.seen_addresses
.iter()
.filter(|ip| peer_db.is_ip_banned(ip))
.cloned()
.collect::<Vec<_>>()
})
.unwrap_or_default();
self.discovery.ban_peer(&peer_id, banned_ip_addresses);
}
/// Unbans a peer.
///
/// Records updates the peers connection status and updates the peer db as well as removes
/// previous bans from discovery.
fn unban_peer(&mut self, peer_id: &PeerId) {
let mut peer_db = self.network_globals.peers.write();
peer_db.unban(&peer_id);
let seen_ip_addresses = peer_db
.peer_info(peer_id)
.map(|info| info.seen_addresses.iter().cloned().collect::<Vec<_>>())
.unwrap_or_default();
self.discovery.unban_peer(&peer_id, seen_ip_addresses);
}
/// The Peer manager's heartbeat maintains the peer count and maintains peer reputations.
///
/// It will request discovery queries if the peer count has not reached the desired number of
@@ -894,7 +937,13 @@ enum ConnectingType {
/// We are in the process of dialing this peer.
Dialing,
/// A peer has dialed us.
IngoingConnected,
IngoingConnected {
// The multiaddr the peer connected to us on.
multiaddr: Multiaddr,
},
/// We have successfully dialed a peer.
OutgoingConnected,
OutgoingConnected {
/// The multiaddr we dialed to reach the peer.
multiaddr: Multiaddr,
},
}