Reverse ssh tunnel without screen

November 06, 2017

In a previous article we talked about screen, that was used to setup reverse ssh tunnels on deployed infrastructure without the hassle of setting up port-forwarding on every modem thery are deployed behind. Today I will note down a better way to set this up, without screen, in a single crontab.

Without much further ado, the glorious crontab:

*       *       *       *       *       ssh -q -f -N -R 8888:localhost:22 REMOTEUSER@remote.example.com -o "ExitOnForwardFailure yes" -o "ServerAliveInterval 15" -o "ServerAliveCountMax 2" 2>/dev/null

And on remote.example.com to connect to the tunnel (as before):

su REMOTEUSER
ssh LOCALUSER@localhost -p 8888

Why does it work: first, we suppress messages (-q, 2>/dev/null so my /var/spool/mail/LOCALUSER mail does not get uselessly populated after each network hiccup), we detach the ssh command (-f), in batch-mode (-N, no command issued on remote host), then we define the reverse tunnel (-R 8888:localhost:22, redirect port 8888 on remote to port 22 on localhost), we connect as user REMOTEUSER on remote.example.com (REMOTEUSER@remote.example.com), and most importantly we set ExitOnForwardFailure yes so the ssh tunnels exits if it is unable to create the forward tunnel (most notably if it is already set), we define another pair of failsafe so if the connection is cut it will exit after 30 seconds (ServerAliveInterval 15 and ServerAliveCountMax 2, 15*2) of inactivity, so the tunnel could be recreated the next minute when the crontab is executed.

Addentum 2020-02-04: You should probably reduce sshd log verbosity (LogLevel) on the remote server as it appends a new line every minute as the connection fails if already established with ExitOnForwardFailure.

Maybe also/instead you could use flock to define a lock file for the crontab, like this

*       *       *       *       *       flock -w 0 /tmp/sshtunnel.lock ssh -q -f -N -R 8888:localhost:22 REMOTEUSER@remote.example.com -o "ExitOnForwardFailure yes" -o "ServerAliveInterval 15" -o "ServerAliveCountMax 2" 2>/dev/null