github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/p2p/connection_gater.go (about) 1 package p2p 2 3 import ( 4 "net" 5 "runtime" 6 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 manet "github.com/multiformats/go-multiaddr/net" 12 "github.com/sirupsen/logrus" 13 ) 14 15 const ( 16 // Limit for rate limiter when processing new inbound dials. 17 ipLimit = 4 18 19 // Burst limit for inbound dials. 20 ipBurst = 8 21 22 // High watermark buffer signifies the buffer till which 23 // we will handle inbound requests. 24 highWatermarkBuffer = 10 25 ) 26 27 // InterceptPeerDial tests whether we're permitted to Dial the specified peer. 28 func (s *Service) InterceptPeerDial(_ peer.ID) (allow bool) { 29 return true 30 } 31 32 // InterceptAddrDial tests whether we're permitted to dial the specified 33 // multiaddr for the given peer. 34 func (s *Service) InterceptAddrDial(pid peer.ID, m multiaddr.Multiaddr) (allow bool) { 35 // Disallow bad peers from dialing in. 36 if s.peers.IsBad(pid) { 37 return false 38 } 39 return filterConnections(s.addrFilter, m) 40 } 41 42 // InterceptAccept checks whether the incidental inbound connection is allowed. 43 func (s *Service) InterceptAccept(n network.ConnMultiaddrs) (allow bool) { 44 if !s.validateDial(n.RemoteMultiaddr()) { 45 // Allow other go-routines to run in the event 46 // we receive a large amount of junk connections. 47 runtime.Gosched() 48 log.WithFields(logrus.Fields{"peer": n.RemoteMultiaddr(), 49 "reason": "exceeded dial limit"}).Trace("Not accepting inbound dial from ip address") 50 return false 51 } 52 if s.isPeerAtLimit(true /* inbound */) { 53 log.WithFields(logrus.Fields{"peer": n.RemoteMultiaddr(), 54 "reason": "at peer limit"}).Trace("Not accepting inbound dial") 55 return false 56 } 57 return filterConnections(s.addrFilter, n.RemoteMultiaddr()) 58 } 59 60 // InterceptSecured tests whether a given connection, now authenticated, 61 // is allowed. 62 func (s *Service) InterceptSecured(_ network.Direction, _ peer.ID, _ network.ConnMultiaddrs) (allow bool) { 63 return true 64 } 65 66 // InterceptUpgraded tests whether a fully capable connection is allowed. 67 func (s *Service) InterceptUpgraded(_ network.Conn) (allow bool, reason control.DisconnectReason) { 68 return true, 0 69 } 70 71 func (s *Service) validateDial(addr multiaddr.Multiaddr) bool { 72 ip, err := manet.ToIP(addr) 73 if err != nil { 74 return false 75 } 76 remaining := s.ipLimiter.Remaining(ip.String()) 77 if remaining <= 0 { 78 return false 79 } 80 s.ipLimiter.Add(ip.String(), 1) 81 return true 82 } 83 84 var privateCIDRList = []string{ 85 // Private ip addresses specified by rfc-1918. 86 // See: https://tools.ietf.org/html/rfc1918 87 "10.0.0.0/8", 88 "172.16.0.0/12", 89 "192.168.0.0/16", 90 // Reserved address space for CGN devices, specified by rfc-6598 91 // See: https://tools.ietf.org/html/rfc6598 92 "100.64.0.0/10", 93 // IPv4 Link-Local addresses, specified by rfc-3926 94 // See: https://tools.ietf.org/html/rfc3927 95 "169.254.0.0/16", 96 } 97 98 // configureFilter looks at the provided allow lists and 99 // deny lists to appropriately create a filter. 100 func configureFilter(cfg *Config) (*multiaddr.Filters, error) { 101 addrFilter := multiaddr.NewFilters() 102 var privErr error 103 switch { 104 case cfg.AllowListCIDR == "public": 105 cfg.DenyListCIDR = append(cfg.DenyListCIDR, privateCIDRList...) 106 case cfg.AllowListCIDR == "private": 107 addrFilter, privErr = privateCIDRFilter(addrFilter, multiaddr.ActionAccept) 108 if privErr != nil { 109 return nil, privErr 110 } 111 case cfg.AllowListCIDR != "": 112 _, ipnet, err := net.ParseCIDR(cfg.AllowListCIDR) 113 if err != nil { 114 return nil, err 115 } 116 addrFilter.AddFilter(*ipnet, multiaddr.ActionAccept) 117 } 118 119 // Configure from provided deny list in the config. 120 if len(cfg.DenyListCIDR) > 0 { 121 for _, cidr := range cfg.DenyListCIDR { 122 // If an entry in the deny list is "private", we iterate through the 123 // private addresses and add them to the filter. Likewise, if the deny 124 // list is "public", then we add all private address to the accept filter, 125 switch { 126 case cidr == "private": 127 addrFilter, privErr = privateCIDRFilter(addrFilter, multiaddr.ActionDeny) 128 if privErr != nil { 129 return nil, privErr 130 } 131 continue 132 case cidr == "public": 133 addrFilter, privErr = privateCIDRFilter(addrFilter, multiaddr.ActionAccept) 134 if privErr != nil { 135 return nil, privErr 136 } 137 continue 138 } 139 _, ipnet, err := net.ParseCIDR(cidr) 140 if err != nil { 141 return nil, err 142 } 143 // Check if the address already has an action associated with it 144 // If this address was previously accepted, log a warning before placing 145 // it in the deny filter 146 action, _ := addrFilter.ActionForFilter(*ipnet) 147 if action == multiaddr.ActionAccept { 148 log.Warnf("Address %s is in conflict with previous rule.", ipnet.String()) 149 } 150 addrFilter.AddFilter(*ipnet, multiaddr.ActionDeny) 151 } 152 } 153 return addrFilter, nil 154 } 155 156 //helper function to either accept or deny all private addresses 157 //if a new rule for a private address is in conflict with a previous one, log a warning 158 func privateCIDRFilter(addrFilter *multiaddr.Filters, action multiaddr.Action) (*multiaddr.Filters, error) { 159 for _, privCidr := range privateCIDRList { 160 _, ipnet, err := net.ParseCIDR(privCidr) 161 if err != nil { 162 return nil, err 163 } 164 // Get the current filter action for the address 165 // If it conflicts with the action given by the function call, 166 // log a warning 167 curAction, _ := addrFilter.ActionForFilter(*ipnet) 168 switch { 169 case action == multiaddr.ActionAccept: 170 if curAction == multiaddr.ActionDeny { 171 log.Warnf("Address %s is in conflict with previous rule.", ipnet.String()) 172 } 173 case action == multiaddr.ActionDeny: 174 if curAction == multiaddr.ActionAccept { 175 log.Warnf("Address %s is in conflict with previous rule.", ipnet.String()) 176 } 177 } 178 addrFilter.AddFilter(*ipnet, action) 179 } 180 return addrFilter, nil 181 } 182 183 // filterConnections checks the appropriate ip subnets from our 184 // filter and decides what to do with them. By default libp2p 185 // accepts all incoming dials, so if we have an allow list 186 // we will reject all inbound dials except for those in the 187 // appropriate ip subnets. 188 func filterConnections(f *multiaddr.Filters, a multiaddr.Multiaddr) bool { 189 acceptedNets := f.FiltersForAction(multiaddr.ActionAccept) 190 restrictConns := len(acceptedNets) != 0 191 192 // If we have an allow list added in, we by default reject all 193 // connection attempts except for those coming in from the 194 // appropriate ip subnets. 195 if restrictConns { 196 ip, err := manet.ToIP(a) 197 if err != nil { 198 log.Tracef("Multiaddress has invalid ip: %v", err) 199 return false 200 } 201 found := false 202 for _, ipnet := range acceptedNets { 203 if ipnet.Contains(ip) { 204 found = true 205 break 206 } 207 } 208 return found 209 } 210 return !f.AddrBlocked(a) 211 }