libp2p / js-libp2p

The JavaScript Implementation of libp2p networking stack.
https://libp2p.github.io/js-libp2p/
Other
2.33k stars 445 forks source link

NAT Traversal #104

Closed daviddias closed 1 year ago

daviddias commented 7 years ago

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:

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

daviddias commented 7 years ago

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

agahEbrahimi commented 6 years ago

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

dryajov commented 6 years ago

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

makew0rld commented 6 years ago

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

dryajov commented 6 years ago

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

dryajov commented 6 years ago

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

mateodelnorte commented 6 years ago

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

jacobheun commented 6 years ago

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!

agentofuser commented 5 years ago

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

jacobheun commented 5 years ago

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.

suutaku commented 5 years ago

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?

jacobheun commented 5 years ago

@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.

suutaku commented 5 years ago

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.

jacobheun commented 5 years ago

@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.

suutaku commented 5 years ago

@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 commented 5 years ago

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.

jacobheun commented 5 years ago

@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.
  } 
}
p-shahi commented 1 year ago

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