1#!/bin/bash 2# 3# run OpenVPN client against ``test reference'' server 4# - check that ping, http, ... via tunnel works 5# - check that interface config / routes are properly cleaned after test end 6# 7# prerequisites: 8# - openvpn binary in current directory 9# - writable current directory to create subdir for logs 10# - t_client.rc in current directory OR source dir that specifies tests 11# - for "ping4" checks: fping binary in $PATH 12# - for "ping6" checks: fping6 binary in $PATH 13# 14 15srcdir="${srcdir:-.}" 16top_builddir="${top_builddir:-..}" 17if [ -r "${top_builddir}"/t_client.rc ] ; then 18 . "${top_builddir}"/t_client.rc 19elif [ -r "${srcdir}"/t_client.rc ] ; then 20 . "${srcdir}"/t_client.rc 21else 22 echo "$0: cannot find 't_client.rc' in build dir ('${top_builddir}')" >&2 23 echo "$0: or source directory ('${srcdir}'). SKIPPING TEST." >&2 24 exit 77 25fi 26 27if [ ! -x "${top_builddir}/src/openvpn/openvpn" ] 28then 29 echo "no (executable) openvpn binary in current build tree. FAIL." >&2 30 exit 1 31fi 32 33if [ ! -w . ] 34then 35 echo "current directory is not writable (required for logging). FAIL." >&2 36 exit 1 37fi 38 39if [ -z "$CA_CERT" ] ; then 40 echo "CA_CERT not defined in 't_client.rc'. SKIP test." >&2 41 exit 77 42fi 43 44if [ -z "$TEST_RUN_LIST" ] ; then 45 echo "TEST_RUN_LIST empty, no tests defined. SKIP test." >&2 46 exit 77 47fi 48 49# make sure we have permissions to run ifconfig/route from OpenVPN 50# can't use "id -u" here - doesn't work on Solaris 51ID=`id` 52if expr "$ID" : "uid=0" >/dev/null 53then : 54else 55 if [ -z "$RUN_SUDO" ] 56 then 57 echo "$0: this test must run be as root, or RUN_SUDO=... " >&2 58 echo " must be set correctly in 't_client.rc'. SKIP." >&2 59 exit 77 60 fi 61fi 62 63LOGDIR=t_client-`hostname`-`date +%Y%m%d-%H%M%S` 64if mkdir $LOGDIR 65then : 66else 67 echo "can't create log directory '$LOGDIR'. FAIL." >&2 68 exit 1 69fi 70 71exit_code=0 72 73# ---------------------------------------------------------- 74# helper functions 75# ---------------------------------------------------------- 76# print failure message, increase FAIL counter 77fail() 78{ 79 echo "" 80 echo "FAIL: $@" >&2 81 fail_count=$(( $fail_count + 1 )) 82} 83 84# print "all interface IP addresses" + "all routes" 85# this is higly system dependent... 86get_ifconfig_route() 87{ 88 # linux / iproute2? (-> if configure got a path) 89 if [ -n "/sbin/ip" ] 90 then 91 echo "-- linux iproute2 --" 92 /sbin/ip addr show | grep -v valid_lft 93 /sbin/ip route show 94 /sbin/ip -o -6 route show | grep -v ' cache' | sed -e 's/expires [0-9]*sec//' 95 return 96 fi 97 98 # try uname 99 case `uname -s` in 100 Linux) 101 echo "-- linux / ifconfig --" 102 LANG=C /sbin/ifconfig -a |egrep "( addr:|encap:)" 103 LANG=C netstat -rn -4 -6 104 return 105 ;; 106 FreeBSD|NetBSD|Darwin) 107 echo "-- FreeBSD/NetBSD/Darwin [MacOS X] --" 108 /sbin/ifconfig -a | egrep "(flags=|inet)" 109 netstat -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }' 110 return 111 ;; 112 OpenBSD) 113 echo "-- OpenBSD --" 114 /sbin/ifconfig -a | egrep "(flags=|inet)" | \ 115 sed -e 's/pltime [0-9]*//' -e 's/vltime [0-9]*//' 116 netstat -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }' 117 return 118 ;; 119 SunOS) 120 echo "-- Solaris --" 121 /sbin/ifconfig -a | egrep "(flags=|inet)" 122 netstat -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }' 123 return 124 ;; 125 esac 126 127 echo "get_ifconfig_route(): no idea how to get info on your OS. FAIL." >&2 128 exit 20 129} 130 131# ---------------------------------------------------------- 132# check ifconfig 133# arg1: "4" or "6" -> for message 134# arg2: IPv4/IPv6 address that must show up in out of "get_ifconfig_route" 135check_ifconfig() 136{ 137 proto=$1 ; shift 138 expect_list="$@" 139 140 if [ -z "$expect_list" ] ; then return ; fi 141 142 for expect in $expect_list 143 do 144 if get_ifconfig_route | fgrep "$expect" >/dev/null 145 then : 146 else 147 fail "check_ifconfig(): expected IPv$proto address '$expect' not found in ifconfig output." 148 fi 149 done 150} 151 152# ---------------------------------------------------------- 153# run pings 154# arg1: "4" or "6" -> fping/fing6 155# arg2: "want_ok" or "want_fail" (expected ping result) 156# arg3... -> fping arguments (host list) 157run_ping_tests() 158{ 159 proto=$1 ; want=$2 ; shift ; shift 160 targetlist="$@" 161 162 # "no targets" is fine 163 if [ -z "$targetlist" ] ; then return ; fi 164 165 case $proto in 166 4) cmd=fping ;; 167 6) cmd=fping6 ;; 168 *) echo "internal error in run_ping_tests arg 1: '$proto'" >&2 169 exit 1 ;; 170 esac 171 172 case $want in 173 want_ok) sizes_list="64 1440 3000" ;; 174 want_fail) sizes_list="64" ;; 175 esac 176 177 for bytes in $sizes_list 178 do 179 echo "run IPv$proto ping tests ($want), $bytes byte packets..." 180 181 echo "$cmd -b $bytes -C 20 -p 250 -q $targetlist" >>$LOGDIR/$SUF:fping.out 182 $cmd -b $bytes -C 20 -p 250 -q $targetlist >>$LOGDIR/$SUF:fping.out 2>&1 183 184 # while OpenVPN is running, pings must succeed (want='want_ok') 185 # before OpenVPN is up, pings must NOT succeed (want='want_fail') 186 187 rc=$? 188 if [ $rc = 0 ] # all ping OK 189 then 190 if [ $want = "want_fail" ] # not what we want 191 then 192 fail "IPv$proto ping test succeeded, but needs to *fail*." 193 fi 194 else # ping failed 195 if [ $want = "want_ok" ] # not what we wanted 196 then 197 fail "IPv$proto ping test ($bytes bytes) failed, but should succeed." 198 fi 199 fi 200 done 201} 202 203# ---------------------------------------------------------- 204# main test loop 205# ---------------------------------------------------------- 206SUMMARY_OK= 207SUMMARY_FAIL= 208 209for SUF in $TEST_RUN_LIST 210do 211 # get config variables 212 eval test_run_title=\"\$RUN_TITLE_$SUF\" 213 eval openvpn_conf=\"\$OPENVPN_CONF_$SUF\" 214 eval expect_ifconfig4=\"\$EXPECT_IFCONFIG4_$SUF\" 215 eval expect_ifconfig6=\"\$EXPECT_IFCONFIG6_$SUF\" 216 eval ping4_hosts=\"\$PING4_HOSTS_$SUF\" 217 eval ping6_hosts=\"\$PING6_HOSTS_$SUF\" 218 219 echo -e "\n### test run $SUF: '$test_run_title' ###\n" 220 fail_count=0 221 222 echo "save pre-openvpn ifconfig + route" 223 get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_pre.txt 224 225 echo -e "\nrun pre-openvpn ping tests - targets must not be reachable..." 226 run_ping_tests 4 want_fail "$ping4_hosts" 227 run_ping_tests 6 want_fail "$ping6_hosts" 228 if [ "$fail_count" = 0 ] ; then 229 echo -e "OK.\n" 230 else 231 echo -e "FAIL: make sure that ping hosts are ONLY reachable via VPN, SKIP test $SUF". 232 exit_code=31 233 continue 234 fi 235 236 echo " run openvpn $openvpn_conf" 237 echo "# src/openvpn/openvpn $openvpn_conf" >$LOGDIR/$SUF:openvpn.log 238 $RUN_SUDO "${top_builddir}/src/openvpn/openvpn" $openvpn_conf >>$LOGDIR/$SUF:openvpn.log & 239 opid=$! 240 241 # make sure openvpn client is terminated in case shell exits 242 trap "$RUN_SUDO kill $opid" 0 243 trap "$RUN_SUDO kill $opid ; trap - 0 ; exit 1" 1 2 3 15 244 245 echo "wait for connection to establish..." 246 sleep ${SETUP_TIME_WAIT:-10} 247 248 # test whether OpenVPN process is still there 249 if $RUN_SUDO kill -0 $opid 250 then : 251 else 252 echo -e "OpenVPN process has failed to start up, check log ($LOGDIR/$SUF:openvpn.log). FAIL.\ntail of logfile follows:\n..." >&2 253 tail $LOGDIR/$SUF:openvpn.log >&2 254 trap - 0 1 2 3 15 255 exit 10 256 fi 257 258 # compare whether anything changed in ifconfig/route setup? 259 echo "save ifconfig+route" 260 get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route.txt 261 262 echo -n "compare pre-openvpn ifconfig+route with current values..." 263 if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \ 264 $LOGDIR/$SUF:ifconfig_route.txt >/dev/null 265 then 266 fail "no differences between ifconfig/route before OpenVPN start and now." 267 else 268 echo -e " OK!\n" 269 fi 270 271 # expected ifconfig values in there? 272 check_ifconfig 4 "$expect_ifconfig4" 273 check_ifconfig 6 "$expect_ifconfig6" 274 275 run_ping_tests 4 want_ok "$ping4_hosts" 276 run_ping_tests 6 want_ok "$ping6_hosts" 277 echo -e "ping tests done.\n" 278 279 echo "stopping OpenVPN" 280 $RUN_SUDO kill $opid 281 wait $! 282 rc=$? 283 if [ $rc != 0 ] ; then 284 fail "OpenVPN return code $rc, expect 0" 285 fi 286 287 echo -e "\nsave post-openvpn ifconfig + route..." 288 get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_post.txt 289 290 echo -n "compare pre- and post-openvpn ifconfig + route..." 291 if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \ 292 $LOGDIR/$SUF:ifconfig_route_post.txt >$LOGDIR/$SUF:ifconfig_route_diff.txt 293 then 294 echo -e " OK.\n" 295 else 296 cat $LOGDIR/$SUF:ifconfig_route_diff.txt >&2 297 fail "differences between pre- and post-ifconfig/route" 298 fi 299 if [ "$fail_count" = 0 ] ; then 300 echo -e "test run $SUF: all tests OK.\n" 301 SUMMARY_OK="$SUMMARY_OK $SUF" 302 else 303 echo -e "test run $SUF: $fail_count test failures. FAIL.\n"; 304 SUMMARY_FAIL="$SUMMARY_FAIL $SUF" 305 exit_code=30 306 fi 307done 308 309if [ -z "$SUMMARY_OK" ] ; then SUMMARY_OK=" none"; fi 310if [ -z "$SUMMARY_FAIL" ] ; then SUMMARY_FAIL=" none"; fi 311echo "Test sets succeded:$SUMMARY_OK." 312echo "Test sets failed:$SUMMARY_FAIL." 313 314# remove trap handler 315trap - 0 1 2 3 15 316exit $exit_code 317