mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-22 02:47:48 +08:00
commit
d303ff45f8
@ -3,12 +3,15 @@ package conn
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
handshake "github.com/jbenet/go-ipfs/net/handshake"
|
||||
hspb "github.com/jbenet/go-ipfs/net/handshake/pb"
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
|
||||
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||
proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
)
|
||||
|
||||
// Handshake1 exchanges local and remote versions and compares them
|
||||
@ -65,6 +68,10 @@ func Handshake3(ctx context.Context, c Conn) error {
|
||||
|
||||
var remoteH, localH *hspb.Handshake3
|
||||
localH = handshake.Handshake3Msg(lpeer)
|
||||
|
||||
rma := c.RemoteMultiaddr()
|
||||
localH.ObservedAddr = proto.String(rma.String())
|
||||
|
||||
localB, err := proto.Marshal(localH)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -99,5 +106,43 @@ func Handshake3(ctx context.Context, c Conn) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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
|
||||
}
|
||||
|
||||
// checkNAT returns whether or not we might be behind a NAT
|
||||
func checkNAT(observedaddr string) (bool, error) {
|
||||
observedma, err := ma.NewMultiaddr(observedaddr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
addrs, err := u.GetLocalAddresses()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
omastr := observedma.String()
|
||||
for _, addr := range addrs {
|
||||
if strings.HasPrefix(omastr, addr.String()) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -14,15 +14,11 @@ It has these top-level messages:
|
||||
*/
|
||||
package handshake_pb
|
||||
|
||||
import proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/gogoprotobuf/proto"
|
||||
import json "encoding/json"
|
||||
import proto "code.google.com/p/gogoprotobuf/proto"
|
||||
import math "math"
|
||||
|
||||
// discarding unused import mux "github.com/jbenet/go-ipfs/net/mux/mux.pb"
|
||||
|
||||
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = &json.SyntaxError{}
|
||||
var _ = math.Inf
|
||||
|
||||
// Handshake1 is delivered _before_ the secure channel is initialized
|
||||
@ -56,8 +52,10 @@ func (m *Handshake1) GetAgentVersion() string {
|
||||
// Handshake3 is delivered _after_ the secure channel is initialized
|
||||
type Handshake3 struct {
|
||||
// listenAddrs are the multiaddrs this node listens for open connections on
|
||||
ListenAddrs [][]byte `protobuf:"bytes,2,rep,name=listenAddrs" json:"listenAddrs,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
ListenAddrs [][]byte `protobuf:"bytes,2,rep,name=listenAddrs" json:"listenAddrs,omitempty"`
|
||||
// we'll have more fields here later.
|
||||
ObservedAddr *string `protobuf:"bytes,4,opt,name=observedAddr" json:"observedAddr,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Handshake3) Reset() { *m = Handshake3{} }
|
||||
@ -71,5 +69,12 @@ func (m *Handshake3) GetListenAddrs() [][]byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Handshake3) GetObservedAddr() string {
|
||||
if m != nil && m.ObservedAddr != nil {
|
||||
return *m.ObservedAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package handshake.pb;
|
||||
|
||||
import "github.com/jbenet/go-ipfs/net/mux/mux.proto";
|
||||
//import "github.com/jbenet/go-ipfs/net/mux/mux.proto";
|
||||
|
||||
// Handshake1 is delivered _before_ the secure channel is initialized
|
||||
message Handshake1 {
|
||||
@ -30,4 +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;
|
||||
}
|
||||
|
||||
@ -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 the zero 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
|
||||
|
||||
58
util/util.go
58
util/util.go
@ -4,12 +4,16 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
|
||||
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
||||
manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
@ -107,3 +111,57 @@ func GetenvBool(name string) bool {
|
||||
v := strings.ToLower(os.Getenv(name))
|
||||
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"}
|
||||
for _, loop := range loops {
|
||||
if strings.HasPrefix(addr, loop) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
var maddrs []ma.Multiaddr
|
||||
for _, i := range ifaces {
|
||||
addrs, err := i.Addrs()
|
||||
if err != nil {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
return maddrs, nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user