github.com/koko1123/flow-go-1@v0.29.6/network/p2p/connection/connection_gater.go (about)

     1  package connection
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/libp2p/go-libp2p/core/connmgr"
     7  	"github.com/libp2p/go-libp2p/core/control"
     8  	"github.com/libp2p/go-libp2p/core/network"
     9  	"github.com/libp2p/go-libp2p/core/peer"
    10  	"github.com/multiformats/go-multiaddr"
    11  	"github.com/rs/zerolog"
    12  
    13  	"github.com/koko1123/flow-go-1/network/p2p"
    14  	"github.com/koko1123/flow-go-1/utils/logging"
    15  )
    16  
    17  var _ connmgr.ConnectionGater = (*ConnGater)(nil)
    18  
    19  // ConnGaterOption allow the connection gater to be configured with a list of PeerFilter funcs for a specific conn gater callback.
    20  // In the current implementation of the ConnGater the following callbacks can be configured with peer filters.
    21  // * InterceptPeerDial - peer filters can be configured with WithOnInterceptPeerDialFilters which will allow or disallow outbound connections.
    22  // * InterceptSecured - peer filters can be configured with WithOnInterceptSecuredFilters which will allow or disallow inbound connections after libP2P security handshake.
    23  type ConnGaterOption func(*ConnGater)
    24  
    25  // WithOnInterceptPeerDialFilters sets peer filters for outbound connections.
    26  func WithOnInterceptPeerDialFilters(filters []p2p.PeerFilter) ConnGaterOption {
    27  	return func(c *ConnGater) {
    28  		c.onInterceptPeerDialFilters = filters
    29  	}
    30  }
    31  
    32  // WithOnInterceptSecuredFilters sets peer filters for inbound secured connections.
    33  func WithOnInterceptSecuredFilters(filters []p2p.PeerFilter) ConnGaterOption {
    34  	return func(c *ConnGater) {
    35  		c.onInterceptSecuredFilters = filters
    36  	}
    37  }
    38  
    39  // ConnGater is the implementation of the libp2p connmgr.ConnectionGater interface
    40  // It provides node allowlisting by libp2p peer.ID which is derived from the node public networking key
    41  type ConnGater struct {
    42  	sync.RWMutex
    43  	onInterceptPeerDialFilters []p2p.PeerFilter
    44  	onInterceptSecuredFilters  []p2p.PeerFilter
    45  	log                        zerolog.Logger
    46  }
    47  
    48  func NewConnGater(log zerolog.Logger, opts ...ConnGaterOption) *ConnGater {
    49  	cg := &ConnGater{
    50  		log: log.With().Str("component", "connection_gater").Logger(),
    51  	}
    52  
    53  	for _, opt := range opts {
    54  		opt(cg)
    55  	}
    56  
    57  	return cg
    58  }
    59  
    60  // InterceptPeerDial - a callback which allows or disallows outbound connection
    61  func (c *ConnGater) InterceptPeerDial(p peer.ID) bool {
    62  	if len(c.onInterceptPeerDialFilters) == 0 {
    63  		c.log.Debug().
    64  			Str("peer_id", p.String()).
    65  			Msg("allowing outbound connection intercept peer dial has no peer filters set")
    66  		return true
    67  	}
    68  
    69  	if err := c.peerIDPassesAllFilters(p, c.onInterceptPeerDialFilters); err != nil {
    70  		// log the filtered outbound connection attempt
    71  		c.log.Warn().
    72  			Err(err).
    73  			Str("peer_id", p.String()).
    74  			Msg("rejected outbound connection attempt")
    75  		return false
    76  	}
    77  
    78  	return true
    79  }
    80  
    81  // InterceptAddrDial is not used. Currently, allowlisting is only implemented by Peer IDs and not multi-addresses
    82  func (c *ConnGater) InterceptAddrDial(_ peer.ID, ma multiaddr.Multiaddr) bool {
    83  	return true
    84  }
    85  
    86  // InterceptAccept is not used. Currently, allowlisting is only implemented by Peer IDs and not multi-addresses
    87  func (c *ConnGater) InterceptAccept(cm network.ConnMultiaddrs) bool {
    88  	return true
    89  }
    90  
    91  // InterceptSecured a callback executed after the libp2p security handshake. It tests whether to accept or reject
    92  // an inbound connection based on its peer id.
    93  func (c *ConnGater) InterceptSecured(dir network.Direction, p peer.ID, addr network.ConnMultiaddrs) bool {
    94  	switch dir {
    95  	case network.DirInbound:
    96  		lg := c.log.With().
    97  			Str("peer_id", p.String()).
    98  			Str("remote_address", addr.RemoteMultiaddr().String()).
    99  			Logger()
   100  
   101  		if len(c.onInterceptSecuredFilters) == 0 {
   102  			lg.Info().Msg("inbound connection established")
   103  			return true
   104  		}
   105  
   106  		if err := c.peerIDPassesAllFilters(p, c.onInterceptSecuredFilters); err != nil {
   107  			// log the illegal connection attempt from the remote node
   108  			lg.Error().
   109  				Err(err).
   110  				Str("local_address", addr.LocalMultiaddr().String()).
   111  				Bool(logging.KeySuspicious, true).
   112  				Msg("rejected inbound connection")
   113  			return false
   114  		}
   115  
   116  		lg.Info().Msg("inbound connection established")
   117  		return true
   118  	default:
   119  		// outbound connection should have been already blocked before this call
   120  		return true
   121  	}
   122  }
   123  
   124  // InterceptUpgraded decision to continue or drop the connection should have been made before this call
   125  func (c *ConnGater) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) {
   126  	return true, 0
   127  }
   128  
   129  func (c *ConnGater) peerIDPassesAllFilters(p peer.ID, filters []p2p.PeerFilter) error {
   130  	for _, allowed := range filters {
   131  		if err := allowed(p); err != nil {
   132  			return err
   133  		}
   134  	}
   135  
   136  	return nil
   137  }