#!/bin/bash function usage() { echo "SYNOPSYS $0 [OPTIONS] DESCRIPTION Spawn TCP tunnels between your computer and a remote SSH server. If the connection fail for some reason, the script will try to re-create the tunnels automatically every TIMEOUT seconds. OPTIONS -S,--server=HOST Set the tunnel host. HOST can be either the IP or hostname of the server to tunnel to, as seen from the ssh host. -t, --tunnel=TUNNELPORT Specify the ports to tunnel. -i, --interface=IF Specify the interface to listen on. -H,--host=SSHHOST Set the ssh host. SSHHOST can be either the full hostname as you would specify it on the ssh command-line (e.g. user@example.com or hostname if it is set up in your ssh config). -p, --port=SSHPORT Set the ssh remote port if different from the default. -f Fork the script to the background. -h,--help Print this help and exit. " } # Help argument if [[ " $@" = *" -h"* || " $@" = *" --help"* ]]; then usage exit 0 fi #if [[ -z "$@" || " $@" != *" --ok"* ]]; then # echo 'This script will only do something if `--ok` is provided' # echo '' # usage # echo '' # echo 'Nothing has been done. Exiting.' # exit 1 #fi # Logfile location # comment to use stdout/stderr LOGFILE=proxy.log LOGFILE_ERR=proxy.log # Local bind address # - Use 127.0.0.1 for local computer only; # - Use 0.0.0.0 to give access to other computers (but be careful who can # reach your computer in that case, if you do not have a firewall, your LAN # (at least) normally has access to all your ports (most routers, through # NAT, provide basic firewall functionality)) #LOCAL_BIND_ADDR=0.0.0.0 LOCAL_BIND_ADDR=127.0.0.1 # License host and ports REMOTE_LICENSE_HOST=licence.inl90.ec-lyon.fr DASHBOARD_PORT=8095 FLEX_PORT=27011 LUMERICAL_VENDOR_PORT=42128 # ssh host HOST=sshgate # set default log to stdout/stderr LOGFILE=${LOGFILE:-/dev/stdout} LOGFILE_ERR=${LOGFILE_ERR:-/dev/stderr} function start_and_monitor_tunnels() { # This function takes port numbers as arguments and creates as many TCP # tunnels like so: # LOCAL_BIND_ADDR:$port <--> HOST <--> REMOTE_LICENSE_HOST:$port # If the tunnel fails or ssh exits, we either: # - try again after a timeout if exit code is not 0 # - exit if exit code is 0 # NOTE: for now we just **always** try again after timeout local ports=$@ local timeout_sec=10 declare -a ssh_tunnel_opt for port in ${ports}; do ssh_tunnel_opt+=("-L") ssh_tunnel_opt+=("${LOCAL_BIND_ADDR}:${port}:${REMOTE_LICENSE_HOST}:${port}") done while true; do # Try establishing the tunnel echo "Starting tunnel for ports ${ports[@]}" ssh -N \ ${ssh_tunnel_opt[@]} \ -o "ServerAliveInterval 10" \ -o "ServerAliveCountMax 3" \ -o "ExitOnForwardFailure yes" \ ${HOST} & local pid="$!" # make sure to kill ssh when killed/parent exits trap "kill '$pid'" EXIT wait local exit_code="$?" echo "ssh exited with exit code ${exit_code}" #if [[ ${exit_code} != 0 ]]; then if true; then # If ssh exited with non-zero code, wait a bit and retry echo "restarting in ${timeout_sec}s..." sleep ${timeout_sec} else echo "exiting." return 0 fi done } # Start the tunnels and redirect outputs echo "Setting up tunnels. Logs will be redirected to: stdout --> ${LOGFILE} stderr --> ${LOGFILE_ERR} " # In the following block, the following redirections are set up: # - 777 goes to stdout of current script (and not global /dev/stdout) # - 1 goes to $LOGFILE # - 2 goes to $LOGFILE_ERR { # Enable trace set -x # Set up CTRL-C callback (write to stdout of script, not log) trap_ctrl_c_callback=" echo 'Interrupt signal received, exiting...' 1>&777 exit 130 " trap "${trap_ctrl_c_callback}" SIGINT ports=(${DASHBOARD_PORT} ${FLEX_PORT} ${LUMERICAL_VENDOR_PORT}) start_and_monitor_tunnels ${ports[@]} } 777>&1 1>>${LOGFILE} 2>>${LOGFILE_ERR}