From 647599e87fb47ceb16d70441d58a7802a131c58a Mon Sep 17 00:00:00 2001 From: Nishant Das Date: Wed, 22 Jul 2020 23:44:17 +0800 Subject: [PATCH] fix for virtual networks (#6676) --- beacon-chain/p2p/discovery.go | 43 +++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/beacon-chain/p2p/discovery.go b/beacon-chain/p2p/discovery.go index 3c72c7cf9f..702a5614a3 100644 --- a/beacon-chain/p2p/discovery.go +++ b/beacon-chain/p2p/discovery.go @@ -5,6 +5,7 @@ import ( "crypto/ecdsa" "fmt" "net" + "strconv" "time" "github.com/ethereum/go-ethereum/p2p/discover" @@ -98,10 +99,6 @@ func (s *Service) createListener( ipAddr net.IP, privKey *ecdsa.PrivateKey, ) (*discover.UDPv5, error) { - udpAddr := &net.UDPAddr{ - IP: ipAddr, - Port: int(s.cfg.UDPPort), - } // assume ip is either ipv4 or ipv6 networkVersion := "" if ipAddr.To4() != nil { @@ -109,6 +106,13 @@ func (s *Service) createListener( } else { networkVersion = "udp6" } + // Check for the real local address which may + // be different in the presence of virtual networks. + ipAddr = s.localAddress(networkVersion, ipAddr) + udpAddr := &net.UDPAddr{ + IP: ipAddr, + Port: int(s.cfg.UDPPort), + } conn, err := net.ListenUDP(networkVersion, udpAddr) if err != nil { return nil, errors.Wrap(err, "could not listen to UDP") @@ -251,6 +255,37 @@ func (s *Service) isPeerAtLimit() bool { return activePeers >= maxPeers || numOfConns >= maxPeers } +// retrieve real local address of the node. In the event +// that is not possible we return the provided ip. +func (s *Service) localAddress(network string, addr net.IP) net.IP { + if len(s.cfg.BootstrapNodeAddr) == 0 { + return addr + } + // Dial the first bootnode to determine our 'real' local address. + bootNode, err := enode.Parse(enode.ValidSchemes, s.cfg.BootstrapNodeAddr[0]) + if err != nil { + log.Error("Could not parse bootnode address") + return addr + } + conn, err := net.DialTimeout(network, net.JoinHostPort(bootNode.IP().String(), strconv.Itoa(bootNode.UDP())), dialTimeout) + if err != nil { + log.Error("Could not dial remote peer") + return addr + } + defer func() { + if err := conn.Close(); err != nil { + log.Error(err) + } + }() + // Determine the real address from which the initial connection was made. + realAddr, _, err := net.SplitHostPort(conn.LocalAddr().String()) + if err != nil { + log.Error("Could not dial remote peer") + return addr + } + return net.ParseIP(realAddr) +} + func parseBootStrapAddrs(addrs []string) (discv5Nodes []string) { discv5Nodes, _ = parseGenericAddrs(addrs) if len(discv5Nodes) == 0 {