From: yahtoo Date: Wed, 27 Mar 2019 03:19:36 +0000 (+0800) Subject: Change get external ip method (#1649) X-Git-Tag: 2.0.0-alpha~88^2~6 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b87552f006c55e36877f54e429d6900bcf161af2;hp=9890f9355542f524bc19f7b29fe19b29e49914ad;p=bytom%2Fbytom.git Change get external ip method (#1649) * Change get external ip method * Add test info * opz code format * Opz address display * Fix review bug * Change cmn.PanicCrisis to log.Panic --- diff --git a/p2p/connection/secret_connection.go b/p2p/connection/secret_connection.go index 63d135b6..69d175ea 100644 --- a/p2p/connection/secret_connection.go +++ b/p2p/connection/secret_connection.go @@ -10,6 +10,7 @@ import ( "net" "time" + log "github.com/sirupsen/logrus" "golang.org/x/crypto/nacl/box" "golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/ripemd160" @@ -213,7 +214,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) { var err error ephPub, ephPriv, err = box.GenerateKey(crand.Reader) if err != nil { - cmn.PanicCrisis("Could not generate ephemeral keypairs") + log.Panic("Could not generate ephemeral keypairs") } return } diff --git a/p2p/external_ip.go b/p2p/external_ip.go new file mode 100644 index 00000000..5c2c90cf --- /dev/null +++ b/p2p/external_ip.go @@ -0,0 +1,47 @@ +package p2p + +import ( + "net" +) + +// ExternalIPv4 returns the first IPv4 available. +func ExternalIPv4() (string, error) { + ifaces, err := net.Interfaces() + if err != nil { + return "", err + } + + for _, iface := range ifaces { + // interface down + if iface.Flags&net.FlagUp == 0 { + continue + } + // loopback interface + if iface.Flags&net.FlagLoopback != 0 { + continue + } + addrs, err := iface.Addrs() + if err != nil { + return "", err + } + + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + continue // not an ipv4 address + } + return ip.String(), nil + } + } + return "127.0.0.1", nil +} diff --git a/p2p/external_ip_test.go b/p2p/external_ip_test.go new file mode 100644 index 00000000..18601fec --- /dev/null +++ b/p2p/external_ip_test.go @@ -0,0 +1,22 @@ +package p2p + +import ( + "regexp" + "testing" +) + +func TestExternalIPv4(t *testing.T) { + // Regular expression format for IPv4 + IPv4Format := `\.\d{1,3}\.\d{1,3}\b` + test, err := ExternalIPv4() + + if err != nil { + t.Errorf("Test check external ipv4 failed with %v", err) + } + + valid := regexp.MustCompile(IPv4Format) + + if !valid.MatchString(test) { + t.Errorf("Wanted: %v, got: %v", IPv4Format, test) + } +} diff --git a/p2p/listener.go b/p2p/listener.go index 204b686b..d7a11998 100644 --- a/p2p/listener.go +++ b/p2p/listener.go @@ -81,27 +81,6 @@ func getUPNPExternalAddress(externalPort, internalPort int) (*NetAddress, error) return NewNetAddressIPPort(ext, uint16(externalPort)), nil } -func getNaiveExternalAddress(port int, settleForLocal bool) *NetAddress { - addrs, err := net.InterfaceAddrs() - if err != nil { - cmn.PanicCrisis(cmn.Fmt("Could not fetch interface addresses: %v", err)) - } - - for _, a := range addrs { - ipnet, ok := a.(*net.IPNet) - if !ok { - continue - } - if v4 := ipnet.IP.To4(); v4 == nil || (!settleForLocal && v4[0] == 127) { - continue - } - return NewNetAddressIPPort(ipnet.IP, uint16(port)) - } - - log.Info("Node may not be connected to internet. Settling for local address") - return getNaiveExternalAddress(port, true) -} - func splitHostPort(addr string) (host string, port int) { host, portStr, err := net.SplitHostPort(addr) if err != nil { @@ -135,12 +114,12 @@ func NewDefaultListener(protocol string, lAddr string, skipUPNP bool) (Listener, listener, err = net.Listen(protocol, lAddr) } if err != nil { - cmn.PanicCrisis(err) + log.Panic(err) } intAddr, err := NewNetAddressString(lAddr) if err != nil { - cmn.PanicCrisis(err) + log.Panic(err) } // Actual listener local IP & port @@ -156,17 +135,16 @@ func NewDefaultListener(protocol string, lAddr string, skipUPNP bool) (Listener, log.WithFields(log.Fields{"module": logModule, "err": err}).Info("get UPNP external address") } + // Get the IPv4 available if extAddr == nil { - if address := GetIP(); address.Success == true { - extAddr = NewNetAddressIPPort(net.ParseIP(address.IP), uint16(lAddrPort)) + if ip, err := ExternalIPv4(); err != nil { + log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("get ipv4 external address") + log.Panic("get ipv4 external address fail!") + } else { + extAddr = NewNetAddressIPPort(net.ParseIP(ip), uint16(lAddrPort)) + log.WithFields(log.Fields{"module": logModule, "addr": extAddr}).Info("get ipv4 external address success") } } - if extAddr == nil { - extAddr = getNaiveExternalAddress(listenerPort, false) - } - if extAddr == nil { - cmn.PanicCrisis("could not determine external address!") - } dl := &DefaultListener{ listener: listener, @@ -211,7 +189,7 @@ func (l *DefaultListener) listenRoutine() { // listener wasn't stopped, // yet we encountered an error. if err != nil { - cmn.PanicCrisis(err) + log.Panic(err) } l.connections <- conn } diff --git a/p2p/peer.go b/p2p/peer.go index 157af7b0..87c159aa 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -156,7 +156,7 @@ func (pc *peerConn) HandshakeTimeout(ourNodeInfo *NodeInfo, timeout time.Duratio func() { var n int wire.ReadBinary(peerNodeInfo, pc.conn, maxNodeInfoSize, &n, &err2) - log.WithFields(log.Fields{"module": logModule, "address": peerNodeInfo.ListenAddr}).Info("Peer handshake") + log.WithFields(log.Fields{"module": logModule, "address": pc.conn.RemoteAddr().String()}).Info("Peer handshake") }) if err1 != nil { return peerNodeInfo, errors.Wrap(err1, "Error during handshake/write") diff --git a/p2p/public_ip.go b/p2p/public_ip.go deleted file mode 100644 index c0395f8d..00000000 --- a/p2p/public_ip.go +++ /dev/null @@ -1,70 +0,0 @@ -package p2p - -import ( - "io/ioutil" - "net" - "net/http" - "strings" - "time" -) - -var ipCheckServices = []string{ - "http://members.3322.org/dyndns/getip", - "http://ifconfig.me/", - "http://icanhazip.com/", - "http://ifconfig.io/ip", - "http://ident.me/", - "http://whatismyip.akamai.com/", - "http://myip.dnsomatic.com/", - "http://diagnostic.opendns.com/myip", - "http://myexternalip.com/raw", -} - -// IPResult is the ip check response -type IPResult struct { - Success bool - IP string -} - -var timeout = time.Duration(5) - -// GetIP return the ip of the current host -func GetIP() *IPResult { - resultCh := make(chan *IPResult, 1) - for _, s := range ipCheckServices { - go ipAddress(s, resultCh) - } - - for { - select { - case result := <-resultCh: - return result - case <-time.After(time.Second * timeout): - return &IPResult{false, ""} - } - } -} - -func ipAddress(service string, done chan<- *IPResult) { - client := http.Client{Timeout: time.Duration(timeout * time.Second)} - resp, err := client.Get(service) - if err != nil { - return - } - - defer resp.Body.Close() - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return - } - - address := strings.TrimSpace(string(data)) - if ip := net.ParseIP(address); ip != nil && ip.To4() != nil { - select { - case done <- &IPResult{true, address}: - return - default: - return - } - } -}