≡ Menu

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.
Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • Jalal Hajigholamali November 27, 2013, 1:55 am

    Thanks for very nice article…

  • Ethan November 27, 2013, 4:27 am

    Very clear.

  • catafest November 27, 2013, 11:01 am

    If I using the PPPoE connection with dynamic IP every time I connected . How to set a ssh tunneling of web browsing ? Can also another way to protect my data ? I use one router with wire – internet and wifi for mobile and tablet. Can this protect me ?

  • Bob November 27, 2013, 12:48 pm

    I always wondered about this. This article clears a lot of my doubts. Thanks!!!

  • Tigerafest November 28, 2013, 10:43 pm


    Internet->your router-> your firewall ( hardware based ) -> your PC ( hardened , latest OS patches applied, installed personal firewall & antivirus { update daily } ).

  • rinshad December 22, 2013, 11:31 am

    Helpful ..

  • Beau June 8, 2015, 8:18 pm

    I must be doing something wrong. I’m trying to set up a persistent reverse tunnel so I can have remote shell access. I’m in test mode right now, and when it looks like I’ve created the tunnel, when I try to ssh to my localhost, I end up with a shell to.. my… localhost.

    What would be some ways to test to see what I am missing or doing wrong?

  • Hasan October 13, 2015, 4:00 am

    Nice article