#!/bin/sh CONFFILE=/usr/local/etc/wssh.conf MINPORT=1025 MAXPORT=65535 DEFPORT=2200 # function which will use egrep to see if the first # argument patches the second argument. # NOTE: ONLY the second argument maybe an extended regular expression match() { string="$1" regexp="$2" echo "$string" | egrep -w "$regexp" >/dev/null return $? } chooseRandomPort() { PORTFORWARD=0 while [ $PORTFORWARD -lt $MINPORT -o $PORTFORWARD -gt $MAXPORT ] do if [ -x /bin/ksh ] then PORTFORWARD=`/bin/ksh -c 'echo $RANDOM'` else if [ -x /bin/bash ] then PORTFORWARD=`/bin/bash -c 'echo $RANDOM'` else PORTFORWARD=$DEFPORT fi fi done } # If you use a passphrase with your keys, and you will be going # through more than one hop, you MUST uncomment this option AGENTFW="-A" NOCHECK="-oStrictHostKeyChecking=no -oNoHostAuthenticationForLocalhost=yes" QUIET="-q" EXTRA="$AGENTFW $NOCHECK $QUIET" # looks in the conf file and returns a list of the hops to make getproxy() { cat $CONFFILE |grep -v "^#" | tr '[A-Z]' '[a-z]' | while read regexp proxy do #echo "trying $regexp" >&2 if match "$dest" "$regexp" then echo $proxy return 0 fi done echo "" return 1 } # sets up a tunnel similar to this #ssh dogmatix -t -L 2200:localhost:2200 ssh falbala -N -t -L 2200:justforkix:22 setuptunnel() { dest=$1 proxy=`getproxy $dest` #echo proxy is $proxy # if no proxy assume can get there directly if [ -z "$proxy" ] then return 1 else #for each proxy in the list, construct the command # each intermediate must go to background or it won't finish set $proxy while [ $# -gt 1 ] do cmdline="$cmdline ssh $1 $EXTRA -f -L $PORTFORWARD:localhost:$PORTFORWARD" shift done # last proxy # this is a total hack, but it works. # it seems that if we use -N, then the damn intermediate # tunnel never dies, BUT, if we put a sleep at the # end, then the sleep will end, but the tunnel won't # terminate until the connection running over it # terminates... Kind of cool actually cmdline="$cmdline ssh $1 $EXTRA -f -L $PORTFORWARD:$dest:22 sleep 5" # execute the command $cmdline ret=$? # sleep for a bit to give the connection time to setup sleep 2 fi return $ret } teardowntunnel() { SSHPFPID=`ps -ef | egrep "ssh.*-L $PORTFORWARD" | awk '{print $2}'` kill $SSHPFPID 2>/dev/null } ##### main # This program acts differently depending on its name # it can be called as wssh or wscp chooseRandomPort case `basename $0` in wssh) if [ -z "$1" ] then echo "USAGE: $0 hostname" >&2 exit 1 fi dest=$1 shift setuptunnel $dest ret=$? case $ret in 0) #tunnel is set ssh $NOCHECK -p $PORTFORWARD localhost $* ret=$? ;; 1) #no tunnel required ssh $NOCHECK $dest $* ret=$? ;; *) #something failed echo "ERROR setting up tunnel" ;; esac #teardowntunnel ;; wscp) if [ -z "$1" ] then echo "USAGE: $0 localfile host:file" >&2 exit 1 fi localfile=$1 dest=`echo $2 | sed -e "s/:.*//"` destfile=`echo $2 | sed -e "s/.*://"` setuptunnel $dest ret=$? case $ret in 0) scp $NOCHECK $QUIET -P $PORTFORWARD \ $localfile localhost:$destfile ret=$? ;; 1) #no tunnel required scp $NOCHECK $QUIET $localfile $dest:$destfile ret=$? ;; *) #something failed echo "ERROR setting up tunnel" ;; esac esac exit $ret