samdecrock / node-tcp-hole-punching Goto Github PK
View Code? Open in Web Editor NEWNode.js script to demonstrate TCP hole punching through NAT
License: MIT License
Node.js script to demonstrate TCP hole punching through NAT
License: MIT License
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.
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 () {
...
});
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
Hi,
Just wondering whether the project works on linux? or appreciated you can point out what operating system can run this sample up?
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.
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 ?
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 ?
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:
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...
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.