From 5460704233f52d919696f0eee14f118ea0c1d12e Mon Sep 17 00:00:00 2001 From: pingke Date: Mon, 4 Dec 2023 17:42:35 +0800 Subject: [PATCH 1/7] Add nat mapping --- ethstorage/p2p/discovery.go | 51 +++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index dced38ab..7380b707 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -23,6 +23,7 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/net/nat" "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr" ) @@ -49,6 +50,20 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, // use the geth curve definition. Same crypto, but geth needs to detect it as *their* definition of the curve. priv.Curve = gcrypto.S256() localNode := enode.NewLocalNode(conf.DiscoveryDB, priv) + if conf.AdvertiseUDPPort != 0 { // explicitly advertised port gets priority + localNode.SetFallbackUDP(int(conf.AdvertiseUDPPort)) + } else if conf.ListenUDPPort != 0 { // otherwise default to the port we configured it to listen on + localNode.SetFallbackUDP(int(conf.ListenUDPPort)) + } + if conf.AdvertiseTCPPort != 0 { // explicitly advertised port gets priority + localNode.Set(enr.TCP(conf.AdvertiseTCPPort)) + } else if tcpPort != 0 { // otherwise try to pick up whatever port LibP2P binded to (listen port, or dynamically picked) + localNode.Set(enr.TCP(tcpPort)) + } else if conf.ListenTCPPort != 0 { // otherwise default to the port we configured it to listen on + localNode.Set(enr.TCP(conf.ListenTCPPort)) + } else { + return nil, nil, fmt.Errorf("no TCP port to put in discovery record") + } if conf.AdvertiseIP != nil { localNode.SetStaticIP(conf.AdvertiseIP) } else { @@ -62,23 +77,27 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, continue } localNode.SetStaticIP(ip) - break + goto end } - // TODO: if no external IP found, use NAT protocol to find external IP - } - if conf.AdvertiseUDPPort != 0 { // explicitly advertised port gets priority - localNode.SetFallbackUDP(int(conf.AdvertiseUDPPort)) - } else if conf.ListenUDPPort != 0 { // otherwise default to the port we configured it to listen on - localNode.SetFallbackUDP(int(conf.ListenUDPPort)) - } - if conf.AdvertiseTCPPort != 0 { // explicitly advertised port gets priority - localNode.Set(enr.TCP(conf.AdvertiseTCPPort)) - } else if tcpPort != 0 { // otherwise try to pick up whatever port LibP2P binded to (listen port, or dynamically picked) - localNode.Set(enr.TCP(tcpPort)) - } else if conf.ListenTCPPort != 0 { // otherwise default to the port we configured it to listen on - localNode.Set(enr.TCP(conf.ListenTCPPort)) - } else { - return nil, nil, fmt.Errorf("no TCP port to put in discovery record") + if n, err := nat.DiscoverNAT(context.Background()); err == nil { + if mapping, err := n.NewMapping("tcp", localNode.Node().TCP()); err == nil { + if addr, err := mapping.ExternalAddr(); err == nil { + ip := net.ParseIP(addr.String()) + port := mapping.ExternalPort() + localNode.SetStaticIP(ip) + localNode.Set(enr.TCP(port)) + log.Info("Add mapping to NAT", "external IP", addr.String(), "internal port", + mapping.InternalPort(), "external port", port) + } else { + log.Warn("Get external IP from NAT mapping fail", "error", err.Error()) + } + } else { + log.Warn("Fail to add mapping to NAT", "error", err.Error()) + } + } else { + log.Warn("No external address set to ENR as no NAT service found", "error", err.Error()) + } + end: } dat := protocol.EthStorageENRData{ ChainID: l1ChainID, From 14f5178bb0508198f13f03f138de932973c06cd8 Mon Sep 17 00:00:00 2001 From: pingke Date: Mon, 4 Dec 2023 22:22:36 +0800 Subject: [PATCH 2/7] bug fix --- ethstorage/p2p/discovery.go | 49 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index 7380b707..d812158e 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -67,6 +67,7 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, if conf.AdvertiseIP != nil { localNode.SetStaticIP(conf.AdvertiseIP) } else { + end := false for _, addr := range addrs { ipStr, err := addr.ValueForProtocol(4) if err != nil { @@ -77,27 +78,21 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, continue } localNode.SetStaticIP(ip) - goto end + end = true + break } - if n, err := nat.DiscoverNAT(context.Background()); err == nil { - if mapping, err := n.NewMapping("tcp", localNode.Node().TCP()); err == nil { - if addr, err := mapping.ExternalAddr(); err == nil { - ip := net.ParseIP(addr.String()) - port := mapping.ExternalPort() - localNode.SetStaticIP(ip) - localNode.Set(enr.TCP(port)) - log.Info("Add mapping to NAT", "external IP", addr.String(), "internal port", - mapping.InternalPort(), "external port", port) - } else { - log.Warn("Get external IP from NAT mapping fail", "error", err.Error()) - } + + if !end { + internalPort := localNode.Node().TCP() + ip, port, err := addNATMapping(internalPort) + if err == nil { + localNode.SetStaticIP(ip) + localNode.Set(enr.TCP(port)) + log.Info("Add mapping to NAT", "external IP", ip.String(), "internal port", internalPort, "external port", port) } else { - log.Warn("Fail to add mapping to NAT", "error", err.Error()) + log.Warn("", "error", err.Error()) } - } else { - log.Warn("No external address set to ENR as no NAT service found", "error", err.Error()) } - end: } dat := protocol.EthStorageENRData{ ChainID: l1ChainID, @@ -168,6 +163,26 @@ func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { return nil } +func addNATMapping(internalPort int) (net.IP, int, error) { + n, err := nat.DiscoverNAT(context.Background()) + if err != nil { + return nil, 0, fmt.Errorf("no external address set to ENR as no NAT service found: %s", err.Error()) + } + mapping, err := n.NewMapping("tcp", internalPort) + if err != nil { + return nil, 0, fmt.Errorf("fail to add mapping to NAT: %s", err.Error()) + } + addr, err := mapping.ExternalAddr() + if err != nil { + return nil, 0, fmt.Errorf("get external IP from NAT mapping fail: %s", err.Error()) + } + tcpAddr, err := net.ResolveTCPAddr("tcp", addr.String()) + if err != nil { + return nil, 0, fmt.Errorf("fail to resolve external address: %s", err.Error()) + } + return tcpAddr.IP, mapping.ExternalPort(), nil +} + func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, error) { ip := r.IP() ipScheme := "ip4" From 9774dd44c725b819c4c67c662055e63f8531a65b Mon Sep 17 00:00:00 2001 From: pingke Date: Mon, 4 Dec 2023 23:15:19 +0800 Subject: [PATCH 3/7] add nat mapping for udp port --- ethstorage/p2p/discovery.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index d812158e..18349bb3 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -83,12 +83,15 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, } if !end { - internalPort := localNode.Node().TCP() - ip, port, err := addNATMapping(internalPort) + intTcpPort := localNode.Node().TCP() + intUdpPort := localNode.Node().UDP() + ip, extTcpPort, extUdpPort, err := addNATMappings(intTcpPort, intUdpPort) if err == nil { localNode.SetStaticIP(ip) - localNode.Set(enr.TCP(port)) - log.Info("Add mapping to NAT", "external IP", ip.String(), "internal port", internalPort, "external port", port) + localNode.Set(enr.TCP(extTcpPort)) + localNode.Set(enr.UDP(extUdpPort)) + log.Info("Add mappings to NAT", "external IP", ip.String(), "internal tcp port", intTcpPort, + "external tcp port", extTcpPort, "internal udp port", intUdpPort, "external udp port", extUdpPort) } else { log.Warn("", "error", err.Error()) } @@ -163,24 +166,28 @@ func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { return nil } -func addNATMapping(internalPort int) (net.IP, int, error) { +func addNATMappings(tcpPort, udpPort int) (net.IP, int, int, error) { n, err := nat.DiscoverNAT(context.Background()) if err != nil { - return nil, 0, fmt.Errorf("no external address set to ENR as no NAT service found: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("no external address set to ENR as no NAT service found: %s", err.Error()) } - mapping, err := n.NewMapping("tcp", internalPort) + tcpMapping, err := n.NewMapping("tcp", tcpPort) if err != nil { - return nil, 0, fmt.Errorf("fail to add mapping to NAT: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("fail to add tcpMapping for tcp port to NAT: %s", err.Error()) } - addr, err := mapping.ExternalAddr() + addr, err := tcpMapping.ExternalAddr() if err != nil { - return nil, 0, fmt.Errorf("get external IP from NAT mapping fail: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("get external IP from NAT tcpMapping fail: %s", err.Error()) } tcpAddr, err := net.ResolveTCPAddr("tcp", addr.String()) if err != nil { - return nil, 0, fmt.Errorf("fail to resolve external address: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("fail to resolve external address: %s", err.Error()) } - return tcpAddr.IP, mapping.ExternalPort(), nil + udpMapping, err := n.NewMapping("udp", udpPort) + if err != nil { + return nil, 0, 0, fmt.Errorf("fail to add tcpMapping for udp port to NAT: %s", err.Error()) + } + return tcpAddr.IP, tcpMapping.ExternalPort(), udpMapping.ExternalPort(), nil } func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, error) { From af511f806b50928b4e9c2c613df0e4ef95860628 Mon Sep 17 00:00:00 2001 From: pingke Date: Mon, 25 Dec 2023 18:59:41 +0800 Subject: [PATCH 4/7] fix build after change to go 1.21 --- ethstorage/p2p/discovery.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index 18349bb3..c07602ef 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -166,28 +166,35 @@ func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { return nil } -func addNATMappings(tcpPort, udpPort int) (net.IP, int, int, error) { - n, err := nat.DiscoverNAT(context.Background()) +func addNATMappings(tcpPort, udpPort int) (net.IP, uint16, uint16, error) { + ctx := context.Background() + n, err := nat.DiscoverNAT(ctx) if err != nil { return nil, 0, 0, fmt.Errorf("no external address set to ENR as no NAT service found: %s", err.Error()) } - tcpMapping, err := n.NewMapping("tcp", tcpPort) + err = n.AddMapping(ctx, "tcp", tcpPort) if err != nil { return nil, 0, 0, fmt.Errorf("fail to add tcpMapping for tcp port to NAT: %s", err.Error()) } - addr, err := tcpMapping.ExternalAddr() + err = n.AddMapping(ctx, "udp", udpPort) if err != nil { - return nil, 0, 0, fmt.Errorf("get external IP from NAT tcpMapping fail: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("fail to add tcpMapping for udp port to NAT: %s", err.Error()) } - tcpAddr, err := net.ResolveTCPAddr("tcp", addr.String()) - if err != nil { - return nil, 0, 0, fmt.Errorf("fail to resolve external address: %s", err.Error()) + + tcpMapping, foundTcp := n.GetMapping("tcp", tcpPort) + if foundTcp { + return nil, 0, 0, fmt.Errorf("fail to get tcpMapping for tcp port %d from NAT", tcpPort) } - udpMapping, err := n.NewMapping("udp", udpPort) + udpMapping, foundUdp := n.GetMapping("udp", udpPort) + if foundUdp { + return nil, 0, 0, fmt.Errorf("fail to get udpMapping for udp port %d from NAT", udpPort) + } + addr := tcpMapping.Addr().AsSlice() if err != nil { - return nil, 0, 0, fmt.Errorf("fail to add tcpMapping for udp port to NAT: %s", err.Error()) + return nil, 0, 0, fmt.Errorf("get external IP from NAT fail: %s", err.Error()) } - return tcpAddr.IP, tcpMapping.ExternalPort(), udpMapping.ExternalPort(), nil + + return addr, tcpMapping.Port(), udpMapping.Port(), nil } func enrToAddrInfo(r *enode.Node) (*peer.AddrInfo, *crypto.Secp256k1PublicKey, error) { From ca2b72e8b6a995ec0bbce3be66d7e63ee8a8b8e0 Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 26 Dec 2023 14:31:56 +0800 Subject: [PATCH 5/7] resolve comments --- ethstorage/p2p/discovery.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index c07602ef..239cadb8 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -86,6 +86,7 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, intTcpPort := localNode.Node().TCP() intUdpPort := localNode.Node().UDP() ip, extTcpPort, extUdpPort, err := addNATMappings(intTcpPort, intUdpPort) + if err == nil { localNode.SetStaticIP(ip) localNode.Set(enr.TCP(extTcpPort)) @@ -93,7 +94,7 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, log.Info("Add mappings to NAT", "external IP", ip.String(), "internal tcp port", intTcpPort, "external tcp port", extTcpPort, "internal udp port", intUdpPort, "external udp port", extUdpPort) } else { - log.Warn("", "error", err.Error()) + log.Warn("Add mappings to NAT fail", "error", err.Error()) } } } @@ -189,10 +190,13 @@ func addNATMappings(tcpPort, udpPort int) (net.IP, uint16, uint16, error) { if foundUdp { return nil, 0, 0, fmt.Errorf("fail to get udpMapping for udp port %d from NAT", udpPort) } - addr := tcpMapping.Addr().AsSlice() + addr := net.IP(tcpMapping.Addr().AsSlice()) if err != nil { return nil, 0, 0, fmt.Errorf("get external IP from NAT fail: %s", err.Error()) } + if addr.IsLoopback() || addr.IsPrivate() { + return nil, 0, 0, fmt.Errorf("NAT address is not external IP") + } return addr, tcpMapping.Port(), udpMapping.Port(), nil } From 421872c54d4e28c0a24a83c7706c163dd9c3c70c Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 26 Dec 2023 16:41:07 +0800 Subject: [PATCH 6/7] fix bug --- ethstorage/p2p/discovery.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index 239cadb8..6e817f10 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -183,11 +183,11 @@ func addNATMappings(tcpPort, udpPort int) (net.IP, uint16, uint16, error) { } tcpMapping, foundTcp := n.GetMapping("tcp", tcpPort) - if foundTcp { + if !foundTcp { return nil, 0, 0, fmt.Errorf("fail to get tcpMapping for tcp port %d from NAT", tcpPort) } udpMapping, foundUdp := n.GetMapping("udp", udpPort) - if foundUdp { + if !foundUdp { return nil, 0, 0, fmt.Errorf("fail to get udpMapping for udp port %d from NAT", udpPort) } addr := net.IP(tcpMapping.Addr().AsSlice()) From 49d8bd4ea45103aec46c077e68561fc66784b6b9 Mon Sep 17 00:00:00 2001 From: pingke Date: Tue, 9 Jan 2024 09:35:51 +0800 Subject: [PATCH 7/7] resolve comments --- ethstorage/p2p/discovery.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethstorage/p2p/discovery.go b/ethstorage/p2p/discovery.go index 6e817f10..c249caac 100644 --- a/ethstorage/p2p/discovery.go +++ b/ethstorage/p2p/discovery.go @@ -87,7 +87,7 @@ func (conf *Config) Discovery(log log.Logger, l1ChainID uint64, tcpPort uint16, intUdpPort := localNode.Node().UDP() ip, extTcpPort, extUdpPort, err := addNATMappings(intTcpPort, intUdpPort) - if err == nil { + if err == nil && !ip.IsPrivate() && !ip.IsLoopback() { localNode.SetStaticIP(ip) localNode.Set(enr.TCP(extTcpPort)) localNode.Set(enr.UDP(extUdpPort))