@@ -171,17 +171,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
171
171
) ;
172
172
}
173
173
174
- // Update the peerdb and peer state accordingly
175
- if self
176
- . network_globals
177
- . peers
178
- . write ( )
179
- . disconnect_and_ban ( peer_id)
180
- {
181
- // update the state of the peer.
182
- self . events
183
- . push ( PeerManagerEvent :: DisconnectPeer ( * peer_id, reason) ) ;
184
- }
174
+ // Update the peerdb and start the disconnection.
175
+ self . ban_peer ( peer_id, reason) ;
185
176
}
186
177
187
178
/// Reports a peer for some action.
@@ -333,18 +324,23 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
333
324
}
334
325
}
335
326
336
- // Should not be able to connect to a banned peer. Double check here
337
- if self . is_banned ( & peer_id) {
338
- warn ! ( self . log, "Connected to a banned peer" ; "peer_id" => %peer_id) ;
339
- self . events . push ( PeerManagerEvent :: DisconnectPeer (
340
- peer_id,
341
- GoodbyeReason :: Banned ,
342
- ) ) ;
343
- self . network_globals
344
- . peers
345
- . write ( )
346
- . notify_disconnecting ( peer_id, true ) ;
347
- return ;
327
+ // Check to make sure the peer is not supposed to be banned
328
+ match self . ban_status ( & peer_id) {
329
+ BanResult :: BadScore => {
330
+ // This is a faulty state
331
+ error ! ( self . log, "Connected to a banned peer, re-banning" ; "peer_id" => %peer_id) ;
332
+ // Reban the peer
333
+ self . goodbye_peer ( & peer_id, GoodbyeReason :: Banned , ReportSource :: PeerManager ) ;
334
+ return ;
335
+ }
336
+ BanResult :: BannedIp ( ip_addr) => {
337
+ // A good peer has connected to us via a banned IP address. We ban the peer and
338
+ // prevent future connections.
339
+ debug ! ( self . log, "Peer connected via banned IP. Banning" ; "peer_id" => %peer_id, "banned_ip" => %ip_addr) ;
340
+ self . goodbye_peer ( & peer_id, GoodbyeReason :: BannedIP , ReportSource :: PeerManager ) ;
341
+ return ;
342
+ }
343
+ BanResult :: NotBanned => { }
348
344
}
349
345
350
346
// Check the connection limits
@@ -356,14 +352,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
356
352
. peer_info ( & peer_id)
357
353
. map_or ( true , |peer| !peer. has_future_duty ( ) )
358
354
{
359
- self . events . push ( PeerManagerEvent :: DisconnectPeer (
360
- peer_id,
361
- GoodbyeReason :: TooManyPeers ,
362
- ) ) ;
363
- self . network_globals
364
- . peers
365
- . write ( )
366
- . notify_disconnecting ( peer_id, false ) ;
355
+ // Gracefully disconnect the peer.
356
+ self . disconnect_peer ( peer_id, GoodbyeReason :: TooManyPeers ) ;
367
357
return ;
368
358
}
369
359
@@ -465,8 +455,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
465
455
/// Reports if a peer is banned or not.
466
456
///
467
457
/// This is used to determine if we should accept incoming connections.
468
- pub fn is_banned ( & self , peer_id : & PeerId ) -> bool {
469
- self . network_globals . peers . read ( ) . is_banned ( peer_id)
458
+ pub fn ban_status ( & self , peer_id : & PeerId ) -> BanResult {
459
+ self . network_globals . peers . read ( ) . ban_status ( peer_id)
470
460
}
471
461
472
462
pub fn is_connected ( & self , peer_id : & PeerId ) -> bool {
@@ -707,7 +697,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
707
697
let mut to_unban_peers = Vec :: new ( ) ;
708
698
709
699
{
710
- //collect peers with scores
700
+ // collect peers with scores
711
701
let mut guard = self . network_globals . peers . write ( ) ;
712
702
let mut peers: Vec < _ > = guard
713
703
. peers_mut ( )
@@ -793,10 +783,11 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
793
783
. write ( )
794
784
. inject_disconnect ( peer_id)
795
785
{
796
- self . ban_peer ( peer_id) ;
786
+ // The peer was awaiting a ban, continue to ban the peer.
787
+ self . ban_peer ( peer_id, GoodbyeReason :: BadScore ) ;
797
788
}
798
789
799
- // remove the ping and status timer for the peer
790
+ // Remove the ping and status timer for the peer
800
791
self . inbound_ping_peers . remove ( peer_id) ;
801
792
self . outbound_ping_peers . remove ( peer_id) ;
802
793
self . status_peers . remove ( peer_id) ;
@@ -816,7 +807,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
816
807
) -> bool {
817
808
{
818
809
let mut peerdb = self . network_globals . peers . write ( ) ;
819
- if peerdb. is_banned ( peer_id) {
810
+ if ! matches ! ( peerdb. ban_status ( peer_id) , BanResult :: NotBanned ) {
820
811
// don't connect if the peer is banned
821
812
slog:: crit!( self . log, "Connection has been allowed to a banned peer" ; "peer_id" => %peer_id) ;
822
813
}
@@ -878,42 +869,45 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
878
869
events : & mut SmallVec < [ PeerManagerEvent ; 16 ] > ,
879
870
log : & slog:: Logger ,
880
871
) {
881
- if previous_state != info. score_state ( ) {
882
- match info. score_state ( ) {
883
- ScoreState :: Banned => {
884
- debug ! ( log, "Peer has been banned" ; "peer_id" => %peer_id, "score" => %info. score( ) ) ;
885
- to_ban_peers. push ( * peer_id) ;
886
- }
887
- ScoreState :: Disconnected => {
888
- debug ! ( log, "Peer transitioned to disconnect state" ; "peer_id" => %peer_id, "score" => %info. score( ) , "past_state" => %previous_state) ;
889
- // disconnect the peer if it's currently connected or dialing
890
- if info. is_connected_or_dialing ( ) {
891
- // Change the state to inform that we are disconnecting the peer.
892
- info. disconnecting ( false ) ;
893
- events. push ( PeerManagerEvent :: DisconnectPeer (
894
- * peer_id,
895
- GoodbyeReason :: BadScore ,
896
- ) ) ;
897
- } else if info. is_banned ( ) {
898
- to_unban_peers. push ( * peer_id) ;
899
- }
900
- }
901
- ScoreState :: Healthy => {
902
- debug ! ( log, "Peer transitioned to healthy state" ; "peer_id" => %peer_id, "score" => %info. score( ) , "past_state" => %previous_state) ;
903
- // unban the peer if it was previously banned.
904
- if info. is_banned ( ) {
905
- to_unban_peers. push ( * peer_id) ;
906
- }
872
+ match ( info. score_state ( ) , previous_state) {
873
+ ( ScoreState :: Banned , ScoreState :: Healthy | ScoreState :: Disconnected ) => {
874
+ debug ! ( log, "Peer has been banned" ; "peer_id" => %peer_id, "score" => %info. score( ) ) ;
875
+ to_ban_peers. push ( * peer_id) ;
876
+ }
877
+ ( ScoreState :: Disconnected , ScoreState :: Banned | ScoreState :: Healthy ) => {
878
+ debug ! ( log, "Peer transitioned to disconnect state" ; "peer_id" => %peer_id, "score" => %info. score( ) , "past_state" => %previous_state) ;
879
+ // disconnect the peer if it's currently connected or dialing
880
+ if info. is_connected_or_dialing ( ) {
881
+ // Change the state to inform that we are disconnecting the peer.
882
+ info. disconnecting ( false ) ;
883
+ events. push ( PeerManagerEvent :: DisconnectPeer (
884
+ * peer_id,
885
+ GoodbyeReason :: BadScore ,
886
+ ) ) ;
887
+ } else if previous_state == ScoreState :: Banned {
888
+ to_unban_peers. push ( * peer_id) ;
907
889
}
908
890
}
891
+ ( ScoreState :: Healthy , ScoreState :: Disconnected ) => {
892
+ debug ! ( log, "Peer transitioned to healthy state" ; "peer_id" => %peer_id, "score" => %info. score( ) , "past_state" => %previous_state) ;
893
+ }
894
+ ( ScoreState :: Healthy , ScoreState :: Banned ) => {
895
+ debug ! ( log, "Peer transitioned to healthy state" ; "peer_id" => %peer_id, "score" => %info. score( ) , "past_state" => %previous_state) ;
896
+ // unban the peer if it was previously banned.
897
+ to_unban_peers. push ( * peer_id) ;
898
+ }
899
+ // Explicitly ignore states that haven't transitioned.
900
+ ( ScoreState :: Healthy , ScoreState :: Healthy ) => { }
901
+ ( ScoreState :: Disconnected , ScoreState :: Disconnected ) => { }
902
+ ( ScoreState :: Banned , ScoreState :: Banned ) => { }
909
903
}
910
904
}
911
905
912
906
/// Updates the state of banned peers.
913
907
fn ban_and_unban_peers ( & mut self , to_ban_peers : Vec < PeerId > , to_unban_peers : Vec < PeerId > ) {
914
908
// process banning peers
915
909
for peer_id in to_ban_peers {
916
- self . ban_peer ( & peer_id) ;
910
+ self . ban_peer ( & peer_id, GoodbyeReason :: BadScore ) ;
917
911
}
918
912
// process unbanning peers
919
913
for peer_id in to_unban_peers {
@@ -953,40 +947,49 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
953
947
///
954
948
/// Records updates the peers connection status and updates the peer db as well as blocks the
955
949
/// peer from participating in discovery and removes them from the routing table.
956
- fn ban_peer ( & mut self , peer_id : & PeerId ) {
957
- {
958
- // write lock scope
959
- let mut peer_db = self . network_globals . peers . write ( ) ;
950
+ fn ban_peer ( & mut self , peer_id : & PeerId , reason : GoodbyeReason ) {
951
+ // NOTE: When we ban a peer, its IP address can be banned. We do not recursively search
952
+ // through all our connected peers banning all other peers that are using this IP address.
953
+ // If these peers are behaving fine, we permit their current connections. However, if any new
954
+ // nodes or current nodes try to reconnect on a banned IP, they will be instantly banned
955
+ // and disconnected.
956
+
957
+ let mut peer_db = self . network_globals . peers . write ( ) ;
960
958
961
- if peer_db. disconnect_and_ban ( peer_id) {
959
+ match peer_db. disconnect_and_ban ( peer_id) {
960
+ BanOperation :: DisconnectThePeer => {
962
961
// The peer was currently connected, so we start a disconnection.
963
- self . events . push ( PeerManagerEvent :: DisconnectPeer (
964
- * peer_id ,
965
- GoodbyeReason :: BadScore ,
966
- ) ) ;
962
+ // Once the peer has disconnected, this function will be called to again to ban
963
+ // at the swarm level.
964
+ self . events
965
+ . push ( PeerManagerEvent :: DisconnectPeer ( * peer_id , reason ) ) ;
967
966
}
968
- } // end write lock
969
-
970
- // take a read lock
971
- let peer_db = self . network_globals . peers . read ( ) ;
972
-
973
- let banned_ip_addresses = peer_db
974
- . peer_info ( peer_id)
975
- . map ( |info| {
976
- info. seen_addresses ( )
977
- . filter ( |ip| peer_db. is_ip_banned ( ip) )
978
- . collect :: < Vec < _ > > ( )
979
- } )
980
- . unwrap_or_default ( ) ;
967
+ BanOperation :: PeerDisconnecting => {
968
+ // The peer is currently being disconnected and will be banned once the
969
+ // disconnection completes.
970
+ }
971
+ BanOperation :: ReadyToBan => {
972
+ // The peer is not currently connected, we can safely ban it at the swarm
973
+ // level.
974
+ let banned_ip_addresses = peer_db
975
+ . peer_info ( peer_id)
976
+ . map ( |info| {
977
+ info. seen_addresses ( )
978
+ . filter ( |ip| peer_db. is_ip_banned ( ip) )
979
+ . collect :: < Vec < _ > > ( )
980
+ } )
981
+ . unwrap_or_default ( ) ;
981
982
982
- // Inform the Swarm to ban the peer
983
- self . events
984
- . push ( PeerManagerEvent :: Banned ( * peer_id, banned_ip_addresses) ) ;
983
+ // Inform the Swarm to ban the peer
984
+ self . events
985
+ . push ( PeerManagerEvent :: Banned ( * peer_id, banned_ip_addresses) ) ;
986
+ }
987
+ }
985
988
}
986
989
987
990
/// Unbans a peer.
988
991
///
989
- /// Records updates the peers connection status and updates the peer db as well as removes
992
+ /// Updates the peer's connection status and updates the peer db as well as removes
990
993
/// previous bans from discovery.
991
994
fn unban_peer ( & mut self , peer_id : & PeerId ) -> Result < ( ) , & ' static str > {
992
995
let mut peer_db = self . network_globals . peers . write ( ) ;
@@ -1003,6 +1006,16 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
1003
1006
Ok ( ( ) )
1004
1007
}
1005
1008
1009
+ // Gracefully disconnects a peer without banning them.
1010
+ fn disconnect_peer ( & mut self , peer_id : PeerId , reason : GoodbyeReason ) {
1011
+ self . events
1012
+ . push ( PeerManagerEvent :: DisconnectPeer ( peer_id, reason) ) ;
1013
+ self . network_globals
1014
+ . peers
1015
+ . write ( )
1016
+ . notify_disconnecting ( peer_id, false ) ;
1017
+ }
1018
+
1006
1019
/// Run discovery query for additional sync committee peers if we fall below `TARGET_PEERS`.
1007
1020
fn maintain_sync_committee_peers ( & mut self ) {
1008
1021
// Remove expired entries
@@ -1101,13 +1114,8 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
1101
1114
}
1102
1115
}
1103
1116
1104
- let mut peer_db = self . network_globals . peers . write ( ) ;
1105
1117
for peer_id in disconnecting_peers {
1106
- peer_db. notify_disconnecting ( peer_id, false ) ;
1107
- self . events . push ( PeerManagerEvent :: DisconnectPeer (
1108
- peer_id,
1109
- GoodbyeReason :: TooManyPeers ,
1110
- ) ) ;
1118
+ self . disconnect_peer ( peer_id, GoodbyeReason :: TooManyPeers ) ;
1111
1119
}
1112
1120
}
1113
1121
}
0 commit comments