Giter VIP home page Giter VIP logo

node-tcp-hole-punching's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

node-tcp-hole-punching's Issues

Is the prototype can be used in real world

In publicserver.js

This piece of code make a strict assumption, it requires in milliseconds, A and B come in order.

var server = require('net').createServer(function (socket) {
	if(!socketA) {
		aConnects(socket);
	}else{
		bConnects(socket);
	}
});

But it is hard to happen in real application.
Could you please tell how to use this method in real world.
Any help will be highly appreciated.

Both client A and client B throw EADDRINUSE

First, thank you for this little sample! It's so exciting to get it to work with minimal dependencies.

My issue looks different than the other two already filed. My public server runs on a host with a public IP. My client A and client B run behind their own NAT. Both of them are on Linux. I have this issue on Ubuntu 18.04 and Debian Stretch. Node version is 8.9.4 or 6.14.2.

$ node clientA.js
> (A->S) connecting to S
> (A->S) connected to S via 192.168.0.188 44808
> (A->S) response from S: {"name":"A","localAddress":"192.168.0.188","localPort":44808,"remoteAddress":"172.58.36.250","remotePort":43526}

> (A) 192.168.0.188:44808 ===> (NAT of A) 172.58.36.250:43526 ===> (S) 104.198.1.109:9999

> (A->S) response from S: {"name":"B","localAddress":"192.168.86.108","localPort":42688,"remoteAddress":"107.194.153.239","remotePort":42688}
> (A) time to listen on port used to connect to S (44808)
> (A->B) connecting to B: ===> (B) 107.194.153.239:42688
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE 192.168.0.188:44808
    at Object._errnoException (util.js:1024:11)
    at _exceptionWithHostPort (util.js:1046:20)
    at Server.setupListenHandle [as _listen2] (net.js:1351:14)
    at listenInCluster (net.js:1392:12)
    at doListen (net.js:1501:7)
    at _combinedTickCallback (internal/process/next_tick.js:141:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
$ node clientB.js 
> (B->S) connecting to S
> (B->S) connected to S via 192.168.86.108 42688
> (B->S) response from S: {"name":"B","localAddress":"192.168.86.108","localPort":42688,"remoteAddress":"107.194.153.239","remotePort":42688}

> (B) 192.168.86.108:42688 ===> (NAT of B) 107.194.153.239:42688 ===> (S) 104.198.1.109:9999

> (B->S) response from S: {"name":"A","localAddress":"192.168.0.188","localPort":44808,"remoteAddress":"172.58.36.250","remotePort":43526}
> (B) time to listen on port used to connect to S (42688)
> (B->A) connecting to A: ===> (A) 172.58.36.250:43526
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE 192.168.86.108:42688
    at Object._errnoException (util.js:1024:11)
    at _exceptionWithHostPort (util.js:1046:20)
    at Server.setupListenHandle [as _listen2] (net.js:1351:14)
    at listenInCluster (net.js:1392:12)
    at doListen (net.js:1501:7)
    at _combinedTickCallback (internal/process/next_tick.js:141:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Apparently, this line failed:

socketToS = require('net').createConnection({host : addressOfS, port : portOfS}, function () {
  ...
});

can not run on centos 7

Dear You,
your program run on widow environment is OK . Client A and B connection successfully
But when I run with Censtos environment , there is a false on Client :
_Error: listen EADDRINUSE : address already in use xx.xx.xx.xx :56830
at Server.setupListenhandle [as isten2] (net.js:1280:14)
please tell me way to debug

Thansk you

Any recommendations to suggest or workaround EADDRINUSE when trying to use the same address?

I tested this script as a prove of concept, unfortunately, it doesn't work. I dug around the detail behind the scene and found out there were some complications around the TCP mechanism of Linux kernel itself, but most of them pointed to SO_REUSEADDR, which is the flag that allow the connection to use the same port, is somehow not active or not working properly. Node.JS documentation stated that SO_REUSEADDR is already active, but somehow the app still complains EADDRINUSE, and did not work.

Client B throw Error: listen EADDRINUSE

So, i think my setup is okay, yet, clientB crash
Error: listen EADDRINUSE 172.19.21.58:34662

ClientA is like

R:\node-tcp-hole-punching>node clientA.js
> (A->S) connecting to S
> (A->S) connected to S via 192.168.131.19 65066
> (A->S) response from S: {"name":"A","localAddress":"192.168.131.19","localPort":65066,"remoteAddress":"::ffff[something],"remotePort":65066}

> (A) 192.168.131.19:65066 ===> (NAT of A) ::ffff:[something]65066 ===> (S) [somethingelse]:9999

> (A->S) response from S: {"name":"B","localAddress":"172.19.21.58","localPort":34662,"remoteAddress":"::ffff:[BPublicIP]","remotePort":34662}
> (A) time to listen on port used to connect to S (65066)
> (A->B) connecting to B: ===> (B) ::ffff:[BPublicIP]:34662
> (A) listening on  192.168.131.19:65066
> (A->B) connection closed with err: ETIMEDOUT
> (A->B) connecting to B: ===> (B) ::ffff:[BPublicIP]:34662

clientB is like

> (B->S) response from S: {"name":"A","localAddress":"192.168.131.19","localPort":65066,"remoteAddress":"::ffff:[clientAPublic]","remotePort":65066}
> (B) time to listen on port used to connect to S (34662)
> (B->A) connecting to A: ===> (A) ::ffff:[clientAPublic]:65066
events.js:141
      throw er; // Unhandled 'error' event

Is there something i can try ?

(B->A) connection closed with err: ETIMEDOUT

i run publicserver.js on a public server (not behind a NAT).
clientA.js on mac behind a NAT.
clientB.js on win10 behind a different NAT.

but it logs :
in win10 : (B->A) connection closed with err: ETIMEDOUT
in mac : (A->B) connection closed with err: ETIMEDOUT

B don't receive any data from A,
A don't receive any data from B.

what is problem ?

Only works with NATs that don't require SYN messages to let packets through

As stated before, this is the simplest code for TCP hole punching I could find. Very helpful and instructive, thanks for putting this out. Especially the stripped-down version is really impressive in its shortness. Congraz!

Now, this code doesn't work if you work with internet gateways that require the devices behind the gateway to initiate a connection before accepting packages from an unknown source.

I.e. if your computer behind a router connects to a http server on the public internet, your computer initiated the connection first, your gateway will remember that and therefore accepts packages from the https server you reached out to.

If a random remote computer tries to connect to your device behind the internet gateway without your device initiating the connection, many internet gateways will refuse those "unsolicited" connections and therefore the random remote computer won't be able to connect.

I think node-tcp-hole-punching could be easily extended to address this issue by adding those two steps to the client code:

  • clientA and clientB receive the socket information of their counterpart from the public server
  • both clients send TCP SYN packages to their counterpart, therefore letting their internet gateways know that they should accept connections from the other client

See also:

This is probably beyond what Sam intended originally but this might be a nice extension. I will give it a try whether I can extend it accordingly...

Client A throws EADDRINUSE

I am trying to do a TCP hole punching, but the clientA is throwing EADDRINUSE in Ubuntu but works fine in Mac.

What might be the problem? Is there a way to set option "reuseaddress" explicitly but node js docs say (Note: All sockets in Node.js are set SO_REUSEADDR.)

Any help is appreciated. Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.