From 402fdd2db9ded7ef5811b6e8a7f57dfd22b433f5 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Mon, 3 Nov 2014 01:45:45 +0000 Subject: [PATCH] changes from PR --- net/conn/dial.go | 5 ----- net/conn/handshake.go | 16 +++++++++++++--- net/handshake/pb/handshake.proto | 4 ++++ net/swarm/swarm.go | 11 +++++++++++ util/util.go | 11 +++++++++++ 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/net/conn/dial.go b/net/conn/dial.go index dcb196bf5..7b9c1dc86 100644 --- a/net/conn/dial.go +++ b/net/conn/dial.go @@ -8,7 +8,6 @@ import ( manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net" peer "github.com/jbenet/go-ipfs/peer" - "github.com/jbenet/go-ipfs/util" ) // Dial connects to a particular peer, over a given network @@ -24,10 +23,6 @@ func (d *Dialer) Dial(ctx context.Context, network string, remote peer.Peer) (Co return nil, fmt.Errorf("No remote address for network %s", network) } - if util.IsLoopbackAddr(raddr.String()) { - return nil, fmt.Errorf("Attempted to connect to loopback address: %s", raddr) - } - remote, err := d.Peerstore.Add(remote) if err != nil { log.Errorf("Error putting peer into peerstore: %s", remote) diff --git a/net/conn/handshake.go b/net/conn/handshake.go index 1d4e63cd3..61e6d183a 100644 --- a/net/conn/handshake.go +++ b/net/conn/handshake.go @@ -106,18 +106,28 @@ func Handshake3(ctx context.Context, c Conn) error { return err } - nat, err := CheckNAT(remoteH.GetObservedAddr()) + // If we are behind a NAT, inform the user that certain things might not work yet + nat, err := checkNAT(remoteH.GetObservedAddr()) if err != nil { log.Errorf("Error in NAT detection: %s", err) } if nat { - log.Warning("We are probably behind a NAT!") + msg := `Remote peer observed our address to be: %s + The local addresses are: %s + Thus, connection is going through NAT, and other connections may fail. + + IPFS NAT traversal is still under development. Please bug us on github or irc to fix this. + Baby steps: http://jbenet.static.s3.amazonaws.com/271dfcf/baby-steps.gif + ` + addrs, _ := u.GetLocalAddresses() + log.Warning(fmt.Sprintf(msg, remoteH.GetObservedAddr(), addrs)) } return nil } -func CheckNAT(obsaddr string) (bool, error) { +// checkNAT returns whether or not we might be behind a NAT +func checkNAT(obsaddr string) (bool, error) { oma, err := ma.NewMultiaddr(obsaddr) if err != nil { return false, err diff --git a/net/handshake/pb/handshake.proto b/net/handshake/pb/handshake.proto index 1e795d881..789c9dbbb 100644 --- a/net/handshake/pb/handshake.proto +++ b/net/handshake/pb/handshake.proto @@ -30,5 +30,9 @@ message Handshake3 { // repeated mux.ProtocolID services = 3; // we'll have more fields here later. + + // oservedAddr is the multiaddr of the remote endpoint that the local node perceives + // this is useful information to convey to the other side, as it helps the remote endpoint + // determine whether its connection to the local peer goes through NAT. optional string observedAddr = 4; } diff --git a/net/swarm/swarm.go b/net/swarm/swarm.go index 2d73a86f6..1f1996afd 100644 --- a/net/swarm/swarm.go +++ b/net/swarm/swarm.go @@ -3,6 +3,7 @@ package swarm import ( "errors" "fmt" + "strings" "sync" conn "github.com/jbenet/go-ipfs/net/conn" @@ -127,6 +128,16 @@ func (s *Swarm) Dial(peer peer.Peer) (conn.Conn, error) { Peerstore: s.peers, } + // If we are attempting to connect to a loopback addr, fail out early + raddr := peer.NetAddress("tcp") + if raddr == nil { + return nil, fmt.Errorf("No remote address for network tcp") + } + + if strings.HasPrefix(raddr.String(), "/ip4/0.0.0.0") { + return nil, fmt.Errorf("Attempted to connect to loopback address: %s", raddr) + } + c, err = d.Dial(s.Context(), "tcp", peer) if err != nil { return nil, err diff --git a/util/util.go b/util/util.go index 81b143057..68109f03f 100644 --- a/util/util.go +++ b/util/util.go @@ -112,6 +112,8 @@ func GetenvBool(name string) bool { return v == "true" || v == "t" || v == "1" } +// IsLoopbackAddr returns whether or not the ip portion of the passed in multiaddr +// string is a loopback address func IsLoopbackAddr(addr string) bool { loops := []string{"/ip4/127.0.0.1", "/ip6/::1", "/ip4/0.0.0.0"} for _, loop := range loops { @@ -122,7 +124,10 @@ func IsLoopbackAddr(addr string) bool { return false } +// GetLocalAddresses returns a list of ip addresses associated with +// the local machine func GetLocalAddresses() ([]ma.Multiaddr, error) { + // Enumerate interfaces on this machine ifaces, err := net.Interfaces() if err != nil { return nil, err @@ -135,19 +140,25 @@ func GetLocalAddresses() ([]ma.Multiaddr, error) { log.Warningf("Skipping addr: %s", err) continue } + // Check each address and convert to a multiaddr for _, addr := range addrs { switch v := addr.(type) { case *net.IPNet: + + // Build multiaddr maddr, err := manet.FromIP(v.IP) if err != nil { log.Errorf("maddr parsing error: %s", err) continue } + + // Dont list loopback addresses if IsLoopbackAddr(maddr.String()) { continue } maddrs = append(maddrs, maddr) default: + // Not sure if any other types will show up here log.Errorf("Got '%s' type = '%s'", v, reflect.TypeOf(v)) } }