Skip to content

Instantly share code, notes, and snippets.

@blakewrege
Created October 9, 2015 05:52
Show Gist options
  • Save blakewrege/bd61cbe398aa3374a923 to your computer and use it in GitHub Desktop.
Save blakewrege/bd61cbe398aa3374a923 to your computer and use it in GitHub Desktop.
reverse tunnel ssh script
#!/bin/bash
# Script: rssht (Reverse SSH Tunnel)
# Author: Khizer Naeem (khizernaeem(x)gmail.com)
# Created : 09 Sep 2012
# Version: 1.04
# Latest Revision: 10 Feb 2013
# Tested on: Centos/RHEL 6, Centos/RHEL 5,
# Description: A bash script to maintain reverse ssh tunnel with remote port forwardings.
# URL: http://kxr.me/scripts/rssht_v1.03
#
# Copyright (C) 2013 Khizer Naeem All rights reserved.
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#############################
## CONFIGURATION VARIABLES ##
#############################
REMOTE_HOST=t4ls.duckdns.org # The remote host to which you want to forward the ports
REMOTE_SSH_PORT=22 # SSH port of the remote host
REMOTE_USER=cclub # SSH user for the remote host (Should have password less login from this machine with this user)
SSH_RUN_DIR=/var/run/rssht/ # Directory to keep ssh socket connection and pid file (Should exist)
PORTS_REMOTELY_ACCESSIBLE=yes # If set to yes, -g switch will be used while making the ssh connection. Read ssh manual for detail of -g
SSH_BIN=/usr/bin/ssh # Location of the ssh client on this host
REFRESH_SOCKET=15 # If set to a non-zero integer, this script will restart the ssh session if its that many minutes old.
###########################
## PORT FORWARDING TABLE ##
###########################
REMOTE_FWDS=(
1337:localhost:80
)
#######################
## SSH OPTIONS TABLE ##
#######################
# These options will be passed to ssh with the -o switch e.g -o "ControlMaster yes"
# You can comment this out if you want the script to obey the ssh config
SSH_OPTS=(
'ControlMaster yes'
'PreferredAuthentications publickey'
'Ciphers arcfour256'
'Compression yes'
'TCPKeepAlive yes'
'ServerAliveCountMax 3'
'ServerAliveInterval 10'
)
# /////////////////////////
# // Do not modify below //
# /////////////////////////
###################
## SCRIPT CHECKS ##
###################
if [ "$1" == "install" -o "$1" == "--help" -o "$1" == "-h" ]
then
echo "INSTALLATION INSTRUCTIONS:"
echo
echo "# Set the configuration variables and forwardings"
echo
echo "# Make sure you have ssh keys generated"
echo "ssh-keygen"
echo
echo "# Setup password-less login to the remote host"
echo "ssh-copy-id '$REMOTE_HOST -l $REMOTE_USER -p $REMOTE_SSH_PORT'"
echo
echo "# Add the cron job"
echo "echo '*/5 * * * * root $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/$(basename ${BASH_SOURCE[0]})' > /etc/cron.d/rssht_$REMOTE_HOST"
exit 0
fi
###############################
## SSH CONNECTION EVALUATION ##
###############################
# - If socket exists:
# 1-If the socket is old kill the connection (so that a new one is created)
# 2-Run the check command on the socket
# 2.1- if it passes, do nothing, exit
# 2.2- if it fails kill ssh and remove socket file
# - Run the ssh command
# Socket file
SOCK_FILE="$SSH_RUN_DIR/$REMOTE_HOST.sock"
# PID file
PID_FILE="$SSH_RUN_DIR/ssh_$REMOTE_HOST.pid"
if (mkdir -p $SSH_RUN_DIR)
then :
else
echo "FATAL Error: Cannot create RUN directory $SSH_RUN_DIR/"
fi
if [ -S "$SOCK_FILE" -o "$1" == "stop" ]
then
# If Socket is older than {REFRESH_SOCKET} minutes OR if stop argument is passed, stop the connection
if [ "$REFRESH_SOCKET" -gt "0" -o "$1" == "stop" ]
then
if [ -n "$(find $SOCK_FILE -mmin +$REFRESH_SOCKET)" -o "$1" == "stop" ]
then
if [ "$1" == "stop" ]
then
echo "Stop argument passed, killing .."
else
echo "Existing SSH connection is old, killing .."
fi
# Send the exit command to the existing socket
ssh -O exit -S $SOCK_FILE $REMOTE_HOST &> /dev/null
# Kill the pid if the process some how still exists
if (kill -0 $(cat $PID_FILE) &> /dev/null )
then
echo "killing ssh process $(cat $PID_FILE)"
kill -9 $(cat $PID_FILE) &> /dev/null
fi
rm -rf $PID_FILE &> /dev/null
fi
fi
fi
#If the user passed stop, don't proceed further
[ "$1" == "stop" ] && exit 0
# Check the status of the SSH connection through the socket file
if (ssh -O check -S $SOCK_FILE $REMOTE_HOST &> /dev/null)
then
# SSH connection is fine
echo "ssh connection is fine, exiting"
exit 0
else
# SSH socket check failed
# Try killing the PID first
if [ -e "$PID_FILE" ]
then
if (kill -0 $(cat $PID_FILE) &> /dev/null )
then
echo "killing ssh process $(cat $PID_FILE)"
kill -9 $(cat $PID_FILE) &> /dev/null
rm -rf $PID_FILE &> /dev/null
fi
fi
# Remove the socket if it still exists
if [ -S "$SOCK_FILE" ]
then
if (rm -rf "$SOCK_FILE" &> /dev/null)
then
echo "FATAL ERROR: Cannot remove stalled socket file $SOCK_FILE"
echo "Exiting.."
exit 9
else
echo "Stalled socket file removed"
fi
fi
fi
fi
# The socket and process should be gone by now; If not this is an exception; exit!
# This should not happen
if [ -S "$SOCK_FILE" ]
then
echo "Exception: Cannot remove socket file. SSH connection seems to be stuck"
echo "Exiting"
exit 11
fi
##########################
## SSH COMMAND CREATION ##
##########################
# Whether to use -g switch or not
P_R_A=""
[ "$PORTS_REMOTELY_ACCESSIBLE" == "yes" ] && P_R_A="-g"
# Remote forwardings
RFWDS=""
for i in "${!REMOTE_FWDS[@]}"
do
RFWDS="$RFWDS-R ${REMOTE_FWDS[$i]} "
done
# SSH options
SOPTS=""
for i in "${!SSH_OPTS[@]}"
do
SOPTS="$SOPTS-o '${SSH_OPTS[$i]}' "
done
# SSH final command
SSH_COMMAND="$SSH_BIN $SOPTS $P_R_A -f -q -N -S $SOCK_FILE $RFWDS -p $REMOTE_SSH_PORT -l $REMOTE_USER $REMOTE_HOST"
#####################
## RUN SSH COMMAND ##
#####################
eval "$SSH_COMMAND"
if [ "$?" -ne "0" ]
then
echo "FATAL ERROR: SSH command failed"
echo "SSH_COMMAND=$SSH_COMMAND"
exit 10
else
#Save the PID
SOCK_CHECK=$(ssh -O check -S $SOCK_FILE $REMOTE_HOST 2>&1)
SPID=$(echo $SOCK_CHECK | cut -d'=' -f2 | sed 's/)//')
echo "$SPID" > $PID_FILE
echo "RSSHT to host $REMOTE_USER@$REMOTE_HOST:$REMOTE_SSH_PORT started successfully ssh pid: $SPID"
exit 0
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment