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
}
 
Add this to .ssh/config for keepalive:
<code>
 
Host *
    ServerAliveInterval 60

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 </code>

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