User Tools

This is an old revision of the document!


On Local Host

Create a new user called tunnel. Leave tunnel home folder on root partition (/home/tunnel) to avoid tunnel failure if partitions don't mount. You need also to create an SSH key, and prepare the tunnels config folder /home/tunnel/tunnels and log folder /home/tunnel/logs:

 > useradd -m tunnel
 > su - tunnel
 > ssh-keygen
 > mkdir tunnels
 > mkdir logs

Add tunnels configurations like this under /home/tunnel/tunnels/main:

main
REMOTE_SERVER=99.99.99.99 # your remote server IP - don't use name, use IP
REMOTE_SERVER_SSH_PORT=22 # your remote server SSH port
HOME_SERVER_REMOTE_SSH_PORT=5022 # the port your local server SSH will be accessible from remote
SSH_IDENTITY=# optional path to private ssh key, leave empty for default
REMOTE_USER=tunnel # remote user to login as
 
REMOTE_TO_HOME=\
"127.0.0.1:8080:127.0.0.1:80 "\
"127.0.0.1:8443:127.0.0.1:8443 "\
"0.0.0.0:6022:10.70.43.99:22 "\
"0.0.0.0:12112:127.0.0.1:12112 " # list of ports forwarded from remote to local
 
HOME_TO_REMOTE= # list of ports forwarded from local to remote

Remember to “ssh” manually at least once each host to accept host keys!

You can create as many tunnels as you like. Note that SSH port will always be forwarded anyway, so you want one file for each remote host.

Now create this script under /home/tunnel/tunnel.sh:

#!/bin/bash
 
function log()
{
        echo $(date) - $@ >> $LOG
}
 
cd $HOME
TUNNELS=$(ls tunnels)
 
TUNNEL_PIDS=
for i in $TUNNELS
do
        # Spin a shell for each tunnel
        (
        NAME=$i
        CONFIG=tunnels/$NAME
        LOG=logs/tunnel-$NAME
 
        log "Starting operations for tunnel '$NAME'..."
 
        # Iterate forever
        while true
        do
                # Spin up a sub-shell to ensure we reload the config properly each iteration
                (log "Reading configuration from '$CONFIG'..."
                source $CONFIG
 
                log "Testing if remote server '$REMOTE_SERVER' is reachable..."
                if ping -c 10 -W 5 $REMOTE_SERVER &> /dev/null
                then
                        log "Remote server '$REMOTE_SERVER' is reachable!"
 
                        LOGIN_IDENTITY=
                        test ! -z $SSH_IDENTITY && LOGIN_IDENTITY="-i $SSH_IDENTITY"
                        LOGIN_AS=$USER
                        test ! -z $REMOTE_USER  && LOGIN_AS="-l $REMOTE_USER"
 
                        REMOTES="-R0.0.0.0:$HOME_SERVER_REMOTE_SSH_PORT:127.0.0.1:22" # SSH port we always export
                        LOCALS=
                        for i in $REMOTE_TO_HOME; do REMOTES="$REMOTES -R$i"; done
                        for i in $HOME_TO_REMOTE; do LOCALS="$LOCALS -L$i"; done
 
                        COMMAND="ssh $LOCALS $REMOTES $LOGIN_IDENTITY $LOGIN_IDENTITY $LOGIN_AS -p $REMOTE_SERVER_SSH_PORT $REMOTE_SERVER -nNT"
 
                        log "Run: '$COMMAND'..."
                        $COMMAND &>> $LOG &
                        ssh_pid=$!
 
                        # Wait a bit to ensure command is running...
                        sleep 1
 
                        # until SSH returns, check network, because SSH might hang for a long time.
                        while ps -p $ssh_pid &> /dev/null
                        do
                                if ping -c 2 -W 2 $REMOTE_SERVER &> /dev/null
                                then
                                        sleep 30
                                else
                                        # Network is down? forcing ssh to stop
                                        log "WATCHDOG: Detected '$REMOTE_SERVER' is NOT reachable! Killing command."
                                        kill -9 $ssh_pid
                                        while ps -p $ssh_pid; do sleep 1; done
                                fi
                        done
 
                        # get return code
                        wait $ssh_pid
                        log "Command returned code '$?'. Retrying..."
                        sleep 10 # after disconnection, wait a bit before retrying
                else
                        log "It seems that '$REMOTE_SERVER' is not reachable. Wait and retry..."
                        sleep 5 # wait a bit before retry ping
                fi
                ) # close iteration shell
        done
        )& # close tunnel shell
        TUNNEL_PIDS="$TUNNEL_PIDS "$!
done
 
wait

and set it as executable:

 > chmod +x /home/tunnel/tunnel.sh

Now create the startup script /etc/local.d/99-tunnels.start:

99-tunnels.start
#!/bin/bash
 
start-stop-daemon -b -m -p /var/run/tunnel.pid -n tunnel -u tunnel /home/tunnel/tunnel.sh

Share tunnel's /home/tunnel/.ssh/id_rsa.pub with remote host, paste it inside authorized_hosts file of remote tunnel user.

This website uses technical cookies only. No information is shared with anybody or used in any way but provide the website in your browser.

More information