Skip to content

EnableHolePunching not working! #2878

@iGwkang

Description

@iGwkang

I hope to get help.
I found similar issus, but my problem was not solved.
#2761
#2630

Below is the sample code I wrote and the running steps and results.

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/libp2p/go-libp2p"
	dht "github.com/libp2p/go-libp2p-kad-dht"
	"github.com/libp2p/go-libp2p/core/network"
	"github.com/libp2p/go-libp2p/core/peer"
	drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
	dutil "github.com/libp2p/go-libp2p/p2p/discovery/util"
	"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
	ma "github.com/multiformats/go-multiaddr"
)

var op = flag.String("op", "", "relay and bootstrap server")
var relayAddr = flag.String("relay", "", "relay Addr")

func main() {
	flag.Parse()
	if *op == "relay" {
		runRelayAndBootstrapServer()
	} else if *op == "conn" {
		runNode()
	}
}

func runRelayAndBootstrapServer() {
	relay1, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/9876"))
	if err != nil {
		log.Printf("Failed to create relay1: %v", err)
		return
	}

	_, err = relay.New(relay1)
	if err != nil {
		log.Printf("Failed to instantiate the relay: %v", err)
		return
	}
	_, err = dht.New(context.Background(), relay1, dht.Mode(dht.ModeServer)) //
	if err != nil {
		log.Printf("Failed to create DHT: %v", err)
		return
	}

	// _, err = autonat.New(relay1)
	// if err != nil {
	// 	log.Printf("Failed to create AutoNAT: %v", err)
	// 	return
	// }

	fmt.Printf("[*] Your Bootstrap ID Is: /ip4/%s/tcp/%v/p2p/%s\n", "0.0.0.0", 9876, relay1.ID().String())

	select {}
}

func runNode() {
	maRelayAddr, _ := ma.NewMultiaddr(*relayAddr)
	relay1info, _ := peer.AddrInfoFromP2pAddr(maRelayAddr)

	conn1, err := libp2p.New(
		libp2p.EnableRelay(),
		libp2p.NATPortMap(),
		libp2p.EnableHolePunching(),
		// libp2p.ForceReachabilityPrivate(),
		libp2p.EnableAutoRelayWithStaticRelays([]peer.AddrInfo{*relay1info}),
	)
	if err != nil {
		fmt.Println("Failed to create unreachable1: ", err)
		return
	}

	conn1.SetStreamHandler("/customprotocol", func(s network.Stream) {
		log.Println("Awesome! We're now communicating via the relay!")
		buf := make([]byte, 1024*64)
		for {
			_, err := s.Read(buf)
			if err != nil {
				log.Println("Failed to read from stream")
				break
			}
		}
		s.Close()
	})

	// err = conn1.Connect(context.Background(), *relay1info)
	// if err != nil {
	// 	log.Printf("Failed to connect to relay1: %v", err)
	// 	return
	// }
	// fmt.Println("Successfully connected to relay1!")

	ctx := context.Background()

	kademliaDHT, err := dht.New(ctx, conn1, dht.BootstrapPeers(*relay1info))

	fmt.Println("Bootstrapping the DHT")
	if err = kademliaDHT.Bootstrap(ctx); err != nil {
		panic(err)
	}

	// // Wait a bit to let bootstrapping finish (really bootstrap should block until it's ready, but that isn't the case yet.)
	time.Sleep(1 * time.Second)

	// We use a rendezvous point "meet me here" to announce our location.
	// This is like telling your friends to meet you at the Eiffel Tower.
	fmt.Println("Announcing ourselves...")
	routingDiscovery := drouting.NewRoutingDiscovery(kademliaDHT)
	dutil.Advertise(ctx, routingDiscovery, "test")
	fmt.Println("Successfully announced!")

	fmt.Println("Searching for other peers...")
	peerChan, err := routingDiscovery.FindPeers(ctx, "test")
	if err != nil {
		panic(err)
	}

	for peer := range peerChan {
		if peer.ID == conn1.ID() {
			continue
		}
		fmt.Println("Found And Connecting to peer:", peer)

		s, err := conn1.NewStream(ctx, peer.ID, "/customprotocol")

		if err != nil {
			fmt.Println("Connection failed:", err)
			continue
		}
		fmt.Println("Connected to:", peer)

		go func() {
			buf := make([]byte, 1024*64)
			for {
				_, err := s.Write(buf)
				if err != nil {
					log.Println("Unexpected error here. Failed to write: ", err)
					break
				}
				time.Sleep(70 * time.Millisecond)
			}
			s.Close()
		}()
	}

	select {}
}
go build -o relay .
  • step 1:
    Run ./relay -op relay on a server with a public IP.
    The terminal will output:
[*] Your Bootstrap ID Is: /ip4/0.0.0.0/tcp/9876/p2p/12D3KooWPnMh1ibwK39Y8AuZQtogs2FoQ72JnTEDr6H1JEpVw4Bi
  • step 2:
    Using two hosts, Host A and Host B are behind different firewalls and both are Cone NAT.
    They run simultaneously:
relay -op conn -relay /ip4/public_ip/tcp/9876/p2p/12D3KooWPnMh1ibwK39Y8AuZQtogs2FoQ72JnTEDr6H1JEpVw4Bi

Host A and Host B, terminal Output:

Connection failed: failed to dial: failed to dial 12D3KooWGvYWA3R5TSr8d6ozuja1Nhy1URd3hQGmVyziSs5PNF4A: all dials failed
  * [/ip6/::1/tcp/7334] dial tcp6 [::1]:7334: connectex: No connection could be made because the target machine actively refused it.
  * [/ip6/::1/udp/62311/quic-v1] context deadline exceeded
  * [/ip6/240e:3b7:3248:7a1:e423:e7e:6217:a354/udp/62311/quic-v1] timeout: no recent network activity
  * [/ip4/127.0.0.1/tcp/7333] dial tcp4 127.0.0.1:7333: connectex: No connection could be made because the target machine actively refused it.
  * [/ip4/10.0.0.16/udp/62309/quic-v1] timeout: no recent network activity
  * [/ip4/10.0.0.16/udp/62310/quic-v1/webtransport/certhash/uEiAzQuWpYHXEkiVhAYOohxId2kLmyXS5m3TcFdPPRX2uxw/certhash/uEiA0Ixeot0LRUq6TydJo-NRHlGAOcSHufpALjXNI-ib-Fg] timeout: no recent network activity
  * [/ip4/127.0.0.1/udp/62309/quic-v1] timeout: no recent network activity
  * [/ip6/::1/udp/62312/quic-v1/webtransport/certhash/uEiAzQuWpYHXEkiVhAYOohxId2kLmyXS5m3TcFdPPRX2uxw/certhash/uEiA0Ixeot0LRUq6TydJo-NRHlGAOcSHufpALjXNI-ib-Fg] context deadline exceeded
  * [/ip4/127.0.0.1/udp/62310/quic-v1/webtransport/certhash/uEiAzQuWpYHXEkiVhAYOohxId2kLmyXS5m3TcFdPPRX2uxw/certhash/uEiA0Ixeot0LRUq6TydJo-NRHlGAOcSHufpALjXNI-ib-Fg] context deadline exceeded
  * [/ip4/10.0.0.16/tcp/7333] dial tcp4 0.0.0.0:20934->10.0.0.16:7333: i/o timeout
  * [/ip6/240e:3b7:3248:7a1:e423:e7e:6217:a354/udp/62312/quic-v1/webtransport/certhash/uEiAzQuWpYHXEkiVhAYOohxId2kLmyXS5m3TcFdPPRX2uxw/certhash/uEiA0Ixeot0LRUq6TydJo-NRHlGAOcSHufpALjXNI-ib-Fg] timeout: no recent network activity

The output addresses do not contain the addresses of the holepunching, they are all their own local addresses.

How should I modify this code to make HolePunching work ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions