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.

Related posts:

  1. SSH crash course
  2. Picotux – the smallest Linux Computer in the World
  3. Useful Linux Networking Commands
  4. tcpdump for Dummies

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

18 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. @Justing
    Nice. I am glad to hear that.

  17. 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!

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

Leave a Reply