Reverse SSH tunnel or connecting to computer behind NAT router

Introduction

Few days ago I encountered a problem. How do you connect to a computer behind NAT router? Any NAT router is also a firewall. Sometimes you do have access to firewall configuration and can set up port forwarding. Yet often it is complicated and even impossible. Common situation is when you want to connect to a computer in the office from home. Companies usually hide office computers behind NAT routers and firewalls. Hence you cannot connect to office computer as is.

This is exactly the problem I had to overcome. After googling for couple of minutes I found a solution called reverse SSH tunnel. Yet I could not find a guide that explains how to make it work from A to Z. So I decided to write one.

Understanding the setup

In our basic setup we have a Home Computer. It runs Linux and can freely access the Internet. Office Computer is the Linux machine behind NAT router. We want to connect to Office Computer but can’t because of the NAT router. Server is additional Linux machine. It has to be accessible from both home and office computers via SSH.

Preparations

First, we have to make sure that SSH server on Server has GatewayPorts option turned on. You most likely have openssh SSH server. If so, open /etc/ssh/sshd_config and make sure it has following line.

GatewayPorts yes

If it’s missing, add it and restart SSH service.

Now this is important. Using method described here you can connect to different ports on Office Computer. However, if you want to connect to it via SSH you have to make sure that GatewayPorts is on on the Office Computer as well.

Also, to connect you need access to the Office Computer. I.e. you either have to ask someone to execute commands on Office Computer for you, or you have to run them yourself in advance.

Connecting

This is the easy part.

Assuming you want to connect to port X on Office Computer, do the following.

On Office Computer do the following:

ssh -R 6333:localhost:X user_on_server@server

Server will require regular SSH credentials (either certificate or password) and will open regular SSH session for you. This is the tunnel session. Keep it open as long as you want to stay connected to the Office Computer.

On Home Computer connect to port 6333 on Server as if it was port X on Office Computer. In case you want to connect to SSH port on Office Computer, set X to 22 (SSH port) in step 1 and do the following:

ssh user_on_office_computer@server -p 6333

Again, you may be asked to identify yourself. Do it as you were connecting to Office Computer directly.

Avoiding session expiration

As I mentioned in Preparations section of this guide, you can do step 1 in advance, before going home. Alternatively, you can ask someone to do the command for you. In case you prefer to do it yourself, you may want to make sure that tunnel connection you established won’t expire.

There are three options in /etc/ssh/sshd_config that control SSH session expiration. Once in a while SSH server sends keep-alive messages to connected clients. Temporary connectivity problem can cause it to disconnect certain SSH session, despite this is only a very temporary problem. Depending on the configuration of you SSH server, you may want to prevent these keep-alive messages. On the contrary you may want to increase interval between them or change number of lost keep-alive messages that indicate to SSH server that a connection to a client has been lost.

TCPKeepAlive configuration option enables or disables keep-alive messages. The default is yes (i.e. send keep-alives) and it is a good practice to keep it this way.

ClientAliveInterval specifies number of seconds between every keep-alive message. Depending on quality of connection between Office Computer and the Server we may want to set it to, let’s say 10.

ClientAliveCountMax controls number of lost keep-alive messages that cause SSH server to pull the plug. We want it relatively big, but not too big. With ClientAliveInterval equals 10, its a good idea to loose the connection after keep-alive messages fail for lets say 5 minutes – 300 seconds. This means we can make ClientAliveCountMax equals 30.

Did you know that you can receive periodical updates with the latest articles that I write right into your email box? Alternatively, you subscribe to the RSS feed!

Want to know how? Check out
Subscribe page

70 Comments

  1. Jacob Boyko says:

    I was able to use these instructions to accomplish the desired result (SSH to Linux box @ work behind a NAT) without the additional server. (Thanks for the well written instructions by the way :) I just used my home Linux machine AS the server. I assume this wouldn’t have worked if my home computer was also also behind a NAT unless in conjunction with port forwarding etc, though I’ve yet to try. Thanks again!

    Oh, for anyone looking for a good Windoze remote control option, try logmein.com – it has a great free remote desktop service (but not for Linux).

    Cheers, JAB

  2. @Jacob Boyko
    Jacob, I am glad you found this useful :-) Please visit my web-site again :-)

  3. Ollie Gooch says:

    OMG Finally! That damn “GatewayPorts yes” took me 2 hours of googling to find out :(

    Thanks Alex! :D

  4. @Ollie Gooch
    I am happy I could help. Please visit again :-)

  5. androidx219 says:

    hey, your tutorial is great.. butt, i believe u can easily remove that additional server and u could directly access your office computer without it.
    For this to work, you have to install an ssh server on your home computer itself and then take a free domain name from dyndns.org.( a very nice service). Then you can connect to your home computer from anywhere on the internet even when your ip changes dynamically. Configure your office computer just to connect to your home computer instead of that server and it would work fine.
    It works like a charm for me as my office computer is inside a nazi firewall which allows the port 443 for outgoing connection through a proxy. I installed an ssh server at my home computer (cygwin) and configured it at port 443. configured the office computer to connect to the free domain name i got from dyndns.org, and whenever i come online, within seconds i get connected to my office computer and it works great…

    cheers.

  6. @androidx219
    Actually services like dyndns.org are not appropriate here.

    Remember that we’re connecting to office computer. Most likely that it is behind firewall, so the biggest problem here is not to get its IP address, but to actually connect to it.
    Most likely that you are not a system administrator – usually there’s only one system administrator that manages certain firewall and he/she wouldn’t be reading this article. Therefore, most likely that you cannot configure your firewall to allow connecting to some office computer from outside. This is when this article becomes handy.

    Until now, I didn’t find an alternative method of connecting to a computer behind NAT router/firewall (except for direct connection over VPN of course). There are alternatives to method I described in the article – take hamachi, for instance. But hamachi doesn’t always work in setups that I’ve described – wise system administrator will know how to block inbound connection requests over hamachi.

  7. Just to make sure that you all know, I continued my conversation with androidx219 over email. The guy is very shy and didn’t want to continue the conversation here. He asked me to express his ideas about the article.

    He has suggested another way how to connect to a computer behind NAT router. The idea is very nice, as it does not require additional server.
    Without getting into too many details, he suggested to install SSH server on home computer. Then connect from office computer to home computer’s SSH server with reverse SSH tunnel – similarly to how I did it in the article.
    He suggested to use a SSH client called tunnelier. Tunnelier can be configured to reconnect if the connection drops. This way high availability can be achieved.

    A very nice idea indeed.

  8. androidx219 says:

    thanx alex,
    the reconnect and keepalive feature of tunnelier client is great and with dyndns, the need of a third server can be eliminated. But just in case, if even the home computer is firewalled, i.e. both office & home computers are firewalled which is generally a rare case, then definitely my method will fail i.e. we will require a third server and the method suggested by alex will work and will be the only alternative.

  9. GiaGT says:

    Great tutorial!
    The GatewayPorts command solved my problem.

    Thank you

  10. @GiaGT
    Happy to serve you :-) Please visit again and bring all your friends along.

  11. @Ollie Gooch – I agree, had a hard time finding the problem on a freshly installed server! I thought my FW had gone nuts.

  12. Justing says:

    I have been trying for a few days to get this to work correctly… sort of. This is what I have.

    1) I have 3 systems. homelaptop, officecomputer, remotewww. (all Ubuntu)

    2) I CAN connect from officecomputer to remotewww with a reverse tunnel, which allows me to ssh from homelaptop to remotewww and then from remotewww ssh to localhost -p officecomputerPORT

    3) In remotewww I have the GatewayPorts yes located in /etc/ssh/sshd_config

    4) My intent is to be able to be at my homelaptop (or any other system) and do something like this. e.g ( ssh officecomputer_user@remotewww -p officecomputer_userPORT)
    The main goal in this is I would like to establish several computer connections to the remotewww and use it to locate my remote systems.

    on remotewww a netstat -tnl shows 127.0.0.1:officecomputerPORT

    either way I am unable to connect from homelaptop like such ssh officecomputer_user@remotewww -p officecomputer_userPORT

    I get the following error (ssh: connect to host 64.xxx.xxx.xxx port 2222: Connection refused)

    Any help?
    I seen some stuff like this (ssh -R 89.xxx.xx.4:2210:localhost:22 bserver.outside.com) (from this site:http://toic.org/2009/01/18/reverse-ssh-port-forwarding/) but cant seem to get that working either.. (though it sounds like what were trying to do)

  13. Justing says:

    @Justing
    Just an update. I was restarting ssh services over an ssh connection, this seems to not work and needed a system restart (or a restart from the console perhaps.) anyhow all is working now.

    Thanks a million worked wonderful

  14. @Justing
    So, just to make things clear, is it working now?

  15. Justing says:

    Yea it works find now, had a bit tweaking for my liking but it works perfect now. Have even redirected VNC of an iPod from another network to my system using the same trick.

    @Alexander Sandler -

  16. A lot of thanks for that fascinating write up! I found your post quite interesting, I think you are a outstanding article writer. I actually added your weblog to my favorites and definately will come back again. Continue the fantastic job!

  17. @Shamwow Vince
    Thanks for a warm comment. Please bring along all your friends as well ;D

  18. Arun says:

    To avoid ssh expiration, use the autossh package. (available on cygwin and standard linux installations).

  19. T says:

    Oh this is lovely. thank you so much.

  20. @T
    Thanks for coming. Please come again :D

  21. Rahul Panwar says:

    Wow,
    Its really amazing, now i can connect to any port (21,22,80,5900 etc) of my office local PCs from my home PC.

    I can say Firewall bye bye. Is there any way to avoid this ;-).
    In firewall, if port 22 is blocked, i can change the port of SSH gateway to some other general port like 443 or 80.

    Thanks for this interesting article.
    Rahul Panwar

  22. @Rahul Panwar
    Don’t throw your firewall away. It allows SSH to slip in, but it blocks everything else so keep it for awhile :-)

  23. Rahul Panwar says:

    @Alexander Sandler
    ;) I am not going to throw it, but i want to know the method to stop it. If i am a network admin, how can i stop the lan users to allow the remote access of their PC?

    Thanks for your reply
    Rahul Panwar

  24. @Rahul Panwar
    You can’t. You can block port 22, but then, they can open ssh connection on port 80. So, the only way to overcome this problem is to block their internet access :-)

  25. Vinod says:

    Hey Alex,

    Liked your article on reverse ssh tunneling. It was really useful for a problem I’m trying to solve.

    I have a question though. How do we keep the reverse-ssh tunnel active?

    As I see it, a “ServerAliveInterval” will only keep-alive the forward connection, not the reverse? Wouldn’t the NAT block the reverse channel, if there is no traffic for some time?

    And since, a since a reverse SSH tunnel doesnot actually setup a ssh connection in the reverse direction (unless someone connects), even a “ClientAliveInterval” doesn’t work?

    thanks,
    Vinod

  26. Hale says:

    Is it possible to make the home pc and office pc to communicate directly? I mean, after the remote connection is established, the data goes p2p?

  27. androidx219 says:

    @Hale
    After the remote connection is established by the above described method, you may either have shell access (X=22) or vnc type remote access (X=5900) to office computer whatever you prefer. Now you can use this connection to establish a new connection directly from office computer to the home computer by using the IP of your home computer/router (with appropriate port forwardings in case you use a router). You may use the ssh service of the home computer or whatever service you might like to use. Once this new p2p connection is established, the previous indirect connection can be terminated.
    I dont think there is any other way to accomplish direct connection in this type of a setup.

  28. @Hale
    There’s no way to establish p2p connection bypassing NAT/firewall without some serious TCP magic. I know one application that does this kind of magic. It’s called hamachi (logmein.com).

  29. androidx219 says:

    @Alexander Sandler
    Are you sure that logmein enables the computers establish a p2p link. I had used logmein earlier and i could not see the remote computer’s nat/external ip in my connection list (using tcpview in windows) when using the remote desktop feature. May be i did’nt notice carefully, i used it long back. If it really helps establishing a p2p link then its great.

  30. Rahul Panwar says:

    @androidx219@androidx219 – Logmein client creates a connection with a remote public server & that remote public server connect your system to other system. It is not P2P.

  31. @androidx219
    Yes, I am sure about it. I don’t know how you used their products before. Hamachi creates P2P connection.

    @Rahul Panwar
    I am afraid you’re mistaken. Hamachi creates P2P connections. If it cannot bypass firewall it will drop do relay mode (with server in the middle, like you described). Naturally relay mode is very slow. However, normally it will be P2P.

  32. Rahul Panwar says:

    @Alexander Sandler – Thanks for giving this information, i was always using it through a firewall. But i will definitely try it without any firewall. ;)

  33. I absolutely accept what you have stated. In fact, I browsed through your other articles and I do believe you are completely correct. Great job with this online site.

  34. Neil says:

    thanks! is it ok to run

    ssh -R 6333:localhost:X user_on_server@server

    as a cron job?

  35. Ivan says:

    Hey, the most interesting part I expected is where I can find the server visible from both Office and Home computer?

  36. Tom says:

    Hi Alexander,

    Quick question please: I`m using putty to connect to my home SSh server, but I just can`t figure out how to create the reverse connection. There is no one in the office to ask to execute the commands for myself and I`m not sure what commands do I need to run in advance myself.
    The method I`m using is similar to the one described by androidx219..
    Please advise.
    Thank you,

    Tom.

  37. Tom says:

    @androidx219 – “and whenever i come online, within seconds i get connected to my office computer” – please advise how :).
    I`m using Putty to connect from work to my home SSH server, but not sure how to set-up the reverse connection…?

  38. androidx219 says:

    @Tom

    My home computer gets a public ip when connected to internet and any client can connect to it at port 443, (if it knows the ip/domain name). At my office, I have installed tunnelier (a windows client) and I have coupled it with firedaemonlite (a free program that can run any program as a system service). Now the tunnelier client is configured to connect to my home computer (ssh server) continuously even if my home computer (ssh server) is not online.
    When I am at home and my home pc is offline, the office computer keeps on persistently trying to connect to my home computer at the given domain name and obviously fails.
    Whenever I connect to internet i.e. come online, the dynamic ip of my home computer gets updated with the domain name and the continuous hits from the office pc (tunnelier client) become successful.
    So now, a successful connection is established from office pc to home pc when the home pc comes online.
    The reconnect feature of tunnelier client and the server feature of firedaemonlite make it possible that no manual intervention is required at the office end. Tunnelier client is feature rich.

    If a successful connection from office to home is not a problem, then things become very simple. To allow reverse connections from home to office, you have to run certain commands in advance when connecting from office (putty) to home ssh server. Then you will not be requiring any person in office. In Putty, you have to go to Connections -> SSH -> Tunnels -> select Remote. In Source type: and in Destination, type: where X is the port number as described in alex’s example. And then connect to home server.

    Images in the link: http://www.smythies.com/~doug/network/reverse_ssh_tunnel/index.html
    should help.

    If you still have a problem, you can revert back.

  39. androidx219 says:

    in source you have to type: “6333″ and in Destination, you have to type “127.0.0.1:X”

    These got omitted from the above comment due to some formatting problem.

    Then any connection to 127.0.0.1:6333 will get forwarded to your office computer’s port number X.

  40. fireforce blaze says:

    Hi Alex,
    It is really a very nice and informative article. I am sure it has helped a lot of people and is going to help many others in future. I am sure to tell my friends about your article.
    I have a question to ask. Could you shed some light on the way some of the commercial remote desktop sharing applications work? I mean do they use the technology of ssh server as mentioned in your article or do they use some thing else. The particular professional remote PC control application I am talking about are Ammyy Admin and TeamViewer.
    These applications have really intrigued me. I really wonder how is it possible that they connect to remote machines so seamlessly without modification of firewall/router settings as what they claim in their websites.
    Could you please share some information on this. I am sure there are many people like me who want to know about this. It would be really nice if you could come up with any article on this topic on remote desktop sharing like the one you did here on ssh server.
    Thanks again for your excellent article.

    FireForceBlaze
    fireforceblaze@gmail.com

  41. androidx219 says:

    @FireForceBlaze

    This is probably possible because of TCP/UDP Hole punching method. Refer to point 3.4 and 4.2 in this link (http://www.brynosaurus.com/pub/net/p2pnat/)when both communicating systems are behind firewall.

  42. fireforce blaze says:

    @androidx219 – Hi androidx219,
    Thank you so much for your response. I will surely look into the above mentioned article and revert back to you. Thanks once again.

  43. [...] signifie que nous pouvons faireClientAliveCountMax est égal à 30. Article de référence :  http://www.alexonlinux.com/reverse-ssh-tunnel-or-connecting-to-computer-behind-nat-router Ce contenu a été publié dans Non classé par admin. Mettez-le en favori avec son [...]

  44. Angel Genchev says:

    @androidx219 – Thank you for the article link. I was wondering how OpenArena (ioQuake3) game engine punched an UDP hole in my NATting firewall and connected to a game server.
    And about teamviewer, logmein, I was wondering how they could afford to pass all communication between pairs of natted clients through their servers.
    For a pair of NATted (I mean client behind NAT) and not NATted clients I figured myself that the server is coordinating the connection to originate from the NATted to the non NATted client.(NATted client ought to do periodic checks for “incomming” connection with the server).

  45. hidemy ip says:

    Anonymous Web Surfing – Safeguard your privateness and go over your tracks! Choose from one of our numerous phony proxy IP addresses for completely anonymous searching.

  46. [...] struggling on this and can't get it to work. Googling around for similar solutions brought me to http://www.alexonlinux.com/reverse-s…ind-nat-router and I tried it and it works well. However, the issue I'm facing there is, it's not making a [...]

  47. Bizres says:

    Alex, I struggled for MONTHS to get access to my PC behind a NAT and your guide helped me succeed. Thanks so much.

    I do have a question or two on this, pls.

    Firstly, what I’ve been working on, is a PC that will act as a server ‘Office Computer’, so it’s going to be an unattended Linux machine with no GUI and no keyboard, Monitor or Mouse, so I’d need this ‘Office Computer’ to be permanently connected to the ‘Server’ (you’ve shown in the diagram).
    Could setting up a cron (that runs every minute) for the command you’ve said above (ssh -R 6333:localhost:X user_on_server@server) do the job?

    Secondly, this ‘Office Computer’ that’s behind a NAT also has admin programs like Webmin and Nagios.
    How can I access these from ‘Home Computer’?

    What makes the scenario odd is, that even my ‘Home Computer’ is behind a NAT – in our place, all ISP’s connect us behind their NAT to which we have no access.

    Thanks.

Leave a Reply


9 − = six