Files
q-tools/web/ssh-tunnelier
ville rantanen e38f0ff835 posix friendly
2017-09-04 08:46:56 +03:00

165 lines
4.1 KiB
Bash
Executable File

#!/bin/bash
CONFDIR="$HOME/.config/ssh-tunnelier"
CONF="$CONFDIR/config"
# Just over a year in minutes
MAGIC_TIME=525601
BASE="base64 -w 0"
UNBASE="base64 -d"
if [[ "$OSTYPE" = "darwin"* ]]; then
BASE="base64"
UNBASE="base64 -D"
fi
function _helpexit() {
echo "SSH tunnel manager
Runs and monitors preconfigured background ssh tunnels, with the ability
to kill existing ssh processes. You don't need to keep the program on
to remember connected sessions.
Configuration stored in: $CONF
If run with arguments, runs an ssh tunnel with arguments:
ssh-tunnelier hostname [local-port] remote-port
If local port missing, the same port assumed in local
"
exit 0
}
for (( i=1; i<=$#; i++ )); do
[[ ${!i} = "-h" ]] && _helpexit
[[ ${!i} = "--help" ]] && _helpexit
done
[[ -f "$CONF" ]] || {
echo No config file.
echo "$CONF" each line like:
echo -L 8888:localhost:8888 servername
mkdir -p "$CONFDIR"
echo -e "# example:\n -L 8888:localhost:8888 servername" > "$CONF"
}
number_re='^[0-9]+$'
# import qolop
_qCol(){ true; } # incase qolop missing
. qolop &>/dev/null
colZ=$( _qCol z )
colTitle=$( _qCol z G )
colRow=$( _qCol z S )
colMenu=$( _qCol z y )
colWarn=$( _qCol z R )
function fpgrep() {
[[ -z $( pgrep -x -u $UID "$@" ) ]] && { echo '----'; return; }
pgrep -x -u $UID "$@" | xargs ps -o pid,start,args
}
function get_id() {
id=$( printf "%s" "$line" | $BASE )
echo -n $id
}
function get_command() {
switches=$( echo "$1" | $UNBASE )
echo -n "ssh -f -n $switches \"nice /bin/bash -c 'for ((i=1;i<$MAGIC_TIME;i++)); do cut -f4 -d \\\" \\\" /proc/\\\$PPID/stat | xargs kill -0 || exit ; sleep 60;done'; echo tunnelier $1\""
}
function get_pid() {
pgrep -f "$MAGIC_TIME.*echo tunnelier $1" | head -n 1
}
function list_all_ssh() {
printf "\n${colTitle}=============================================\n"
printf "${colTitle} List of SSH:${colZ}\n"
printf "${colTitle}Enter PID to kill, empty to return $colZ\n"
printf "${colTitle}Outgoing SSH processes\n"
printf "${colTitle}=============================================\n${colRow}"
fpgrep ssh
printf "${colTitle}Incoming SSH processes\n"
printf "${colTitle}=============================================\n${colRow}"
fpgrep sshd
read -t 600 inputpid
[[ "$inputpid" =~ $number_re ]] && {
ask_to_kill $inputpid
}
}
function read_config() {
while read line; do
id=$( get_id "$line" )
pid=$( get_pid "$id" )
printf "%-3d %-7s %s\n" $i "$pid" "$line"
ids+=( $id )
i=$(( i + 1 ))
done < <( grep -v ^# "$CONF" | grep '[a-zA-Z]' )
}
function run_args() {
HOST="$1"
LOCAL="$2"
REMOTE="$3"
[[ -z "$REMOTE" ]] && REMOTE="$LOCAL"
echo Connect to $HOST
switches=$( echo '-L "${LOCAL}:localhost:${REMOTE}" "$HOST"' | $BASE )
run_command "$switches"
}
function run_command() {
eval $( get_command "$1" )
}
function ask_to_kill() {
printf "${colRow}"
ps -o pid,bsdstart,args "$1"
printf "\n k kill\n t terminate${colZ}\n"
read -t 600 input2
[[ "$input2" = "k" ]] && kill $1
[[ "$input2" = "t" ]] && kill -9 $1
}
[[ -n "$2" ]] && {
run_args "$@"
}
while true; do
ids=()
i=1
printf "\n${colTitle}=============================================\n"
printf "${colTitle} List of tunnels:${colZ}\n"
printf "${colTitle} (q)uit (e)dit (l)ist ssh [%s]${colZ}\n" $( date +%H:%M )
printf "${colTitle}=============================================\n"
printf "${colRow}ID PID command\n"
read_config
printf "$colZ"
read -t 600 input
[[ "$input" = "q" ]] && exit 0
[[ "$input" = "e" ]] && vim "$CONF"
[[ "$input" = "l" ]] && list_all_ssh
[[ "$input" = "0" ]] && continue
[[ "$input" =~ $number_re ]] && {
j=$(( $input - 1 ))
[[ $j -gt $(( $i - 1 )) ]] && {
printf "${colWarn}No such tunnel number${colZ}\n"
continue
}
printf "\n${colTitle}Tunnel command: %s${colZ}\n" "$( echo "${ids[$j]}" | $UNBASE )"
this_pid="$( get_pid "${ids[$j]}" )"
[[ -n "$this_pid" ]] && {
# PID exists, ask to kill
ask_to_kill "$this_pid"
}
[[ -z "$this_pid" ]] && {
# PID empty, run
run_command "${ids[$j]}"
sleep 1
}
}
done