Introducing `Tunnel` - a minimal alternative to Autorelay (p2p-circuit-relay)

Hello Community :slight_smile:

Although autorelay works great when you know the relay-node that any given peer is connected to, discovering the routing to the peer behind NAT might be problematic at times. To elaborate, consider the following.

Peer A is behind NAT, enables autorelay ( ipfs config --json Swarm.EnableAutoRelay true ), then launches the ipfs daemon announcing the p2p-circuit addresses using Addresses.Announce, as can be confirmed subsequently with: ipfs id.

  1. Now, if peer B knows what relay-node A is connected to, it can simply do: ipfs swarm connect /p2p/QmRelayAddress/p2p-circuit/p2p/peerIDofA

  2. But, what if peer B doesn’t know the address of the relay-node that A is connected to! It can try to find the relay-address using: ipfs dht findpeer peerIDofA. In my case at least, this command used to take a lot of time and then output: Error: routing: not found. Edit: It must be emphasized however, that since updating to go-ipfs v0.9.1 recently, this problem magically disappeared.

Point 2 above won’t be a problem if peer A was guaranteed to always use the same relay, or, if there was a public list of all available relays that B can query for a p2p-circuit to A.

I faced point 2 above while connecting my home computer (behind NAT+Firewall) to my research workstation in my university (also behind NAT+Firewall). To make the connection as easy and reliable as possible I repurposed a universal p2p-port-forwarder, called tunnel, for the special case of IPFS. [You can use tunnel for any TCP/UDP port forwarding across NAT and Firewalls.]

Connecting to peer A behind NAT/Firewall from peer B also behind NAT/Firewall, is now as easy as:

tunnel ipfs # In peer A’s node.

tunnel peerIDofA # In peer B’s node.

Notice that none of peer A or B need to launch ipfs daemon . tunnel takes care of that. Also, peer B doesn’t need to swarm connect to A manually. tunnel keeps swarm connecting in the background every few seconds to keep the connection to A alive.

To make the connection private, peer A and B can both use a shared secret with the command-line option: -k secret. Also, besides the usual IPFS_PATH environment variable, the path to a non-default ipfs-repo may be passed using the option -r.

I tested tunnel in this IPFS mode for both file-sharing and pubsub. Worked fine for me. You can also use tunnel for SSH to a remote node behind NAT, and together with IPFS, you no more need to use SFTP for file-sharing.

I am sharing this here with the sincere hope that this humble project (tunnel) would be helpful to at least some of you trying to use IPFS from behind NAT. Thanks for your time.

I think that this is a great workaround you made. However there have been substantial improvements to libp2p that now allow “hole punching” native. If you have known nodes that are addressed they could be bootstrapped together which would make them dedicated peers in their own cluster. Then you can use IPFS cluster to orchestrate pins between them. Those pins represent objects much like a torrent or magnet file. You could conceivably run your own remote pinning service by using the “custom remote pinning API” which is just a template that says A remotely addressed node will replicate and store pin. A sort of bond or contract obligation to host the object(s)