Skip to content

Instantly share code, notes, and snippets.

@taylor
Created November 17, 2011 11:09
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • 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.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history.
  • If you want to have your own version, that is fine but bump version in a commit by itself so I can ignore when I pull
  • Send me a pull request. Bonus points for topic branches.

Copyright

Released into the public domain.

#!/bin/sh
# 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 <taylor@codecafe.com>
#echo $* > /tmp/fooo
#exit
DEBUG_ME=0
me=`basename $0`
mydir=$(dirname $0)
function _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
function usage() {
echo "usage: $me [args] [user@<host>] [args]"
echo "See man ssh (1)"
}
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
_dmsg "Checking SRV"
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
echo "srv: '$srv'"
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 $SSH ${args[@]}
exec $SSH ${args[@]}
@taylor
Copy link
Author

taylor commented Nov 17, 2011

this version is incomplete but will allow arguments to go anywhere

@taylor
Copy link
Author

taylor commented Nov 17, 2011

Working version.

@taylor
Copy link
Author

taylor commented Nov 17, 2011

fixed bug in SRV lookup code

@ssbarnea
Copy link

Quite cool. I am wondering if there is any SSH client that does support that by default or if there are any plans (feature requests) for introducing this.

It seems that the OS X ssh client already does this, or at least this is what http://egopoly.com/2008/02/ssh-slow-on-leopard.html suggests.

Two more two go: linux ssh and putty!

@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.

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