Skip to content

Instantly share code, notes, and snippets.

@taylor
Created November 17, 2011 11:09
Show Gist options
  • Save taylor/1372925 to your computer and use it in GitHub Desktop.
Save taylor/1372925 to your computer and use it in GitHub Desktop.
wrapper to support SSH SRV records

Introduction

ssh-srv-wrapper is bash shell script which tries to find a SSH SRV record for the first host and uses what is found rather than what was passed (if a valid record is found).

Install

Run the script directly or feel free to rename or symlink to the name ssh. It will look for another ssh in your path to execute.

TODO

  • Validate host found in DNS. Potential security risk if DNS server returned shell esacpe sequences, etc.

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Send me a pull request -- not sure if that will work in a Gist...

Copyright

Released into the public domain.

#!/bin/bash
# Name: ssh-srv-wrapper
#
# Purpose: Check DNS SRV records and use the entry when possible.
#
# This code is hereby released to the public domain and may be used for any
# purpose whatsoever without permission or acknowledgment.
#
# Taylor Carpenter <[email protected]>
DEBUG_ME=0
me=`basename $0`
mydir=$(dirname $0)
_dmsg() { if [ "${DEBUG_ME}" = 1 ] ; then echo $* ; fi ; }
SSH=`which ssh`
if [ "$me" = "ssh" -a "$0" = "${SSH}" ] ; then
SSH=`PATH=${PATH/$mydir:} which ssh`
fi
usage() {
#echo "usage: $me [args] [user@<host>] [args]"
#echo "See man ssh (1)"
$SSH
}
if [ "$1" = "" ] ; then
usage
exit 1
elif [ "$1" = "-V" -o "$1" = "-version" ] ; then
exec $SSH -V
else
args=("$@")
fi
preargs=()
postargs=()
nao=1246AaCfgKkMNnqsTtVvXxYy
userhost=
check_srv=true
i=0
# Only parse args up to [user@]host
for (( i=0; i<${#args[*]}; i++ )) ; do
case ${args[i]} in
-[$nao]|-[$nao]*[$nao])
preargs[${#preargs[*]}]="${args[i]}"
args[i]=
;;
-*p)
preargs[${#preargs[*]}]="${args[i]}"
args[i]=
((i++))
preargs[${#preargs[*]}]="${args[i]}"
args[i]=
check_srv=false # ignore SRV record
;;
-*)
preargs[${#preargs[*]}]="${args[i]}"
args[i]=
((i++))
preargs[${#preargs[*]}]="${args[i]}"
args[i]=
;;
*)
userhost="${args[i]}"
args[i]=
postargs=($(echo "${args[@]}"))
break
;;
esac
done
if [ -z "$userhost" ] ; then
usage
exit 1
fi
host=${userhost##*@}
user=${userhost%%@*}
[ "$user" = "$host" ] && user=
if [ "$check_srv" = "true" ] ; then
echo $host | grep '[A-Za-z]' > /dev/null
if [ $? = 0 ] ; then
srv=$(host -s -W 1 -t SRV _ssh._tcp.${host}|grep "has SRV")
if [ $? = 0 ] ; then
shost=${srv##* }
host=${shost%*.}
sport=${srv%* $host.}
port=${sport##* }
if [ -z "$host" ] ; then
echo "Could not figure out hostname in SRV record"
exit 1
fi
fi
fi
[ "$port" != "" ] && preargs[${#preargs[*]}]="-p ${port}"
_dmsg "After SRV lookup -- HOST: $host PORT: $port"
fi
[ "$user" != "" ] && userat="${user}@" || userat=""
args=("${preargs[@]}" "${userat}${host}" "${postargs[@]}")
_dmsg Executing $SSH ${args[@]}
exec $SSH ${args[@]}
@sbuzonas
Copy link

sbuzonas commented Mar 9, 2015

Just made a fork https://gist.github.com/slbmeh/5206bf9b4bf0c381017d that removes all equivalent paths for cases where the script resolves to twice in path e.g. ~/bin and ./bin if you execute it from your home directory.

Should probably just get rid of the if condition completely. Not certain.

@laurivosandi
Copy link

What the heck guys, why not just use dig? dig -t srv _ssh._tcp.example.com +short

@snaeqe
Copy link

snaeqe commented Jan 6, 2016

Because dig is neither a libc function like gethostbyname nor a universally installed util like host.

@lcharles123
Copy link

lcharles123 commented Jun 15, 2024

If you have ssh on non default port, you can just remove "_ssh._tcp." from line 89 and it just works.

@taylor
Copy link
Author

taylor commented Jun 19, 2024

@lcharles123 I do not understand... the point is to look for a specified port in the records that uses SRV then select that port... If they do not use SRV it should not find non default port...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment