js-libp2p icon indicating copy to clipboard operation
js-libp2p copied to clipboard

NAT Traversal

Open daviddias opened this issue 8 years ago • 17 comments
trafficstars

Currently, the only mechanism to pierce through NATs in js-libp2p is the WebRTC transport. NAT Traversal is a feature that is hard to get 100% complete as there will be always more NAT implementations that will not work with the strategies we have in place. Ultimately the last resort is Relay (Circuit or Packet Switched).

There is plenty of work available for NAT Traversal, WebRTC is kind of a canon to solve this problem, but not every peer will have WebRTC neither we can trust WebRTC 100% of the times.

Here is a list of good resources to get started:

  • https://tools.ietf.org/html/rfc5128
  • http://www.brynosaurus.com/pub/net/p2pnat/
  • https://samy.pl/chownat/
  • http://samy.pl/pwnat/
  • https://en.wikipedia.org/wiki/Universal_Plug_and_Play
  • https://www.npmjs.com/package/pmp
  • There are more modules -- https://www.npmjs.com/search?q=nat+traversal --, I haven't looked at them all. Getting a throughout review of them would be awesome.
  • https://github.com/getlantern/natty

The next milestone for Relay is to support UPnP for TCP ports, the same way go-ipfs does.

daviddias avatar Jul 09 '17 13:07 daviddias

One more resource: - https://nice.freedesktop.org/wiki/

daviddias avatar Jul 29 '17 17:07 daviddias

So there aren't any NAT Traversal techniques in js-libp2p? Not even Nat Port mapping?

agahEbrahimi avatar Apr 16 '18 14:04 agahEbrahimi

Work on this is planned already, and will begin very soon.

dryajov avatar Apr 16 '18 16:04 dryajov

Can't ipfs's NAT traversal just be reimplemented here? Why is it being worked on separately?

makew0rld avatar Apr 19 '18 18:04 makew0rld

Quick update and outline of what is currently being worked on:

  • I've put together an initial implementation of a nat mapper that will allow creating port mappings using different available techniques (upnp, pmp, pcp, hole punching, etc...). Currently, pmp and upnp are being supported, with pcp and hole punching planed once the rest settles in.
    • the code is here (heavy wip) - https://github.com/libp2p/js-libp2p-nat-mngr
  • A dialme protocol has been proposed here - https://github.com/libp2p/specs/pull/64
    • this will allow us to request dial backs on mapped public ports from clients dialed over a relay, thus allowing to upgrade circuited connections to direct ones if that is possible

dryajov avatar May 29 '18 20:05 dryajov

I've added an issue describing the NAT flow here - https://github.com/libp2p/js-libp2p/issues/200

dryajov avatar May 31 '18 21:05 dryajov

Hi all. What's the current state of affairs here? Any way for additional individuals to help out?

mateodelnorte avatar Jul 25 '18 15:07 mateodelnorte

We are planning on picking this back up this quarter, it's just lower on the priority list at the moment. The next steps for moving this forward are to finalize the specs, https://github.com/libp2p/specs/pull/64, and work on getting the initial work of the nat manager finished, https://github.com/libp2p/js-libp2p-nat-mngr/pull/1.

The spec will be the big blocker to get resolved, so that nat manager can get moving again. There are a lot of considerations that need to get figured out, so any additional help/support there would be great!

jacobheun avatar Jul 30 '18 13:07 jacobheun

Hi! Is this on the table for Q2? It would be really nice to have for ipfs-deploy.

agentofuser avatar May 02 '19 13:05 agentofuser

Hi! Is this on the table for Q2? It would be really nice to have for ipfs-deploy.

Yes. This is on my list for the quarter and I am hoping to tackle this as well as https://github.com/libp2p/js-libp2p/issues/202 to help node addressing.

jacobheun avatar May 02 '19 15:05 jacobheun

Somebody said NAT traversal using libp2p-webrtc-star works. I have tried wrtc + libp2p-webrtc-star, but it's not working.

const wr= new WRTC(
      { id: _options.peerInfo.id,
        wrtc: wrtc
      })

can somebody give an example or some docs?

suutaku avatar Jul 09 '19 15:07 suutaku

@suutaku what does your network setup look like in terms of libp2p nodes? Are you connecting both nodes to the same signaling server? The chat example at https://github.com/libp2p/js-libp2p-examples/tree/master/chat provides a setup that includes a node client, a node bootstrap node (with signaling server), and a browser client. I have not had the chance to test that across networks yet though.

I am out next week but will be continuing work on the AutoNAT protocol in js when I am back.

jacobheun avatar Jul 10 '19 13:07 jacobheun

Welcome to back! we need you @jacobheun I tested both chat and libp2p-in-the-browser example in my network and also set relay enabled(I don't know if it is work). I have tow routers. node A connected router A, node B connected router B. node A address 192.168.0.100 node B address 192.168.199.132 A,B can not discoveried each other. but if I change node B to connect router A. everything is OK.

suutaku avatar Jul 11 '19 02:07 suutaku

@suutaku are they both connected to a signaling server? You'll need to add listening addresses to both nodes for the signaling server, until we get a decentralized signaling protocol in place.

This is adding a local address, https://github.com/libp2p/js-libp2p-examples/blob/d17d5d2f97a592a2441b8dddb305c96b839cf660/chat/browser/08-End/libp2p.js#L16, but you will need to use a common signaling server both your nodes can hit. We currently host one for testing, https://github.com/libp2p/js-libp2p-webrtc-star#hosted-rendezvous-server, but I am not sure if that has been blocked yet in China or not. If you have a common local gateway you can try running the signaling server also mentioned in that readme.

jacobheun avatar Jul 11 '19 07:07 jacobheun

@jacobheun thank you! I tried as you said. it's worked but not well. I mean I start a signaling server and get /dns/peer.xxxx.com:/8088/ws/p2p-webrtc-star/. local peers added _options.peerInfo.multiaddrs.add("/dns4/peer.xxxx.com/tcp/8088/ws/p2p-webrtc-star/p2p/${_options.peerInfo.id.toB58String()}");

only sometime it worked. most time they can not find each other.

suutaku avatar Jul 22 '19 04:07 suutaku

by check log info. I found:

1. peer discovery was OK.

peer can be discovered.

2. dial was failed.

error info: No available transports to dial peer my transport :

const wrct = require('wrtc')
const webrtcStar = new WebrtcStar({ wrtc: wrct })
transport: [
          TCP,
          new WebSockets(),
          webrtcStart
          
        ],

and listening on:

info.multiaddrs.add("/ip4/0.0.0.0/tcp/0");
info.multiaddrs.add("/ip4/0.0.0.0/tcp/0/ws");
info.multiaddrs.add(`/dns4/peer.xxxxx.com/tcp/8088/ws/p2p-webrtc-star/p2p/${info.id.toB58String()}`);

Update

@jacobheun have did some test and research. I found NAT traversal is a big problem in China. by my case. internet works like:

public network --> NAT1 --> NAT2 --> NAT3 --> my router --> my device

maybe is difficult to punch a hole? so if it's difficult, how about circuit relay?
I noticed js-libp2p have relay configure option

 relay: { 
          enabled: true, 
          hop: { 
            enabled: true,
             active: true 
          } 
        },

and also not working........

Update agin

by launch a relay node with public ip, problem solved.

suutaku avatar Jul 22 '19 05:07 suutaku

@suutaku hole punching definitely is not 100%. WebRTC has our only method of doing this in JS right now. There are other NAT traversal techniques we're working on adding, but circuit relay is the best interim solution, assuming you have a dialable relay that both nodes are connected to. I am going to post some notes today on https://github.com/libp2p/js-libp2p/issues/385, which is likely going to require some more improvements to how circuits and webrtc signaling are done to help with this.

For the relay config I'm adding some comments below to try and help clarify. Note, your relay node must be dialable, and both your other nodes must be connected to it at the moment. I'm looking to improve this with the work for #385.

relay: { 
  enabled: true,  // This line means your node is dialable over a Relay, but doesn't make it a relay itself
  hop: { 
    enabled: true,  // `true` means your node is a relay. So if two nodes are connected to it, it should relay their dials to one another
    active: true  // `true` means your node will attempt to actively dial the requested peer. This is likely not going to work in your situation, since your nodes aren't dialable.
  } 
}

jacobheun avatar Jul 23 '19 13:07 jacobheun

closing in favor of https://github.com/libp2p/js-libp2p/issues/1461 AutoNat has landed https://github.com/libp2p/js-libp2p/issues/1005 hole punching in the browser is possible via private-to-private/browser-to-browser https://github.com/libp2p/js-libp2p-webrtc

p-shahi avatar May 30 '23 03:05 p-shahi