From e01f8e4f22a929b69daaaadeda730dc6f3d05d5d Mon Sep 17 00:00:00 2001 From: Jeromy Date: Tue, 16 Jun 2015 11:06:04 -0700 Subject: [PATCH 1/3] add in basic address dial filtering License: MIT Signed-off-by: Jeromy --- Godeps/Godeps.json | 4 +++ .../whyrusleeping/multiaddr-filter/mask.go | 19 ++++++++++ .../multiaddr-filter/mask_test.go | 36 +++++++++++++++++++ core/core.go | 24 +++++++++---- p2p/net/swarm/swarm.go | 8 +++++ p2p/net/swarm/swarm_dial.go | 28 +++++++++++++++ repo/config/config.go | 1 + util/sadhack/godep.go | 1 + 8 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask.go create mode 100644 Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask_test.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4ee07c958..426cabafd 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -239,6 +239,10 @@ "ImportPath": "github.com/whyrusleeping/iptb", "Rev": "3970c95a864f1a40037f796ff596607ce8ae43be" }, + { + "ImportPath": "github.com/whyrusleeping/multiaddr-filter", + "Rev": "15837fcc356fddef27c634b0f6379b3b7f259114" + }, { "ImportPath": "golang.org/x/crypto/blowfish", "Rev": "c84e1f8e3a7e322d497cd16c0e8a13c7e127baf3" diff --git a/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask.go b/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask.go new file mode 100644 index 000000000..91208fe04 --- /dev/null +++ b/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask.go @@ -0,0 +1,19 @@ +package mask + +import ( + "errors" + "net" + "strings" +) + +func NewMask(a string) (*net.IPNet, error) { + parts := strings.Split(a, "/") + if len(parts) == 5 && parts[1] == "ip4" && parts[3] == "ipcidr" { + _, ipn, err := net.ParseCIDR(parts[2] + "/" + parts[4]) + if err != nil { + return nil, err + } + return ipn, nil + } + return nil, errors.New("invalid format") +} diff --git a/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask_test.go b/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask_test.go new file mode 100644 index 000000000..4507dca68 --- /dev/null +++ b/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask_test.go @@ -0,0 +1,36 @@ +package mask + +import ( + "net" + "testing" +) + +func TestFiltered(t *testing.T) { + var tests = map[string]map[string]bool{ + "/ip4/10.0.0.0/ipcidr/8": map[string]bool{ + "10.3.3.4": true, + "10.3.4.4": true, + "10.4.4.4": true, + "15.52.34.3": false, + }, + "/ip4/192.168.0.0/ipcidr/16": map[string]bool{ + "192.168.0.0": true, + "192.168.1.0": true, + "192.1.0.0": false, + "10.4.4.4": false, + }, + } + + for mask, set := range tests { + m, err := NewMask(mask) + if err != nil { + t.Fatal(err) + } + for addr, val := range set { + ip := net.ParseIP(addr) + if m.Contains(ip) != val { + t.Fatalf("expected contains(%s, %s) == %s", mask, addr, val) + } + } + } +} diff --git a/core/core.go b/core/core.go index 877ffe9c0..e3111a172 100644 --- a/core/core.go +++ b/core/core.go @@ -13,17 +13,17 @@ import ( "errors" "fmt" "io" + "net" "time" b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" ctxgroup "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup" ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" + mamask "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter" context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" - metrics "github.com/ipfs/go-ipfs/metrics" - eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog" - diag "github.com/ipfs/go-ipfs/diagnostics" + metrics "github.com/ipfs/go-ipfs/metrics" ic "github.com/ipfs/go-ipfs/p2p/crypto" discovery "github.com/ipfs/go-ipfs/p2p/discovery" p2phost "github.com/ipfs/go-ipfs/p2p/host" @@ -32,6 +32,7 @@ import ( swarm "github.com/ipfs/go-ipfs/p2p/net/swarm" addrutil "github.com/ipfs/go-ipfs/p2p/net/swarm/addr" peer "github.com/ipfs/go-ipfs/p2p/peer" + eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog" routing "github.com/ipfs/go-ipfs/routing" dht "github.com/ipfs/go-ipfs/routing/dht" @@ -254,7 +255,18 @@ func (n *IpfsNode) startOnlineServices(ctx context.Context, routingOption Routin // Set reporter n.Reporter = metrics.NewBandwidthCounter() - peerhost, err := hostOption(ctx, n.Identity, n.Peerstore, n.Reporter) + // get undialable addrs from config + cfg := n.Repo.Config() + var addrfilter []*net.IPNet + for _, s := range cfg.DialBlocklist { + f, err := mamask.NewMask(s) + if err != nil { + return fmt.Errorf("incorrectly formatter address filter in config: %s", s) + } + addrfilter = append(addrfilter, f) + } + + peerhost, err := hostOption(ctx, n.Identity, n.Peerstore, n.Reporter, addrfilter) if err != nil { return err } @@ -508,12 +520,12 @@ func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) { return listen, nil } -type HostOption func(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter) (p2phost.Host, error) +type HostOption func(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter, fs []*net.IPNet) (p2phost.Host, error) var DefaultHostOption HostOption = constructPeerHost // isolates the complex initialization steps -func constructPeerHost(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter) (p2phost.Host, error) { +func constructPeerHost(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter, fs []*net.IPNet) (p2phost.Host, error) { // no addresses to begin with. we'll start later. network, err := swarm.NewNetwork(ctx, nil, id, ps, bwr) diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go index 15a5bbddb..489d6fec3 100644 --- a/p2p/net/swarm/swarm.go +++ b/p2p/net/swarm/swarm.go @@ -4,6 +4,7 @@ package swarm import ( "fmt" + "net" "sync" "time" @@ -50,6 +51,9 @@ type Swarm struct { notifmu sync.RWMutex notifs map[inet.Notifiee]ps.Notifiee + // filters for addresses that shouldnt be dialed + filters []*net.IPNet + cg ctxgroup.ContextGroup bwc metrics.Reporter } @@ -84,6 +88,10 @@ func (s *Swarm) teardown() error { return s.swarm.Close() } +func (s *Swarm) AddDialFilter(f *net.IPNet) { + s.filters = append(s.filters, f) +} + // CtxGroup returns the Context Group of the swarm func filterAddrs(listenAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) { if len(listenAddrs) > 0 { diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go index aacee6ec4..534f916d1 100644 --- a/p2p/net/swarm/swarm_dial.go +++ b/p2p/net/swarm/swarm_dial.go @@ -303,6 +303,8 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) { ila, _ := s.InterfaceListenAddresses() remoteAddrs = addrutil.Subtract(remoteAddrs, ila) remoteAddrs = addrutil.Subtract(remoteAddrs, s.peers.Addrs(s.local)) + remoteAddrs = s.filterAddrs(remoteAddrs) + log.Debugf("%s swarm dialing %s -- local:%s remote:%s", s.local, p, s.ListenAddresses(), remoteAddrs) if len(remoteAddrs) == 0 { err := errors.New("peer has no addresses") @@ -454,6 +456,32 @@ func (s *Swarm) dialAddr(ctx context.Context, d *conn.Dialer, p peer.ID, addr ma return connC, nil } +func (s *Swarm) filterAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { + var out []ma.Multiaddr + for _, a := range addrs { + if !s.addrBlocked(a) { + out = append(out, a) + } + } + return out +} + +func (s *Swarm) addrBlocked(a ma.Multiaddr) bool { + _, addr, err := manet.DialArgs(a) + if err != nil { + // if we cant parse it, its probably not blocked + return false + } + + ip := net.ParseIP(addr) + for _, f := range s.filters { + if f.Contains(ip) { + return true + } + } + return false +} + // dialConnSetup is the setup logic for a connection from the dial side. it // needs to add the Conn to the StreamSwarm, then run newConnSetup func dialConnSetup(ctx context.Context, s *Swarm, connC conn.Conn) (*Conn, error) { diff --git a/repo/config/config.go b/repo/config/config.go index c9a8aabec..e7474cf7e 100644 --- a/repo/config/config.go +++ b/repo/config/config.go @@ -26,6 +26,7 @@ type Config struct { Tour Tour // local node's tour position Gateway Gateway // local node's gateway server options SupernodeRouting SupernodeClientConfig // local node's routing servers (if SupernodeRouting enabled) + DialBlocklist []string Log Log } diff --git a/util/sadhack/godep.go b/util/sadhack/godep.go index c38bbb1e4..47a2350bb 100644 --- a/util/sadhack/godep.go +++ b/util/sadhack/godep.go @@ -6,4 +6,5 @@ import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-hum // similar to the above, only used in the tests makefile import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/whyrusleeping/iptb" + import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/chriscool/go-sleep" From fbab2a727320af83c45a9f81bf10c16a1a02d062 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Wed, 17 Jun 2015 09:53:12 -0700 Subject: [PATCH 2/3] broke filters out into a struct License: MIT Signed-off-by: Jeromy --- p2p/net/swarm/swarm.go | 42 ++++++++++++++++++++++++++++--------- p2p/net/swarm/swarm_dial.go | 18 +--------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go index 489d6fec3..814fc7157 100644 --- a/p2p/net/swarm/swarm.go +++ b/p2p/net/swarm/swarm.go @@ -16,6 +16,7 @@ import ( ctxgroup "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup" ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" + manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" ps "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream" pst "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport" psy "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/yamux" @@ -52,7 +53,7 @@ type Swarm struct { notifs map[inet.Notifiee]ps.Notifiee // filters for addresses that shouldnt be dialed - filters []*net.IPNet + Filters *Filters cg ctxgroup.ContextGroup bwc metrics.Reporter @@ -68,13 +69,14 @@ func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr, } s := &Swarm{ - swarm: ps.NewSwarm(PSTransport), - local: local, - peers: peers, - cg: ctxgroup.WithContext(ctx), - dialT: DialTimeout, - notifs: make(map[inet.Notifiee]ps.Notifiee), - bwc: bwc, + swarm: ps.NewSwarm(PSTransport), + local: local, + peers: peers, + cg: ctxgroup.WithContext(ctx), + dialT: DialTimeout, + notifs: make(map[inet.Notifiee]ps.Notifiee), + bwc: bwc, + Filters: new(Filters), } // configure Swarm @@ -88,8 +90,28 @@ func (s *Swarm) teardown() error { return s.swarm.Close() } -func (s *Swarm) AddDialFilter(f *net.IPNet) { - s.filters = append(s.filters, f) +type Filters struct { + filters []*net.IPNet +} + +func (fs *Filters) AddDialFilter(f *net.IPNet) { + fs.filters = append(fs.filters, f) +} + +func (f *Filters) AddrBlocked(a ma.Multiaddr) bool { + _, addr, err := manet.DialArgs(a) + if err != nil { + // if we cant parse it, its probably not blocked + return false + } + + ip := net.ParseIP(addr) + for _, ft := range f.filters { + if ft.Contains(ip) { + return true + } + } + return false } // CtxGroup returns the Context Group of the swarm diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go index 534f916d1..4fe2bc126 100644 --- a/p2p/net/swarm/swarm_dial.go +++ b/p2p/net/swarm/swarm_dial.go @@ -459,29 +459,13 @@ func (s *Swarm) dialAddr(ctx context.Context, d *conn.Dialer, p peer.ID, addr ma func (s *Swarm) filterAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { var out []ma.Multiaddr for _, a := range addrs { - if !s.addrBlocked(a) { + if !s.Filters.AddrBlocked(a) { out = append(out, a) } } return out } -func (s *Swarm) addrBlocked(a ma.Multiaddr) bool { - _, addr, err := manet.DialArgs(a) - if err != nil { - // if we cant parse it, its probably not blocked - return false - } - - ip := net.ParseIP(addr) - for _, f := range s.filters { - if f.Contains(ip) { - return true - } - } - return false -} - // dialConnSetup is the setup logic for a connection from the dial side. it // needs to add the Conn to the StreamSwarm, then run newConnSetup func dialConnSetup(ctx context.Context, s *Swarm, connC conn.Conn) (*Conn, error) { From 0bf6b39cafda5fb243f8ae3c909650077c6ecab3 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Wed, 17 Jun 2015 16:26:45 -0700 Subject: [PATCH 3/3] filter incoming connections and add a test of functionality - add extra check to dialblock test - move filter to separate package - also improved tests - sunk filters down into p2p/net/conn/listener License: MIT Signed-off-by: Jeromy Signed-off-by: Juan Batiz-Benet --- p2p/net/conn/interface.go | 3 ++ p2p/net/conn/listen.go | 13 ++++++++ p2p/net/filter/filter.go | 34 ++++++++++++++++++++ p2p/net/swarm/swarm.go | 31 ++----------------- p2p/net/swarm/swarm_dial.go | 8 ++++- p2p/net/swarm/swarm_listen.go | 2 ++ p2p/net/swarm/swarm_test.go | 58 +++++++++++++++++++++++++++++++++++ 7 files changed, 120 insertions(+), 29 deletions(-) create mode 100644 p2p/net/filter/filter.go diff --git a/p2p/net/conn/interface.go b/p2p/net/conn/interface.go index 7d2c95af1..3a61911af 100644 --- a/p2p/net/conn/interface.go +++ b/p2p/net/conn/interface.go @@ -7,6 +7,7 @@ import ( key "github.com/ipfs/go-ipfs/blocks/key" ic "github.com/ipfs/go-ipfs/p2p/crypto" + filter "github.com/ipfs/go-ipfs/p2p/net/filter" peer "github.com/ipfs/go-ipfs/p2p/peer" msgio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-msgio" @@ -86,6 +87,8 @@ type Listener interface { // LocalPeer is the identity of the local Peer. LocalPeer() peer.ID + SetAddrFilters(*filter.Filters) + // Close closes the listener. // Any blocked Accept operations will be unblocked and return errors. Close() error diff --git a/p2p/net/conn/listen.go b/p2p/net/conn/listen.go index d60c0ba3a..ea91e5a56 100644 --- a/p2p/net/conn/listen.go +++ b/p2p/net/conn/listen.go @@ -13,6 +13,7 @@ import ( context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" ic "github.com/ipfs/go-ipfs/p2p/crypto" + filter "github.com/ipfs/go-ipfs/p2p/net/filter" peer "github.com/ipfs/go-ipfs/p2p/peer" ) @@ -26,6 +27,8 @@ type listener struct { local peer.ID // LocalPeer is the identity of the local Peer privk ic.PrivKey // private key to use to initialize secure conns + filters *filter.Filters + wrapper ConnWrapper cg ctxgroup.ContextGroup @@ -45,6 +48,10 @@ func (l *listener) String() string { return fmt.Sprintf("", l.local, l.Multiaddr()) } +func (l *listener) SetAddrFilters(fs *filter.Filters) { + l.filters = fs +} + // Accept waits for and returns the next connection to the listener. // Note that unfortunately this func (l *listener) Accept() (net.Conn, error) { @@ -81,6 +88,12 @@ func (l *listener) Accept() (net.Conn, error) { } log.Debugf("listener %s got connection: %s <---> %s", l, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr()) + + if l.filters != nil && l.filters.AddrBlocked(maconn.RemoteMultiaddr()) { + log.Debugf("blocked connection from %s", maconn.RemoteMultiaddr()) + maconn.Close() + continue + } // If we have a wrapper func, wrap this conn if l.wrapper != nil { maconn = l.wrapper(maconn) diff --git a/p2p/net/filter/filter.go b/p2p/net/filter/filter.go new file mode 100644 index 000000000..1642a8b77 --- /dev/null +++ b/p2p/net/filter/filter.go @@ -0,0 +1,34 @@ +package filter + +import ( + "net" + "strings" + + ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" + manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" +) + +type Filters struct { + filters []*net.IPNet +} + +func (fs *Filters) AddDialFilter(f *net.IPNet) { + fs.filters = append(fs.filters, f) +} + +func (f *Filters) AddrBlocked(a ma.Multiaddr) bool { + _, addr, err := manet.DialArgs(a) + if err != nil { + // if we cant parse it, its probably not blocked + return false + } + + ipstr := strings.Split(addr, ":")[0] + ip := net.ParseIP(ipstr) + for _, ft := range f.filters { + if ft.Contains(ip) { + return true + } + } + return false +} diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go index 814fc7157..4fe45df85 100644 --- a/p2p/net/swarm/swarm.go +++ b/p2p/net/swarm/swarm.go @@ -4,19 +4,18 @@ package swarm import ( "fmt" - "net" "sync" "time" metrics "github.com/ipfs/go-ipfs/metrics" inet "github.com/ipfs/go-ipfs/p2p/net" + filter "github.com/ipfs/go-ipfs/p2p/net/filter" addrutil "github.com/ipfs/go-ipfs/p2p/net/swarm/addr" peer "github.com/ipfs/go-ipfs/p2p/peer" eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog" ctxgroup "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup" ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" - manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" ps "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream" pst "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport" psy "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/yamux" @@ -53,7 +52,7 @@ type Swarm struct { notifs map[inet.Notifiee]ps.Notifiee // filters for addresses that shouldnt be dialed - Filters *Filters + Filters *filter.Filters cg ctxgroup.ContextGroup bwc metrics.Reporter @@ -76,7 +75,7 @@ func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr, dialT: DialTimeout, notifs: make(map[inet.Notifiee]ps.Notifiee), bwc: bwc, - Filters: new(Filters), + Filters: new(filter.Filters), } // configure Swarm @@ -90,30 +89,6 @@ func (s *Swarm) teardown() error { return s.swarm.Close() } -type Filters struct { - filters []*net.IPNet -} - -func (fs *Filters) AddDialFilter(f *net.IPNet) { - fs.filters = append(fs.filters, f) -} - -func (f *Filters) AddrBlocked(a ma.Multiaddr) bool { - _, addr, err := manet.DialArgs(a) - if err != nil { - // if we cant parse it, its probably not blocked - return false - } - - ip := net.ParseIP(addr) - for _, ft := range f.filters { - if ft.Contains(ip) { - return true - } - } - return false -} - // CtxGroup returns the Context Group of the swarm func filterAddrs(listenAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) { if len(listenAddrs) > 0 { diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go index 4fe2bc126..c969ca570 100644 --- a/p2p/net/swarm/swarm_dial.go +++ b/p2p/net/swarm/swarm_dial.go @@ -303,7 +303,6 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) { ila, _ := s.InterfaceListenAddresses() remoteAddrs = addrutil.Subtract(remoteAddrs, ila) remoteAddrs = addrutil.Subtract(remoteAddrs, s.peers.Addrs(s.local)) - remoteAddrs = s.filterAddrs(remoteAddrs) log.Debugf("%s swarm dialing %s -- local:%s remote:%s", s.local, p, s.ListenAddresses(), remoteAddrs) if len(remoteAddrs) == 0 { @@ -312,6 +311,13 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) { return nil, err } + remoteAddrs = s.filterAddrs(remoteAddrs) + if len(remoteAddrs) == 0 { + err := errors.New("all adresses for peer have been filtered out") + logdial["error"] = err + return nil, err + } + // open connection to peer d := &conn.Dialer{ Dialer: manet.Dialer{ diff --git a/p2p/net/swarm/swarm_listen.go b/p2p/net/swarm/swarm_listen.go index 2a985763f..4a8f4dd4d 100644 --- a/p2p/net/swarm/swarm_listen.go +++ b/p2p/net/swarm/swarm_listen.go @@ -69,6 +69,8 @@ func (s *Swarm) setupListener(maddr ma.Multiaddr) error { return err } + list.SetAddrFilters(s.Filters) + if cw, ok := list.(conn.ListenerConnWrapper); ok { cw.SetConnWrapper(func(c manet.Conn) manet.Conn { return mconn.WrapConn(s.bwc, c) diff --git a/p2p/net/swarm/swarm_test.go b/p2p/net/swarm/swarm_test.go index 9aa825320..4c12a1b5d 100644 --- a/p2p/net/swarm/swarm_test.go +++ b/p2p/net/swarm/swarm_test.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io" + "net" "sync" "testing" "time" @@ -270,3 +271,60 @@ func TestConnHandler(t *testing.T) { default: } } + +func TestAddrBlocking(t *testing.T) { + ctx := context.Background() + swarms := makeSwarms(ctx, t, 2) + + swarms[0].SetConnHandler(func(conn *Conn) { + t.Fatal("no connections should happen!") + }) + + _, block, err := net.ParseCIDR("127.0.0.1/8") + if err != nil { + t.Fatal(err) + } + + swarms[1].Filters.AddDialFilter(block) + + swarms[1].peers.AddAddr(swarms[0].LocalPeer(), swarms[0].ListenAddresses()[0], peer.PermanentAddrTTL) + _, err = swarms[1].Dial(context.TODO(), swarms[0].LocalPeer()) + if err == nil { + t.Fatal("dial should have failed") + } + + swarms[0].peers.AddAddr(swarms[1].LocalPeer(), swarms[1].ListenAddresses()[0], peer.PermanentAddrTTL) + _, err = swarms[0].Dial(context.TODO(), swarms[1].LocalPeer()) + if err == nil { + t.Fatal("dial should have failed") + } +} + +func TestFilterBounds(t *testing.T) { + ctx := context.Background() + swarms := makeSwarms(ctx, t, 2) + + conns := make(chan struct{}, 8) + swarms[0].SetConnHandler(func(conn *Conn) { + conns <- struct{}{} + }) + + // Address that we wont be dialing from + _, block, err := net.ParseCIDR("192.0.0.1/8") + if err != nil { + t.Fatal(err) + } + + // set filter on both sides, shouldnt matter + swarms[1].Filters.AddDialFilter(block) + swarms[0].Filters.AddDialFilter(block) + + connectSwarms(t, ctx, swarms) + + select { + case <-time.After(time.Second): + t.Fatal("should have gotten connection") + case <-conns: + fmt.Println("got connect") + } +}