diff --git a/README.md b/README.md index db9ba5e..bc0b44a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +## ⚠️ DEPRECATED: Filters have been migrated to [multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr). + go-maddr-filter ================== diff --git a/filter.go b/filter.go index 4eb0c56..b2d4a63 100644 --- a/filter.go +++ b/filter.go @@ -1,181 +1,23 @@ package filter -import ( - "net" - "sync" +import "github.com/multiformats/go-multiaddr" - ma "github.com/multiformats/go-multiaddr" -) - -// Action is an enum modelling all possible filter actions. -type Action int32 +// Deprecated. Use "github.com/multiformats/go-multiaddr".Action instead. +type Action = multiaddr.Action const ( - ActionNone Action = iota // zero value. - ActionAccept - ActionDeny + // Deprecated. Use "github.com/multiformats/go-multiaddr".ActionNone instead. + ActionNone = multiaddr.ActionNone + // Deprecated. Use "github.com/multiformats/go-multiaddr".ActionAccept instead. + ActionAccept = multiaddr.ActionAccept + // Deprecated. Use "github.com/multiformats/go-multiaddr".ActionDeny instead. + ActionDeny = multiaddr.ActionDeny ) -type filterEntry struct { - f net.IPNet - action Action -} - -// Filters is a structure representing a collection of accept/deny -// net.IPNet filters, together with the DefaultAction flag, which -// represents the default filter policy. -// -// Note that the last policy added to the Filters is authoritative. -type Filters struct { - DefaultAction Action - - mu sync.RWMutex - filters []*filterEntry -} - -// NewFilters constructs and returns a new set of net.IPNet filters. -// By default, the new filter accepts all addresses. -func NewFilters() *Filters { - return &Filters{ - DefaultAction: ActionAccept, - filters: make([]*filterEntry, 0), - } -} - -func (fs *Filters) find(ipnet net.IPNet) (int, *filterEntry) { - s := ipnet.String() - for idx, ft := range fs.filters { - if ft.f.String() == s { - return idx, ft - } - } - return -1, nil -} - -// AddDialFilter adds a deny rule to this Filters set. Hosts -// matching the given net.IPNet filter will be denied, unless -// another rule is added which states that they should be accepted. -// -// No effort is made to prevent duplication of filters, or to simplify -// the filters list. -// -// Deprecated: Use AddFilter(). -func (fs *Filters) AddDialFilter(f *net.IPNet) { - fs.AddFilter(*f, ActionDeny) -} - -// AddFilter adds a rule to the Filters set, enforcing the desired action for -// the provided IPNet mask. -func (fs *Filters) AddFilter(ipnet net.IPNet, action Action) { - fs.mu.Lock() - defer fs.mu.Unlock() - - if _, f := fs.find(ipnet); f != nil { - f.action = action - } else { - fs.filters = append(fs.filters, &filterEntry{ipnet, action}) - } -} - -// RemoveLiteral removes the first filter associated with the supplied IPNet, -// returning whether something was removed or not. It makes no distinction -// between whether the rule is an accept or a deny. -// -// Deprecated: use RemoveLiteral() instead. -func (fs *Filters) Remove(ipnet *net.IPNet) (removed bool) { - return fs.RemoveLiteral(*ipnet) -} - -// RemoveLiteral removes the first filter associated with the supplied IPNet, -// returning whether something was removed or not. It makes no distinction -// between whether the rule is an accept or a deny. -func (fs *Filters) RemoveLiteral(ipnet net.IPNet) (removed bool) { - fs.mu.Lock() - defer fs.mu.Unlock() - - if idx, _ := fs.find(ipnet); idx != -1 { - fs.filters = append(fs.filters[:idx], fs.filters[idx+1:]...) - return true - } - return false -} - -// AddrBlocked parses a ma.Multiaddr and, if a valid netip is found, it applies the -// Filter set rules, returning true if the given address should be denied, and false if -// the given address is accepted. -// -// If a parsing error occurs, or no filter matches, the Filters' -// default is returned. -// -// TODO: currently, the last filter to match wins always, but it shouldn't be that way. -// Instead, the highest-specific last filter should win; that way more specific filters -// override more general ones. -func (fs *Filters) AddrBlocked(a ma.Multiaddr) (deny bool) { - var ( - netip net.IP - found bool - ) - - ma.ForEach(a, func(c ma.Component) bool { - switch c.Protocol().Code { - case ma.P_IP6ZONE: - return true - case ma.P_IP6, ma.P_IP4: - found = true - netip = net.IP(c.RawValue()) - return false - default: - return false - } - }) - - if !found { - return fs.DefaultAction == ActionDeny - } - - fs.mu.RLock() - defer fs.mu.RUnlock() - - action := fs.DefaultAction - for _, ft := range fs.filters { - if ft.f.Contains(netip) { - action = ft.action - } - } - - return action == ActionDeny -} - -// Filters returns the list of DENY net.IPNet masks. For backwards compatibility. -// -// A copy of the filters is made prior to returning, so the inner state is not exposed. -// -// Deprecated: Use FiltersForAction(). -func (fs *Filters) Filters() (result []*net.IPNet) { - ffa := fs.FiltersForAction(ActionDeny) - for _, res := range ffa { - res := res // allocate a new copy - result = append(result, &res) - } - return result -} - -func (fs *Filters) ActionForFilter(ipnet net.IPNet) (action Action, ok bool) { - if _, f := fs.find(ipnet); f != nil { - return f.action, true - } - return ActionNone, false -} - -// FiltersForAction returns the filters associated with the indicated action. -func (fs *Filters) FiltersForAction(action Action) (result []net.IPNet) { - fs.mu.RLock() - defer fs.mu.RUnlock() +// Deprecated. Use "github.com/multiformats/go-multiaddr".Filters instead. +type Filters = multiaddr.Filters - for _, ff := range fs.filters { - if ff.action == action { - result = append(result, ff.f) - } - } - return result +// Deprecated. Use "github.com/multiformats/go-multiaddr".NewFilters instead. +func NewFilters() *multiaddr.Filters { + return multiaddr.NewFilters() } diff --git a/filter_test.go b/filter_test.go deleted file mode 100644 index 3df0812..0000000 --- a/filter_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package filter - -import ( - "net" - "testing" - - ma "github.com/multiformats/go-multiaddr" -) - -func TestFilterListing(t *testing.T) { - f := NewFilters() - expected := map[string]bool{ - "1.2.3.0/24": true, - "4.3.2.1/32": true, - "fd00::/8": true, - "fc00::1/128": true, - } - for cidr := range expected { - _, ipnet, _ := net.ParseCIDR(cidr) - f.AddDialFilter(ipnet) - } - - for _, filter := range f.Filters() { - cidr := filter.String() - if expected[cidr] { - delete(expected, cidr) - } else { - t.Errorf("unexected filter %s", cidr) - } - } - for cidr := range expected { - t.Errorf("expected filter %s", cidr) - } -} - -func TestFilterBlocking(t *testing.T) { - f := NewFilters() - - _, ipnet, _ := net.ParseCIDR("0.1.2.3/24") - f.AddDialFilter(ipnet) - filters := f.Filters() - if len(filters) != 1 { - t.Fatal("Expected only 1 filter") - } - - if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionDeny { - t.Fatal("Expected filter with DENY action") - } - - if !f.RemoveLiteral(*filters[0]) { - t.Error("expected true value from RemoveLiteral") - } - - for _, cidr := range []string{ - "1.2.3.0/24", - "4.3.2.1/32", - "fd00::/8", - "fc00::1/128", - } { - _, ipnet, _ := net.ParseCIDR(cidr) - f.AddDialFilter(ipnet) - } - - // These addresses should all be blocked - for _, blocked := range []string{ - "/ip4/1.2.3.4/tcp/123", - "/ip4/4.3.2.1/udp/123", - "/ip6/fd00::2/tcp/321", - "/ip6/fc00::1/udp/321", - } { - maddr, err := ma.NewMultiaddr(blocked) - if err != nil { - t.Error(err) - } - if !f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be blocked", blocked) - } - } - - // test that other net intervals are not blocked - for _, addr := range []string{ - "/ip4/1.2.4.1/tcp/123", - "/ip4/4.3.2.2/udp/123", - "/ip6/fe00::1/tcp/321", - "/ip6/fc00::2/udp/321", - } { - maddr, err := ma.NewMultiaddr(addr) - if err != nil { - t.Error(err) - } - if f.AddrBlocked(maddr) { - t.Fatalf("expected %s to not be blocked", addr) - } - } -} - -func TestFilterWhitelisting(t *testing.T) { - f := NewFilters() - - // Add default reject filter - f.DefaultAction = ActionDeny - - // Add a whitelist - _, ipnet, _ := net.ParseCIDR("1.2.3.0/24") - f.AddFilter(*ipnet, ActionAccept) - - if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionAccept { - t.Fatal("Expected filter with ACCEPT action") - } - - // That /24 should now be allowed - for _, addr := range []string{ - "/ip4/1.2.3.1/tcp/123", - "/ip4/1.2.3.254/tcp/123", - "/ip4/1.2.3.254/udp/321", - } { - maddr, err := ma.NewMultiaddr(addr) - if err != nil { - t.Error(err) - } - if f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be whitelisted", addr) - } - } - - // No policy matches these maddrs, they should be blocked by default - for _, blocked := range []string{ - "/ip4/1.2.4.4/tcp/123", - "/ip4/4.3.2.1/udp/123", - "/ip6/fd00::2/tcp/321", - "/ip6/fc00::1/udp/321", - } { - maddr, err := ma.NewMultiaddr(blocked) - if err != nil { - t.Error(err) - } - if !f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be blocked", blocked) - } - } -} - -func TestFiltersRemoveRules(t *testing.T) { - f := NewFilters() - - ips := []string{ - "/ip4/1.2.3.1/tcp/123", - "/ip4/1.2.3.254/tcp/123", - } - - // Add default reject filter - f.DefaultAction = ActionDeny - - // Add whitelisting - _, ipnet, _ := net.ParseCIDR("1.2.3.0/24") - f.AddFilter(*ipnet, ActionAccept) - - if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionAccept { - t.Fatal("Expected filter with ACCEPT action") - } - - // these are all whitelisted, should be OK - for _, addr := range ips { - maddr, err := ma.NewMultiaddr(addr) - if err != nil { - t.Error(err) - } - if f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be whitelisted", addr) - } - } - - // Test removing the filter. It'll remove multiple, so make a dupe & - // a complement - f.AddDialFilter(ipnet) - - // Show that they all apply, these are now blacklisted & should fail - for _, addr := range ips { - maddr, err := ma.NewMultiaddr(addr) - if err != nil { - t.Error(err) - } - if !f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be blacklisted", addr) - } - } - - // remove those rules - if !f.RemoveLiteral(*ipnet) { - t.Error("expected true value from RemoveLiteral") - } - - // our default is reject, so the 1.2.3.0/24 should be rejected now, - // along with everything else - for _, addr := range ips { - maddr, err := ma.NewMultiaddr(addr) - if err != nil { - t.Error(err) - } - if !f.AddrBlocked(maddr) { - t.Fatalf("expected %s to be blocked", addr) - } - } -} diff --git a/go.mod b/go.mod index 281a6aa..95fcc41 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/libp2p/go-maddr-filter -require github.com/multiformats/go-multiaddr v0.2.1 - go 1.13 + +require github.com/multiformats/go-multiaddr v0.2.2 diff --git a/go.sum b/go.sum index 9ac0a4b..cc364aa 100644 --- a/go.sum +++ b/go.sum @@ -2,23 +2,12 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-multiaddr v0.1.2 h1:HWYHNSyyllbQopmVIF5K7JKJugiah+L9/kuZKHbmNdQ= -github.com/multiformats/go-multiaddr v0.1.2/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5a9qECv/J90= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.2.1 h1:SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI= -github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= -github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multiaddr v0.2.2 h1:XZLDTszBIJe6m0zF6ITBrEcZR73OPUhCBBS9rYAuUzI= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc= github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=