@@ -28,6 +28,7 @@ import (
2828 "github.com/libp2p/go-libp2p/core/peer"
2929 "github.com/libp2p/go-libp2p/p2p/discovery/mdns"
3030 drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
31+ "github.com/libp2p/go-libp2p/p2p/net/conngater"
3132 "github.com/multiformats/go-multiaddr"
3233 manet "github.com/multiformats/go-multiaddr/net"
3334
@@ -163,9 +164,61 @@ func getLogger(configLogger logger) logger {
163164 return configLogger
164165}
165166
167+ // createPrivateIPConnectionGater creates a ConnectionGater that blocks private IP ranges.
168+ // Returns a configured BasicConnectionGater that prevents connections to/from:
169+ // - RFC1918 private networks (10.x, 172.16-31.x, 192.168.x)
170+ // - Link-local addresses (169.254.x, fe80::)
171+ // - Loopback addresses (127.x, ::1)
172+ // - Shared address space (100.64.x)
173+ // - IPv6 unique local addresses (fc00::)
174+ func createPrivateIPConnectionGater (log logger , cancel context.CancelFunc ) (* conngater.BasicConnectionGater , error ) {
175+ ipFilter , err := conngater .NewBasicConnectionGater (nil )
176+ if err != nil {
177+ cancel ()
178+ return nil , fmt .Errorf ("failed to create connection gater: %w" , err )
179+ }
180+
181+ // Standard private IP ranges to block
182+ privateRanges := []string {
183+ "10.0.0.0/8" , // RFC1918 private network
184+ "172.16.0.0/12" , // RFC1918 private network
185+ "192.168.0.0/16" , // RFC1918 private network
186+ "127.0.0.0/8" , // Loopback
187+ "169.254.0.0/16" , // Link-local
188+ "100.64.0.0/10" , // Shared Address Space (RFC6598)
189+ "fc00::/7" , // IPv6 Unique Local Addresses
190+ "fe80::/10" , // IPv6 Link-Local Addresses
191+ "::1/128" , // IPv6 Loopback
192+ }
193+
194+ for _ , cidr := range privateRanges {
195+ _ , ipnet , err := net .ParseCIDR (cidr )
196+ if err != nil {
197+ cancel ()
198+ return nil , fmt .Errorf ("failed to parse CIDR %s: %w" , cidr , err )
199+ }
200+ if err := ipFilter .BlockSubnet (ipnet ); err != nil {
201+ log .Warnf ("Failed to block subnet %s: %v" , cidr , err )
202+ }
203+ }
204+
205+ return ipFilter , nil
206+ }
207+
166208func buildHostOptions (config Config , log logger , cancel context.CancelFunc ) ([]libp2p.Option , error ) {
167209 hostOpts := []libp2p.Option {libp2p .Identity (config .PrivateKey )}
168210
211+ // Add connection gater to block private IPs if AllowPrivateIPs is false (default)
212+ if ! config .AllowPrivateIPs {
213+ ipFilter , err := createPrivateIPConnectionGater (log , cancel )
214+ if err != nil {
215+ return nil , err
216+ }
217+
218+ hostOpts = append (hostOpts , libp2p .ConnectionGater (ipFilter ))
219+ log .Infof ("Private IP connection gater enabled (blocking RFC1918 and local addresses)" )
220+ }
221+
169222 // Configure announce addresses if provided (useful for K8s)
170223 if len (config .AnnounceAddrs ) > 0 {
171224 announceAddrs := make ([]multiaddr.Multiaddr , 0 , len (config .AnnounceAddrs ))
@@ -316,6 +369,7 @@ func connectToBootstrapPeers(ctx context.Context, h host.Host, peers []peer.Addr
316369 if connectErr := h .Connect (ctx , pi ); connectErr == nil {
317370 log .Infof ("Connected to bootstrap peer: %s" , pi .ID .String ())
318371 }
372+ // Note: ConnectionGater silently blocks private IPs, no error logged here
319373 }(peerInfo )
320374 }
321375}
@@ -332,6 +386,7 @@ func connectToRelayPeers(ctx context.Context, h host.Host, peers []peer.AddrInfo
332386 } else {
333387 log .Warnf ("Failed to connect to relay peer %s: %v" , pi .ID .String (), connectErr )
334388 }
389+ // Note: ConnectionGater silently blocks private IPs
335390 }(relayPeer )
336391 }
337392}
@@ -630,15 +685,7 @@ func (c *client) connectToDiscoveredPeer(ctx context.Context, peerInfo peer.Addr
630685 return
631686 }
632687
633- // Filter private IPs unless explicitly allowed (default: filter for production safety)
634- if ! c .config .AllowPrivateIPs {
635- peerInfo .Addrs = filterPrivateAddrs (peerInfo .Addrs )
636- if len (peerInfo .Addrs ) == 0 {
637- // All addresses were private, skip this peer
638- return
639- }
640- }
641-
688+ // ConnectionGater handles private IP filtering, so just try to connect
642689 if err := c .host .Connect (ctx , peerInfo ); err != nil {
643690 if c .shouldLogConnectionError (err ) {
644691 c .logger .Debugf ("Failed to connect to discovered peer %s: %v" , peerInfo .ID .String (), err )
@@ -891,6 +938,7 @@ func connectToCachedPeers(ctx context.Context, h host.Host, cachedPeers []cached
891938 } else {
892939 logger .Warnf ("Failed to reconnect to cached peer %s [%s]: %v" , name , ai .ID .String (), err )
893940 }
941+ // Note: ConnectionGater silently blocks private IPs
894942 }(addrInfo , cp .Name )
895943 }
896944}
0 commit comments