Search code examples
linuxbashssh

How to set up an automatic (re)start of a background ssh tunnel


I am a beginner user of linux, and also quite newbie at ssh and tunnels.

Anyway, my goal is to maintain a ssh tunnel open in background.

In order to do that, I wrote the following batch that I then added into crontab (the batch is automatically processed every 5 minutes during workdays and from 8am to 9pm). I read in some other thread in stackoverflow that one should use autossh that will ensure the ssh will always be ok through a recurrent check. So did I....

#!/bin/bash
LOGFILE="/root/Tunnel/logBatchRestart.log"
NOW="$(date +%d/%m/%Y' - '%H:%M)" # date & time of log

if ! ps ax | grep ssh | grep tunnelToto &> /dev/null
then
    echo "[$NOW] ssh tunnel not running : restarting it" >> $LOGFILE
    autossh -f -N -L pppp:tunnelToto:nnnnn [email protected] -p qqqq
    if ! ps ax | grep ssh | grep toto &> /dev/null
    then
            echo "[$NOW] failed starting tunnel" >> $LOGFILE
    else
            echo "[$NOW] restart successfull" >> $LOGFILE
    fi
fi

My problem is that sometimes the tunnel stops working, although every thing looks ok (ps ax | grep ssh > the result shows the two expected tasks : autossh main task and the ssh tunnel itself). I actually know about the problem cause the tunnel is used by a third party software that triggers an error as soon as the tunnel is no more responding.

SO I am wondering how I should improve my batch in order It will be able to check the tunnel and restart it if it happens to be dead. I saw some ideas in there, but it was concluded by the "autossh" hint... which I already use. Thus, I am out of ideas... If any of you have, I'd gladly have a look at them!

Thanks for taking interest in my question, and for your (maybe) suggestions!


Solution

  • Instead of checking the ssh process with ps you can do the following trick

    create script, that does the following and add it to your crontab via crontab -e

    #!/bin/sh
    
    REMOTEUSER=username
    REMOTEHOST=remotehost 
    
    SSH_REMOTEPORT=22
    SSH_LOCALPORT=10022
    
    TUNNEL_REMOTEPORT=8080
    TUNNEL_LOCALPORT=8080
    
    createTunnel() {
        /usr/bin/ssh -f -N  -L$SSH_LOCALPORT:$REMOTEHOST:SSH_REMOTEPORT -L$TUNNEL_LOCALPORT:$REMOTEHOST:TUNNEL_REMOTEPORT $REMOTEUSER@$REMOTEHOST
        if [[ $? -eq 0 ]]; then
            echo Tunnel to $REMOTEHOST created successfully
        else
            echo An error occurred creating a tunnel to $REMOTEHOST RC was $?
        fi
    }
    
    ## Run the 'ls' command remotely.  If it returns non-zero, then create a new connection
    /usr/bin/ssh -p $SSH_LOCALPORT $REMOTEUSER@localhost ls >/dev/null 2>&1
    if [[ $? -ne 0 ]]; then
        echo Creating new tunnel connection
        createTunnel
    fi
    

    In fact, this script will open two ports

    • port 22 which will be used to check if the tunnel is still alive
    • port 8080 which is the port you might want to use

    Please check and send me further questions via comments