Use SSH Multiplexing

This commit is contained in:
Kevin Baensch 2022-11-17 13:01:07 +01:00
parent d686edef9d
commit 2e3a1ae389
3 changed files with 66 additions and 46 deletions

View file

@ -1,49 +1,57 @@
#!/usr/bin/env bash #!/usr/bin/env bash
[ -z $SQL_PROXY_HOST ] && SQL_PROXY_HOST="localhost" [ -z $SQL_PROXY_HOST ] && SQL_PROXY_HOST="localhost"
CACHE_FILE="$HOME/.cache/sqlproxy_$SQL_PROXY_HOST" CONNECTION_CACHE="$HOME/.cache/sqlproxy_$SQL_PROXY_HOST"
HELP="Usage: myssh [ls|connect] HELP="Usage: myssh [ls|connect]
SUBCOMMANDS: SUBCOMMANDS:
ls: list available database hosts ls: list available database hosts
connect: connect to a database host connect: connect to a database host
disconnect: Quit existing ssh master session
SYNTAX connect host [-u user] [-p password] [-c client] SYNTAX connect host [-u user] [-p password] [-c client]
" "
ls() { ssh_status() {
echo $(ssh $SQL_PROXY_HOST ls) ssh -O check -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST > /dev/null 2>&1
echo $?
} }
read_cache() { connect() {
if [ -f $CACHE_FILE ] mkdir -p $HOME/.ssh/controlmasters
if [ $(ssh_status) -ne 0 ]
then then
mapfile -t HOST_LIST < $CACHE_FILE echo "" > $CONNECTION_CACHE
LAST_CHANGED=$(expr $(date +"%s") - "${HOST_LIST[0]}") ssh -o "ControlPersist=10m" -M -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST q
# Refresh cache if cache is older than a minute
if [ $LAST_CHANGED -gt 60 ]
then
write_cache $(ls)
read_cache
fi
else
write_cache $(ls)
read_cache
fi fi
} }
write_cache() { disconnect() {
touch $CACHE_FILE if [ $(ssh_status) -eq 0 ]
echo -e $(date +"%s")"\n"$1 > $CACHE_FILE then
ssh -O stop -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST q
fi
}
port_forward() {
ACTIVE_HOST=$(cat $CONNECTION_CACHE)
if [ -z $ACTIVE_HOST ] || [ $ACTIVE_HOST != $1 ]
then
if [ ! -z $ACTIVE_HOST ]
then
ssh -O cancel -L 3306:$ACTIVE_HOST:3306 -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST q
fi
ssh -O forward -L 3306:$1:3306 -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST
fi
echo $1 > $CONNECTION_CACHE
}
ls_hosts() {
echo $(ssh -S $HOME/.ssh/controlmasters/%r@%h:%p $SQL_PROXY_HOST ls)
} }
run_client() { run_client() {
# wait for port to open
while ! nc -z localhost 3306 > /dev/null
do
sleep 0.1
done
if [ $(uname -s) = "Linux" ] if [ $(uname -s) = "Linux" ]
then then
mysql --protocol=TCP -u $1 -p$2 -h localhost -P 3306 mysql --protocol=TCP -u $1 -p$2 -h localhost -P 3306
@ -57,21 +65,15 @@ shift
case $MAIN_OPTION in case $MAIN_OPTION in
ls) ls)
RESPONSE=$(ls) ls_hosts;;
write_cache $RESPONSE
echo $RESPONSE;;
connect) connect)
# Kill open connections on exit # ensure connection
# https://stackoverflow.com/questions/360201/how-do-i-kill-background-processes-jobs-when-my-shell-script-exits connect
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
# check/update cache
read_cache
# check if host is valid # check if host is valid
TARGET_HOST=$1 TARGET_HOST=$1
shift shift
tail -n +2 $CACHE_FILE | grep -qe "^$TARGET_HOST$" ls_hosts | grep -qe "^$TARGET_HOST$"
GREP_EXIT_CODE=$? GREP_EXIT_CODE=$?
if [ $GREP_EXIT_CODE -eq 0 ] if [ $GREP_EXIT_CODE -eq 0 ]
then then
@ -82,18 +84,17 @@ case $MAIN_OPTION in
p) MYSQL_PASSWORD="$OPTARG" ;; p) MYSQL_PASSWORD="$OPTARG" ;;
esac esac
done done
ssh -L 3306:$TARGET_HOST:3306 $SQL_PROXY_HOST > /dev/null 2>&1 & port_forward $TARGET_HOST
if [ ! -z $MYSQL_USERNAME ] && [ ! -z $MYSQL_PASSWORD ] if [ ! -z $MYSQL_USERNAME ] && [ ! -z $MYSQL_PASSWORD ]
then then
run_client $MYSQL_USERNAME $MYSQL_PASSWORD run_client $MYSQL_USERNAME $MYSQL_PASSWORD
else
echo 'Press CTRL C to quit this connection'
wait
fi fi
else else
echo "Invalid Hostname: $2." echo "Invalid Hostname: $2."
fi fi
;; ;;
disconnect)
disconnect;;
*) *)
echo -e "Usage: myssh [ls|connect]\n\n";; echo -e "Usage: myssh [ls|connect]\n\n";;
esac esac

View file

@ -10,9 +10,9 @@ idle() {
sleep infinity sleep infinity
} }
if [ -z $SSH_ORIGINAL_COMMAND ] case "$SSH_ORIGINAL_COMMAND" in
then "") idle;;
idle ls) ls_hosts;;
else q|quit) exit 0;;
ls_hosts *) exit 1;;
fi esac

View file

@ -1,3 +1,22 @@
#!/usr/bin/env bash
which myssh > /dev/null 2>&1
if [ $? -eq 1 ]
then
mkdir -p $HOME/bin
cp ./script/myssh $HOME/bin/myssh
if [[ ! $PATH =~ $HOME/bin ]]
then
if [[ $SHELL =~ bin/bash$ ]]
then
echo -e 'PATH=$PATH:$HOME/bin' >> $HOME/.bashrc
elif [[ $SHELL =~ bin/zsh$ ]]
then
echo -e 'PATH=$PATH:$HOME/bin' >> $HOME/.zshrc
fi
fi
fi
if [ ! -f ./etc/ssh/ssh_host_ed25519_key ] if [ ! -f ./etc/ssh/ssh_host_ed25519_key ]
then then
echo "Generating sqlproxy SSHD keys" echo "Generating sqlproxy SSHD keys"
@ -14,5 +33,5 @@ case $GEN_KEYS in
echo -ne "\n\nHost $HOST_NAME\n User sqlproxy\n IdentityFile ~/.ssh/$KEY_NAME.key" >> ~/.ssh/config echo -ne "\n\nHost $HOST_NAME\n User sqlproxy\n IdentityFile ~/.ssh/$KEY_NAME.key" >> ~/.ssh/config
echo -e command=\"/sqlproxy_cli.sh\" $(cat ~/.ssh/$KEY_NAME.key.pub) >> ./etc/ssh/.ssh/authorized_keys echo -e command=\"/sqlproxy_cli.sh\" $(cat ~/.ssh/$KEY_NAME.key.pub) >> ./etc/ssh/.ssh/authorized_keys
break;; break;;
*) echo "Not generating client ssh key.\nPlease put your desired public keys into ./etc/ssh/.ssh/authorized_keys\nAlso add 'command=\"/sqlproxy_cli.sh\" ' in front of your key";; *) echo -e "Not generating client ssh key.\nPlease put your desired public keys into ./etc/ssh/.ssh/authorized_keys\nAlso add 'command=\"/sqlproxy_cli.sh\" ' in front of your key";;
esac esac