How to Setup Reverse SSH Tunnel on Linux

Reverse SSH is a technique that can be used to access systems (that are behind a firewall) from the outside world.

As you already know SSH is a network protocol that supports cryptographic communication between network nodes. Using this protocol, you can do a secure remote login, secure copy from/to a remote machine etc.

You’ll typically do the following to connect to a remote server securely using ssh command.

$ ssh [your-account-login]@[server-ip]

What is Reverse SSH?

SSH is very good tool to access remote machine or server securely. But, the problem arises when you try to connect to a remote server which is behind a firewall and this firewall denies any incoming connection or data transfer request that has no prior outgoing request. This means that only those connections would be allowed which are initiated by the remote server machine. This is a real problem for those who want to access this server machine remotely.

Reverse SSH provides a technique through which you can simulate a normal SSH to this remote server machine.

The main problem is that firewall is rejecting ssh connection that your machine is trying to establish with remote server machine. But you know that the same firewall will not have any problem with the connections originating from server machine. So, why not ask some one who is sitting behind the firewall to do something with which you can achieve your goal of remotely accessing the server. To do this we have to use ssh -R option.

This is the description of the ssh -R option from the man page:

-R [bind_address:]port:host:hostport

Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side. This works by allocating a socket to listen to port on the remote side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to host port hostport from the local machine.

So you can use ssh command, with -R option, (from server in our case) to connect to your machine, allocate a port there and make sure that any connection request on that port is forwarded to ssh port of the remote server.

Instead of your machine doing an ssh, the server machine does an ssh and through port forwarding makes sure that you can ssh back to server machine.

How to Create a Reverse SSH Tunnel?

Here is the command your friend sitting on remote server side should run on the server :

ssh -fN -R 7000:localhost:22 username@yourMachine-ipaddress

So this ssh connection request originating from remote server to your machine will make sure that any ssh connection request for port 7000 on your machine is forwarded to port 22 of remote server.

Now do an ssh connection request from your machine to your own machine at port 7000:

ssh username@localhost -p 7000

Here, though it may seem like you are doing ssh on localhost but your request would be forwarded to remote host. So, you should use your account ‘username’ on remote server and when prompted for password, enter the corresponding password.

This should clear most of the aspects related to reverse ssh technique. But, there is one catch. The catch is that you have to ask a friend of yours — who is sitting behind the firewall — to create an ssh connection first. This is not feasible every time.

To overcome this problem, what you can do is that you can set up a machine which is out of firewall (just like yours) in a way that it is always on. Lets call this machine as machine_z.

The benefit of machine_z is that you can once do this reverse ssh set up on it and leave it like this. At any point of time, when you need to login to remote machine, you can ssh into machine_z on a specified port (as shown earlier) and your connection request will be forwarded to remote server machine and Voila, you will be running commands on remote server.

On a related note, you can also setup no password SSH to connect to another server without entering the password.

Some settings that you need to configure on machine_z would include :

  • Make sure that the parameters TCPKeepAlive, ClientAliveInterval, ClientAliveCountMax and GatewayPorts are set to appropriate values. These parameters are found in /etc/sshd_config or /etc/ssh/sshd_config file
  • If you make some changes to above parameters, you should restart sshd daemon to reflect the changes.
  • Also, make sure that you run the first ssh command (that is executed from the remote server to machine_z) using nohup command so that this ssh session becomes immune to hangups which can happen when a user logs out.