Unverified Commit 192ac0f7 authored by Raúl Kripalani's avatar Raúl Kripalani Committed by GitHub

absorb go-maddr-filter; rm stale Makefile targets; upgrade deps (#124)

parent 8ae68cf3
gx:
go get github.com/whyrusleeping/gx
go get github.com/whyrusleeping/gx-go
covertools:
go get golang.org/x/tools/cmd/cover
deps: gx covertools
gx --verbose install --global
gx-go rewrite
publish:
gx-go rewrite --undo
conformance: tmp/multiaddr
go build -o tmp/multiaddr/test/go-multiaddr ./multiaddr
cd tmp/multiaddr/test && MULTIADDR_BIN="./go-multiaddr" go test -v
......@@ -23,4 +9,4 @@ tmp/multiaddr:
clean:
rm -rf tmp/
.PHONY: gx covertools deps publish conformance clean
.PHONY: conformance clean
package multiaddr
import (
"net"
"sync"
)
// Action is an enum modelling all possible filter actions.
type Action int32
const (
ActionNone Action = iota // zero value.
ActionAccept
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 Multiaddr) (deny bool) {
var (
netip net.IP
found bool
)
ForEach(a, func(c Component) bool {
switch c.Protocol().Code {
case P_IP6ZONE:
return true
case P_IP6, 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()
for _, ff := range fs.filters {
if ff.action == action {
result = append(result, ff.f)
}
}
return result
}
package multiaddr
import (
"net"
"testing"
)
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 := 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 := 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 := 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 := 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 := 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 := 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 := NewMultiaddr(addr)
if err != nil {
t.Error(err)
}
if !f.AddrBlocked(maddr) {
t.Fatalf("expected %s to be blocked", addr)
}
}
}
......@@ -2,20 +2,10 @@ 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-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM=
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
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 h1:6sUvyh2YHpJCb8RZ6eYzj6iJQ4+chWYmyIHxszqlPTA=
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=
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment