From 3deee921046b2b184d93b4ca64c56d85df1e197a Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Thu, 29 Aug 2024 00:25:05 +0200 Subject: [PATCH] fix: enable dctur when interface address is public (#2931) * fix: allow punching undialable host public ip fixes #2913 * chore: use interface listen addrs to enable dctur * fix: filter public addresses * chore: remove unused function * chore: formatting --------- Co-authored-by: Daniel N <2color@users.noreply.github.com> --- p2p/protocol/holepunch/svc.go | 28 ++++++++++++++++++++++++++-- p2p/protocol/holepunch/util.go | 11 ----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/p2p/protocol/holepunch/svc.go b/p2p/protocol/holepunch/svc.go index 9de0a11e0c..eb8ad9fd38 100644 --- a/p2p/protocol/holepunch/svc.go +++ b/p2p/protocol/holepunch/svc.go @@ -19,6 +19,7 @@ import ( "github.com/libp2p/go-msgio/pbio" ma "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" ) // Protocol is the libp2p protocol for Hole Punching. @@ -106,7 +107,7 @@ func (s *Service) watchForPublicAddr() { t := time.NewTimer(duration) defer t.Stop() for { - if containsPublicAddr(s.ids.OwnObservedAddrs()) { + if len(s.getPublicAddrs()) > 0 { log.Debug("Host now has a public address. Starting holepunch protocol.") s.host.SetStreamHandler(Protocol, s.handleNewStream) break @@ -171,7 +172,7 @@ func (s *Service) incomingHolePunch(str network.Stream) (rtt time.Duration, remo if !isRelayAddress(str.Conn().RemoteMultiaddr()) { return 0, nil, nil, fmt.Errorf("received hole punch stream: %s", str.Conn().RemoteMultiaddr()) } - ownAddrs = removeRelayAddrs(s.ids.OwnObservedAddrs()) + ownAddrs = s.getPublicAddrs() if s.filter != nil { ownAddrs = s.filter.FilterLocal(str.Conn().RemotePeer(), ownAddrs) } @@ -274,6 +275,29 @@ func (s *Service) handleNewStream(str network.Stream) { s.tracer.HolePunchFinished("receiver", 1, addrs, ownAddrs, getDirectConnection(s.host, rp)) } +// getPublicAddrs returns public observed and interface addresses +func (s *Service) getPublicAddrs() []ma.Multiaddr { + addrs := removeRelayAddrs(s.ids.OwnObservedAddrs()) + + interfaceListenAddrs, err := s.host.Network().InterfaceListenAddresses() + if err != nil { + log.Debugf("failed to get to get InterfaceListenAddresses: %s", err) + } else { + addrs = append(addrs, interfaceListenAddrs...) + } + + addrs = ma.Unique(addrs) + + publicAddrs := make([]ma.Multiaddr, 0, len(addrs)) + + for _, addr := range addrs { + if manet.IsPublicAddr(addr) { + publicAddrs = append(publicAddrs, addr) + } + } + return publicAddrs +} + // DirectConnect is only exposed for testing purposes. // TODO: find a solution for this. func (s *Service) DirectConnect(p peer.ID) error { diff --git a/p2p/protocol/holepunch/util.go b/p2p/protocol/holepunch/util.go index 13013568fe..947b1ffd82 100644 --- a/p2p/protocol/holepunch/util.go +++ b/p2p/protocol/holepunch/util.go @@ -8,19 +8,8 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" ) -func containsPublicAddr(addrs []ma.Multiaddr) bool { - for _, addr := range addrs { - if isRelayAddress(addr) || !manet.IsPublicAddr(addr) { - continue - } - return true - } - return false -} - func removeRelayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { result := make([]ma.Multiaddr, 0, len(addrs)) for _, addr := range addrs {