Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

deprecate this repo #81

Merged
merged 2 commits into from
Aug 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# DEPRECATION NOTICE

This package has moved into go-libp2p as a sub-package, `github.com/libp2p/go-libp2p/p2p/host/resource-manager`.

# The libp2p Network Resource Manager

This package contains the canonical implementation of the libp2p
Expand Down
209 changes: 5 additions & 204 deletions allowlist.go
Original file line number Diff line number Diff line change
@@ -1,215 +1,16 @@
package rcmgr

import (
"bytes"
"errors"
"fmt"
"net"
"sync"
rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager"

"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
)

type Allowlist struct {
mu sync.RWMutex
// a simple structure of lists of networks. There is probably a faster way
// to check if an IP address is in this network than iterating over this
// list, but this is good enough for small numbers of networks (<1_000).
// Analyze the benchmark before trying to optimize this.

// Any peer with these IPs are allowed
allowedNetworks []*net.IPNet

// Only the specified peers can use these IPs
allowedPeerByNetwork map[peer.ID][]*net.IPNet
}
// Deprecated: use github.com/libp2p/go-libp2p/p2p/host/resource-manager.Allowlist instead
type Allowlist = rcmgr.Allowlist

// WithAllowlistedMultiaddrs sets the multiaddrs to be in the allowlist
// Deprecated: use github.com/libp2p/go-libp2p/p2p/host/resource-manager.WithAllowlistedMultiaddrs instead
func WithAllowlistedMultiaddrs(mas []multiaddr.Multiaddr) Option {
return func(rm *resourceManager) error {
for _, ma := range mas {
err := rm.allowlist.Add(ma)
if err != nil {
return err
}
}
return nil
}
}

func newAllowlist() Allowlist {
return Allowlist{
allowedPeerByNetwork: make(map[peer.ID][]*net.IPNet),
}
}

func toIPNet(ma multiaddr.Multiaddr) (*net.IPNet, peer.ID, error) {
var ipString string
var mask string
var allowedPeerStr string
var allowedPeer peer.ID
var isIPV4 bool

multiaddr.ForEach(ma, func(c multiaddr.Component) bool {
if c.Protocol().Code == multiaddr.P_IP4 || c.Protocol().Code == multiaddr.P_IP6 {
isIPV4 = c.Protocol().Code == multiaddr.P_IP4
ipString = c.Value()
}
if c.Protocol().Code == multiaddr.P_IPCIDR {
mask = c.Value()
}
if c.Protocol().Code == multiaddr.P_P2P {
allowedPeerStr = c.Value()
}
return ipString == "" || mask == "" || allowedPeerStr == ""
})

if ipString == "" {
return nil, allowedPeer, errors.New("missing ip address")
}

if allowedPeerStr != "" {
var err error
allowedPeer, err = peer.Decode(allowedPeerStr)
if err != nil {
return nil, allowedPeer, fmt.Errorf("failed to decode allowed peer: %w", err)
}
}

if mask == "" {
ip := net.ParseIP(ipString)
if ip == nil {
return nil, allowedPeer, errors.New("invalid ip address")
}
var mask net.IPMask
if isIPV4 {
mask = net.CIDRMask(32, 32)
} else {
mask = net.CIDRMask(128, 128)
}

net := &net.IPNet{IP: ip, Mask: mask}
return net, allowedPeer, nil
}

_, ipnet, err := net.ParseCIDR(ipString + "/" + mask)
return ipnet, allowedPeer, err

}

// Add takes a multiaddr and adds it to the allowlist. The multiaddr should be
// an ip address of the peer with or without a `/p2p` protocol.
// e.g. /ip4/1.2.3.4/p2p/QmFoo, /ip4/1.2.3.4, and /ip4/1.2.3.0/ipcidr/24 are valid.
// /p2p/QmFoo is not valid.
func (al *Allowlist) Add(ma multiaddr.Multiaddr) error {
ipnet, allowedPeer, err := toIPNet(ma)
if err != nil {
return err
}
al.mu.Lock()
defer al.mu.Unlock()

if allowedPeer != peer.ID("") {
// We have a peerID constraint
if al.allowedPeerByNetwork == nil {
al.allowedPeerByNetwork = make(map[peer.ID][]*net.IPNet)
}
al.allowedPeerByNetwork[allowedPeer] = append(al.allowedPeerByNetwork[allowedPeer], ipnet)
} else {
al.allowedNetworks = append(al.allowedNetworks, ipnet)
}
return nil
}

func (al *Allowlist) Remove(ma multiaddr.Multiaddr) error {
ipnet, allowedPeer, err := toIPNet(ma)
if err != nil {
return err
}
al.mu.Lock()
defer al.mu.Unlock()

ipNetList := al.allowedNetworks

if allowedPeer != "" {
// We have a peerID constraint
ipNetList = al.allowedPeerByNetwork[allowedPeer]
}

if ipNetList == nil {
return nil
}

i := len(ipNetList)
for i > 0 {
i--
if ipNetList[i].IP.Equal(ipnet.IP) && bytes.Equal(ipNetList[i].Mask, ipnet.Mask) {
// swap remove
ipNetList[i] = ipNetList[len(ipNetList)-1]
ipNetList = ipNetList[:len(ipNetList)-1]
// We only remove one thing
break
}
}

if allowedPeer != "" {
al.allowedPeerByNetwork[allowedPeer] = ipNetList
} else {
al.allowedNetworks = ipNetList
}

return nil
}

func (al *Allowlist) Allowed(ma multiaddr.Multiaddr) bool {
ip, err := manet.ToIP(ma)
if err != nil {
return false
}
al.mu.RLock()
defer al.mu.RUnlock()

for _, network := range al.allowedNetworks {
if network.Contains(ip) {
return true
}
}

for _, allowedNetworks := range al.allowedPeerByNetwork {
for _, network := range allowedNetworks {
if network.Contains(ip) {
return true
}
}
}

return false
}

func (al *Allowlist) AllowedPeerAndMultiaddr(peerID peer.ID, ma multiaddr.Multiaddr) bool {
ip, err := manet.ToIP(ma)
if err != nil {
return false
}
al.mu.RLock()
defer al.mu.RUnlock()

for _, network := range al.allowedNetworks {
if network.Contains(ip) {
// We found a match that isn't constrained by a peerID
return true
}
}

if expectedNetworks, ok := al.allowedPeerByNetwork[peerID]; ok {
for _, expectedNetwork := range expectedNetworks {
if expectedNetwork.Contains(ip) {
return true
}
}
}

return false
return rcmgr.WithAllowlistedMultiaddrs(mas)
}
Loading