Hole-punching implementation using DCUtR, AutoNAT, and relay via the libp2p networking stack.
Three components must be started in order:
cd relay
cargo runNote the PeerID and port printed on startup — needed for the next two steps.
cd hole-punching
cargo run -- --mode listen \
--relay-addr /ip4/<relay-ip>/tcp/<relay-port>/p2p/<relay-peer-id>Note the Local PeerID printed on startup — needed for the dialer.
cd hole-punching
cargo run -- --mode dial \
--relay-addr /ip4/<relay-ip>/tcp/<relay-port>/p2p/<relay-peer-id> \
--remote-peer-id <listener-peer-id>Three components must be started in order. No hole-punching — traffic is always forwarded through the relay.
cd relay
cargo runNote the PeerID and port printed on startup.
Registers a reservation with the relay so it becomes reachable via a circuit address.
cd relay_test_client_destination
cargo run -- <relay-peer-id> /ip4/<relay-ip>/tcp/<relay-port>Note the Local PeerID printed on startup — needed for the source client.
Dials the destination through the relay circuit.
cd relay_test_client_source
cargo run -- --relay-addr /ip4/<relay-ip>/tcp/<relay-port>/p2p/<relay-peer-id>/p2p-circuit/p2p/<destination-peer-id>An echo example built on the iroh networking
stack (QUIC, with relay + hole-punching and dialing by public key). Connectivity
uses the default n0 discovery service, so the listener's Endpoint ID is the
only thing the dialer needs.
Two components, started in order:
cd iroh-connect
cargo run --bin listenNote the Endpoint ID printed on startup — needed for the dialer.
Dials the listener by its Endpoint ID, sends a message, and prints the echoed reply.
cd iroh-connect
cargo run --bin connect -- <endpoint-id> "hello iroh"The same echo example, but routed over Tor hidden services using the
experimental iroh-tor-transport
custom transport. The peer's .onion address is derived from its Endpoint ID,
so you reach other nodes knowing only their Endpoint ID — no IP address, no NAT
hole-punching, and no public relay. This works even behind NATs that plain
hole-punching can't traverse (symmetric NATs), at the cost of Tor's latency.
tor --ControlPort 9051 --CookieAuthentication 0Each side automatically publishes its own ephemeral hidden service on startup.
cd iroh-tor
cargo run --bin listenNote the Endpoint ID printed on startup — needed for the dialer. To keep the
same identity (and onion address) across restarts, export the printed
IROH_SECRET before running.
cd iroh-tor
cargo run --bin connect -- <endpoint-id> "hello over tor"Establishing the Tor circuit and resolving the hidden service can take tens of seconds on the first connect.