@cryptotaxi247 / kubo / commits / e01f8e4f2

add in basic address dial filtering

License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>

Jeromy committed Jun 16, 2015 at 11:06 UTC e01f8e4f22a929b69daaaadeda730dc6f3d05d5d
8 files changed +115 -6
Godeps/Godeps.json
+4
@@ -239,6 +239,10 @@
239 "ImportPath": "github.com/whyrusleeping/iptb",
240 "Rev": "3970c95a864f1a40037f796ff596607ce8ae43be"
241 },
242 + {
243 + "ImportPath": "github.com/whyrusleeping/multiaddr-filter",
244 + "Rev": "15837fcc356fddef27c634b0f6379b3b7f259114"
245 + },
246 {
247 "ImportPath": "golang.org/x/crypto/blowfish",
248 "Rev": "c84e1f8e3a7e322d497cd16c0e8a13c7e127baf3"
Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask.go new
+19
@@ -0,0 +1,19 @@
1 +package mask
2 +
3 +import (
4 + "errors"
5 + "net"
6 + "strings"
7 +)
8 +
9 +func NewMask(a string) (*net.IPNet, error) {
10 + parts := strings.Split(a, "/")
11 + if len(parts) == 5 && parts[1] == "ip4" && parts[3] == "ipcidr" {
12 + _, ipn, err := net.ParseCIDR(parts[2] + "/" + parts[4])
13 + if err != nil {
14 + return nil, err
15 + }
16 + return ipn, nil
17 + }
18 + return nil, errors.New("invalid format")
19 +}
Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter/mask_test.go new
+36
@@ -0,0 +1,36 @@
1 +package mask
2 +
3 +import (
4 + "net"
5 + "testing"
6 +)
7 +
8 +func TestFiltered(t *testing.T) {
9 + var tests = map[string]map[string]bool{
10 + "/ip4/10.0.0.0/ipcidr/8": map[string]bool{
11 + "10.3.3.4": true,
12 + "10.3.4.4": true,
13 + "10.4.4.4": true,
14 + "15.52.34.3": false,
15 + },
16 + "/ip4/192.168.0.0/ipcidr/16": map[string]bool{
17 + "192.168.0.0": true,
18 + "192.168.1.0": true,
19 + "192.1.0.0": false,
20 + "10.4.4.4": false,
21 + },
22 + }
23 +
24 + for mask, set := range tests {
25 + m, err := NewMask(mask)
26 + if err != nil {
27 + t.Fatal(err)
28 + }
29 + for addr, val := range set {
30 + ip := net.ParseIP(addr)
31 + if m.Contains(ip) != val {
32 + t.Fatalf("expected contains(%s, %s) == %s", mask, addr, val)
33 + }
34 + }
35 + }
36 +}
core/core.go
+18 -6
@@ -13,17 +13,17 @@ import (
13 "errors"
14 "fmt"
15 "io"
16 + "net"
17 "time"
18
19 b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
20 ctxgroup "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
21 ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
22 ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
23 + mamask "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter"
24 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
23 - metrics "github.com/ipfs/go-ipfs/metrics"
24 - eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
25 -
25 diag "github.com/ipfs/go-ipfs/diagnostics"
26 + metrics "github.com/ipfs/go-ipfs/metrics"
27 ic "github.com/ipfs/go-ipfs/p2p/crypto"
28 discovery "github.com/ipfs/go-ipfs/p2p/discovery"
29 p2phost "github.com/ipfs/go-ipfs/p2p/host"
@@ -32,6 +32,7 @@ import (
32 swarm "github.com/ipfs/go-ipfs/p2p/net/swarm"
33 addrutil "github.com/ipfs/go-ipfs/p2p/net/swarm/addr"
34 peer "github.com/ipfs/go-ipfs/p2p/peer"
35 + eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
36
37 routing "github.com/ipfs/go-ipfs/routing"
38 dht "github.com/ipfs/go-ipfs/routing/dht"
@@ -254,7 +255,18 @@ func (n *IpfsNode) startOnlineServices(ctx context.Context, routingOption Routin
255 // Set reporter
256 n.Reporter = metrics.NewBandwidthCounter()
257
257 - peerhost, err := hostOption(ctx, n.Identity, n.Peerstore, n.Reporter)
258 + // get undialable addrs from config
259 + cfg := n.Repo.Config()
260 + var addrfilter []*net.IPNet
261 + for _, s := range cfg.DialBlocklist {
262 + f, err := mamask.NewMask(s)
263 + if err != nil {
264 + return fmt.Errorf("incorrectly formatter address filter in config: %s", s)
265 + }
266 + addrfilter = append(addrfilter, f)
267 + }
268 +
269 + peerhost, err := hostOption(ctx, n.Identity, n.Peerstore, n.Reporter, addrfilter)
270 if err != nil {
271 return err
272 }
@@ -508,12 +520,12 @@ func listenAddresses(cfg *config.Config) ([]ma.Multiaddr, error) {
520 return listen, nil
521 }
522
511 -type HostOption func(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter) (p2phost.Host, error)
523 +type HostOption func(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter, fs []*net.IPNet) (p2phost.Host, error)
524
525 var DefaultHostOption HostOption = constructPeerHost
526
527 // isolates the complex initialization steps
516 -func constructPeerHost(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter) (p2phost.Host, error) {
528 +func constructPeerHost(ctx context.Context, id peer.ID, ps peer.Peerstore, bwr metrics.Reporter, fs []*net.IPNet) (p2phost.Host, error) {
529
530 // no addresses to begin with. we'll start later.
531 network, err := swarm.NewNetwork(ctx, nil, id, ps, bwr)
p2p/net/swarm/swarm.go
+8
@@ -4,6 +4,7 @@ package swarm
4
5 import (
6 "fmt"
7 + "net"
8 "sync"
9 "time"
10
@@ -50,6 +51,9 @@ type Swarm struct {
51 notifmu sync.RWMutex
52 notifs map[inet.Notifiee]ps.Notifiee
53
54 + // filters for addresses that shouldnt be dialed
55 + filters []*net.IPNet
56 +
57 cg ctxgroup.ContextGroup
58 bwc metrics.Reporter
59 }
@@ -84,6 +88,10 @@ func (s *Swarm) teardown() error {
88 return s.swarm.Close()
89 }
90
91 +func (s *Swarm) AddDialFilter(f *net.IPNet) {
92 + s.filters = append(s.filters, f)
93 +}
94 +
95 // CtxGroup returns the Context Group of the swarm
96 func filterAddrs(listenAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
97 if len(listenAddrs) > 0 {
p2p/net/swarm/swarm_dial.go
+28
@@ -303,6 +303,8 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
303 ila, _ := s.InterfaceListenAddresses()
304 remoteAddrs = addrutil.Subtract(remoteAddrs, ila)
305 remoteAddrs = addrutil.Subtract(remoteAddrs, s.peers.Addrs(s.local))
306 + remoteAddrs = s.filterAddrs(remoteAddrs)
307 +
308 log.Debugf("%s swarm dialing %s -- local:%s remote:%s", s.local, p, s.ListenAddresses(), remoteAddrs)
309 if len(remoteAddrs) == 0 {
310 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
456 return connC, nil
457 }
458
459 +func (s *Swarm) filterAddrs(addrs []ma.Multiaddr) []ma.Multiaddr {
460 + var out []ma.Multiaddr
461 + for _, a := range addrs {
462 + if !s.addrBlocked(a) {
463 + out = append(out, a)
464 + }
465 + }
466 + return out
467 +}
468 +
469 +func (s *Swarm) addrBlocked(a ma.Multiaddr) bool {
470 + _, addr, err := manet.DialArgs(a)
471 + if err != nil {
472 + // if we cant parse it, its probably not blocked
473 + return false
474 + }
475 +
476 + ip := net.ParseIP(addr)
477 + for _, f := range s.filters {
478 + if f.Contains(ip) {
479 + return true
480 + }
481 + }
482 + return false
483 +}
484 +
485 // dialConnSetup is the setup logic for a connection from the dial side. it
486 // needs to add the Conn to the StreamSwarm, then run newConnSetup
487 func dialConnSetup(ctx context.Context, s *Swarm, connC conn.Conn) (*Conn, error) {
repo/config/config.go
+1
@@ -26,6 +26,7 @@ type Config struct {
26 Tour Tour // local node's tour position
27 Gateway Gateway // local node's gateway server options
28 SupernodeRouting SupernodeClientConfig // local node's routing servers (if SupernodeRouting enabled)
29 + DialBlocklist []string
30 Log Log
31 }
32
util/sadhack/godep.go
+1
@@ -6,4 +6,5 @@ import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-hum
6
7 // similar to the above, only used in the tests makefile
8 import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/whyrusleeping/iptb"
9 +
10 import _ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/chriscool/go-sleep"