Skip to content

Configuring a self-restoring reverse SSH tunnel

No time to make it a proper post, so I’ll mainly post the syntax and files to edit. Here I’m creating a reverse SSH tunnel to be able to access my GNU/Linux machine behind a work firewall, via another Linux machine (a VPS or dedicated server running Linux too) as a relay. Then I use any PC (it’s really as easy on Windows and Linux for this part) with PuTTY to connect to it. If the machine behind the firewall is on Windows and you know Windows enough to modify the batch file accordingly and add it at start-up, you’ll probably still find the guide useful. If the machine you want to use as a relay runs on Windows, well good luck setting up OpenSSH on it… 🙁

List of stuff to install (if not already present):
On the relay: openssh-server, webmin (optional)
On the firewalled machine: plink (in package putty-tools I think), sudo

On the relay, make sure OpenSSH allows opening gateway ports. The config file is /etc/ssh/sshd_config. Just add or modify:
GatewayPorts yes
NB: in previous guides, I used to set this to GatewayPorts clientspecified, but for some reason (maybe I lost a plink option or something), at the moment “clientspecified” is not working.

Optionally, still on the relay, create a user just for the tunneling (useradd XX, then password XX). This way you can give it a specific password (for the sake of simplicity I won’t be using a key but a password) and disable the shell, so as to only allow tunneling but note typing commands. To do so, we’ll use a shell I found here and there: create for instance a file named /usr/bin/tunnel_shell with the following content:

echo -e "\r\n\033[32mSSH tunnel started, shell disabled by the system administrator\r\n"
while [ true ] ; do
sleep 1000
exit 0

Then make sure it’s executable (for instance chmod 755), and set it as the shell for the tunnel-specific user (for this I used Webmin, in System → Users and Groups).

On the firewalled machine, create a bash script (eg /home/ containing something like:

while [ true ] ; do
plink -ssh -P 22 -pw [password] -N -R 4444: [usernam]@[relayIP]
sleep 120
exit 0

It’s an infinite loop, that tries to connect every 120 seconds to [relayIP] (IP of the relay machine). 4444 is the port on [relayIP] that will be forwarded to port 22 on the firewalled machine (you can choose any port you like, of course). Check out the plink documentation if some arguments are unclear.
You could now test the command alone (the whole “plink” line) to see if it properly connects to your relay and establishes the tunnel (try connecting to [relayIP]:22).

Finally, we will add the script to be launched at start-up on the firewalled machine. First I advise you to create a specific user that will launch the script, so that it will be easier to spot in top (there’s no easy way to stop the script, so the simplest way I found is to get its PIDs via top and kill them).
Then in Webmin, go to System → Bootup and Shutdown, then Create a new bootup and shutdown action. Enter a short name (eg, a description (eg My reverse tunnel), and in the Bootup commands field, enter sudo -u [username] /home/ Of course, enable Start at boot time.
NB: when you validate, Webmin will create a little wrapper script around your command. But as of version 1.660, if you leave the stop block empty, it will neglect to add a
"# Default-Stop:" line in the INIT INFO section. You should add it manually if you want to avoid this kind of warning:
insserv: missing `Default-Stop:' entry: please add even if empty.
insserv: Script is broken: incomplete LSB comment.

That’s about it. Next time you restart the firewalled machine, it will connect to the relay and establish the reverse tunnel, and you can connect with PuTTY to [relayIP]:4444. Note that the first time you connect, plink will ask you to confirm the relay’s RSA key: this requires manual input (you need to respond yes), so before running the script you should establish a connection manually, with the same user as the one which will be running the tunnel automatically. Long story short, just run sudo -u [username] /home/ yourself before letting the script do it itself.

Posted in Linux, web filtering.

Tagged with .

One Response

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. patheticcockroach says


    When configuring to run at startup, you may encounter an error message with sudo, saying “Executable path is not absolute”. To fix it, replace sudo with its full path, ie /usr/bin/sudo

    You might run into trouble when trying to memorize the server’s key as a trusted key. Namely:
    ERROR: Unable to store host key: open("/root/.putty/sshhostkeys.tmp") returned 'Permission denied'
    In this case, a workaround I use is to connect and add the key as trusted using the root account, and then copying or moving the /root/.putty/sshhostkeys file into /home/[username]/.putty/

Some HTML is OK

or, reply to this post via trackback.

Sorry about the CAPTCHA that requires JS. If you really don't want to enable JS and still want to comment, you can send me your comment via e-mail and I'll post it for you.

Please solve the CAPTCHA below in order to fight spamWordPress CAPTCHA