Click here to Skip to main content
14,983,071 members
Articles / Web Development / Node.js
Posted 7 Jul 2017


7 bookmarked

Reverse tunneling / port forwarding with Node.js

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
8 Jul 2017CPOL6 min read
Connect to PC with no public IP using Node.js app for reverse port forwarding / tunneling.


An app allows you to forward specific port of some machine inside network with no public IPs.


Time to time I have to connect via RDP, SSH, proxy, etc. to several machines inside private network. Sadly, tools like TeamViewer, Hamachi, SSH tunneling, VPN are blocked there... 

Image 1So I decided to build a Node.js app to fulfil my needs.

Using the code

Running locally

I'll start with a minimal amount actions required to run app and play around with it.

Prerequisites: Node.js (tested with 8), git client

  1. git clone
  2. cd node-tunnel
  3. npm install

Now, let's create minimal config file, I'll provide two examples: for people who has SSH, another one - for guys with browser :)

Create .env file (it's full file name ".env", not an extension!) with content:
NOTE: ".env" file should be created in project root folder, in this case: node-tunnel

for SSH (you may change host/port to any other if you want)


for http (you may change host/port to any other; most likely website won't work due to certificates and other issues, but it's enough as an example)

We are ready to launch it! Start three terminal windows because we need to start 3 node instances, and run:
node server
node agent
node client

If you've chosen SSH way, connect to localhost:2222 -> ssh -p 2222 localhost
If you've chosen http way, open your browser and visit localhost:8000

Yeah! This is the minimal working example. All your traffic goes through client->server->agent and back.

Real life case, two PCs

In this example we have such situation. You have PC with public IP and another one without it. Goal - connect to it with SSH/RDP/whatever.

Let's start with cloning repo and installing modules on each machine.

Now, go to remote PC and create .env file. In this example I'm using RDP port, feel free to change to anything else.

N_T_SERVER_HOST=ip of machine with public ip


Now, start agent here: node agent

Switch to local PC, and create .env file:



Now, start server and client here:
node server
node client

Once you are done - you can connect with RPD client to localhost:8000 that will open connection to remote PC.

Real life case, two PCs and server

That looks great but what if yours local PC has no public IP? You have to forward all traffic though some PC with public IP. If you haven't such - you may create free container on AWS.

Image 2

Let's do it! As usual, install node.js, clone repo and install modules on each machine.

Go to PC with public IP (server) and create .env file there:


Great, run server: node server

On remote PC, create .env file. In this example I'm using SSH port, but you can change host/port to anything you want. Also, I would give some name to agent (that should match with client name).

N_T_SERVER_HOST=ip of machine with public ip


Ready to launch agent: node agent

Switch to client PC and create .env file. Client name should match agent name.

N_T_SERVER_HOST=ip of machine with public ip


Finally, start client: node client

Cool. Now we can open SSH connection to localhost:8000 that will open ssh connection to remote PC.

We have created tunnel though server machine, as we, actually, did before. All the data goes like this:
ssh client -> client -> server -> agent -> ssh server
and back ssh server -> agent -> server -> client -> ssh client
There is no direct connection between agent and client.

More agents and clients

Multiple agents and clients can go through one server. Example:
You can run one agent to handle SSH, another to handle RDP. Please note that each agent should have name (N_T_AGENT_NAME).

Each agent may work with multiple client, so you can run client on your machine and others to go to specific agent. Don't forget to specify which agent client should use by providing name (N_T_CLIENT_NAME)

Multiple .env files

If you need to run multiple agents/clients/servers you may create multiple .env files, example:

Having such .env.* files you can start server/client/agent by passing .env file name as argument:
node server .env.rdp
node agent .env.ssh
node client .env.test

NOTE: ".env" file should be created in project root folder, in this case: node-tunnel.

How it works?

Core stuff here: Net that allows to create stream-based TCP servers/clients and stream pipes.
To forward data from one socket to another and back - I simply piped them like this:


Let's take a look at this example:
Image 3

In an example with SSH the following happens:

  1. SSH client connects to client (that is listening on some port)
  2. client forwards all data to server
  3. server knows that it is required to forward data to specific agent
  4. agent opens connection to SSH server and forwards data from server to it

    response from SSH server goes back to agent, server, client and reaches SSH client finally

Let me try to explain what each part of app does


  • by default server listens for clients and agents connections
  • once new agent connects - server creates a dedicated server for it
  • once new client connects - server notifies it that there is a dedicated server for agent and its port
  • client and agent names should match in order to start data forwarding, agent with same name are not allowed
  • there may be multiple agents, and there may be multiple client per agent (there may be a low of clients with same name)

Dedicated server for agent behaves this way:

  1. on new connection to client server a new connection opens to agent dedicated server
  2. once client connected - a notification to agent is sent so it can open connection to server 
    in a meanwhile: client socket is now stored and waiting for agent socket
  3. once agent is connected - dedicated server pipes agent to client and back, and removes data listeners of client and agent sockets
  4. dedicated server sends notification to client saying that pipe is created and we are ready to go
  5. Done!


Client creates server and listens for incoming connections on port provided in .env file.

On new connection client starts forwarding data to server (see server section for details).


Agent waits for notification regarding client connection. When such happened - agents connects to host:port specified in .env file and forwards it to server.

What's next?

Encryption! Currently data is not encrypted, it's not a problem for SSH, RDP but is an issue for plain text protocols.
Only service messages are encrypted at the moment.

And, of course, fix some defects, cleanup code, increase stability.

If you have any ideas - feel free share :)

As a conclusion

Thank you for reading!

I hope it was somehow interesting, somewhat understandable and maybe even useful :)

Points of Interest

Helpful module when working with pipes may be though2.
With this module you pass data though your worker and do stuff like: logging, error handling or changing data, let's say change some keyword (ebay) to another one (amazon), or change all 0 to 1 :)


Initial version, fixed some typos.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer
Ukraine Ukraine
I'm a fan of javascript, love Node.js and Vue.js that allow me to build complex applications easily. Like to play with Arduino. Also have experience and worked/working with c#, java, groovy, python, bash, batch.

Comments and Discussions

QuestionFeature request Pin
skippy767-Dec-18 11:33
Memberskippy767-Dec-18 11:33 
QuestionSetup tunnel Pin
skippy766-Dec-18 11:50
Memberskippy766-Dec-18 11:50 
AnswerRe: Setup tunnel Pin
skippy767-Dec-18 11:27
Memberskippy767-Dec-18 11:27 
QuestionAgent not working behind network proxy Pin
Member 101897155-Nov-18 21:13
professionalMember 101897155-Nov-18 21:13 
QuestionInteresting article, but browser case not clear Pin
Dewey8-Jul-17 7:46
MemberDewey8-Jul-17 7:46 
AnswerRe: Interesting article, but browser case not clear Pin
_m0n8-Jul-17 9:06
professional_m0n8-Jul-17 9:06 
GeneralRe: Interesting article, but browser case not clear Pin
Dewey8-Jul-17 13:29
MemberDewey8-Jul-17 13:29 
GeneralRe: Interesting article, but browser case not clear Pin
_m0n8-Jul-17 17:12
professional_m0n8-Jul-17 17:12 
GeneralRe: Interesting article, but browser case not clear Pin
Dewey8-Jul-17 19:18
MemberDewey8-Jul-17 19:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.