aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtests/clientsh.bash264
-rwxr-xr-xtests/netsh.sh27
2 files changed, 281 insertions, 10 deletions
diff --git a/tests/clientsh.bash b/tests/clientsh.bash
new file mode 100755
index 0000000..9d5baea
--- /dev/null
+++ b/tests/clientsh.bash
@@ -0,0 +1,264 @@
+#! /bin/bash
+
+set -e
+
+exec 3>&1
+
+DEBUG=1
+netnsprefix="$1"; shift # wg-test-$PID
+server_public="$1"; shift
+
+netnsn() { echo $netnsprefix-$1; }
+pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; }
+pp() { pretty "" "$*"; "$@"; }
+maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; }
+nn() {
+ [[ "$1" != "-q" ]] && pretty $n "$*" || shift
+ local netns=$(netnsn $1) n=$1; shift;
+ maybe_exec ip netns exec $netns "$@";
+}
+ipn() {
+ [[ "$1" != "-q" ]] && pretty $n "ip $*" || shift
+ local netns=$(netnsn $1) n=$1; shift;
+ ip -n $netns "$@";
+}
+
+ns=
+
+cleanup() {
+ set +e
+ exec 2>/dev/null
+
+ for n in $ns; do ipn $n link del dev wg0; done
+
+ local to_kill="$(for n in $ns; do $(ip netns pids $(netnsn $n)); done)"
+ [[ -n $to_kill ]] && kill $to_kill
+
+ for n in $ns; do pp ip netns del $(netnsn $n); done
+
+ exit
+}
+
+trap cleanup EXIT
+
+setup_client_peer() {
+ local n=$1; shift
+ ns+=" $n"
+
+ pp ip netns add $(netnsn $n)
+ ipn 0 link add dev wg0 type wireguard
+ ipn 0 link set wg0 netns $(netnsn $n)
+
+ privkey=$(wg genkey)
+ pubkey=$(wg pubkey <<< $privkey)
+
+ ipn $n addr add fe80::badc:0ffe:e0dd:$n/64 dev wg0
+ nn $n wg set wg0 \
+ private-key <(echo $privkey) \
+ listen-port $n \
+ peer $server_public \
+ allowed-ips 0.0.0.0/0,::/0
+
+ ipn $n link set up dev wg0
+ ipn $n route add fe80::/128 dev wg0
+
+ nn $n wg set wg0 peer "$server_public" endpoint [::1]:1
+ nn 1 wg set wg0 peer "$pubkey" \
+ allowed-ips fe80::badc:0ffe:e0dd:$n/128 \
+ endpoint [::1]:$n
+
+ nn $n ping6 -c 10 -f -W 1 fe80::%wg0
+ nn 1 ping6 -c 10 -f -W 1 fe80::badc:0ffe:e0dd:$n%wg0
+}
+
+# Positive check -- verify that $1 is allowed on server.
+check_alowedips() {
+ local n="$1"; shift
+ local pubkey="$1"; shift
+ local ip="$1"; shift
+
+ [[ -z "$ip" ]] && return 0
+
+ nn -q 1 wg show wg0 allowed-ips |
+ while read -r _pubkey _ips; do
+ [[ "$_pubkey" = "$pubkey" ]] || continue
+ for _ip in $_ips; do
+ [[ "$_ip" = "$ip" ]] && return 0
+ done
+ done && return 0
+
+ pretty $n "Missing $ip in allowedips"
+ return 1
+}
+
+declare -a IPV4
+declare -a IPV6
+declare -a LEASESTART
+declare -a LEASETIME
+declare -a ERRNO
+
+send_cmd() {
+ local n=$1; shift
+ local REQ="$1"; shift
+
+ # - It would have been nice to use /dev/tcp/fe80::%w0/970 instead
+ # of nc, but we need to use a specific source port.
+ eval $(
+ printf $REQ | nn -q $n ncat -p 970 fe80::%wg0 970 |
+ while read -r line; do
+ key="${line%%=*}"
+ value="${line#*=}"
+ case "$key" in
+ ipv4) echo IPV4[$n]="$value"; continue ;;
+ ipv6) echo IPV6[$n]="$value"; continue ;;
+ leasestart) echo LEASESTART[$n]="$value"; continue ;;
+ leasetime) echo LEASETIME[$n]="$value"; continue ;;
+ errno) echo ERRNO[$n]="$value"; continue ;;
+ esac
+ done
+ )
+}
+
+req() {
+ local n=$1; shift
+ local ipv4_req=
+ [ $# -gt 0 ] && [ -n "$1" ] && { ipv4_req="ipv4=$1\n"; shift; }
+ [ "$ipv4_req" = "ipv4=-\n" ] && ipv4_req="ipv4=\n"
+ local ipv6_req=
+ [ $# -gt 0 ] && [ -n "$1" ] && { ipv6_req="ipv6=$1\n"; shift; }
+ [ "$ipv6_req" = "ipv6=-\n" ] && ipv6_req="ipv6=\n"
+
+ IPV4[$n]=
+ IPV6[$n]=
+ LEASESTART[$n]=
+ LEASETIME[$n]=
+ ERRNO[$n]=
+
+ REQ="request_ip=1\n${ipv4_req}${ipv6_req}\n"
+ send_cmd $n "$REQ"
+}
+
+req_check() {
+ local n=$1
+
+ req $*
+
+ pubkey=$(nn -q $n wg show wg0 public-key)
+ check_alowedips $n "$pubkey" "${IPV4[$n]}"
+ check_alowedips $n "$pubkey" "${IPV6[$n]}"
+}
+
+run_k_at_random() {
+ local NCLIENTS=$1; shift
+ local k=$1; shift
+ local n=10
+ local i
+
+ if [[ $NCLIENTS -gt $k ]]; then
+ n=$(( 10 + $RANDOM % ($NCLIENTS - $k) ))
+ fi
+
+ for i in $(seq $n $(( $n + $k - 1))); do
+ case $(( $RANDOM % 9 )) in
+ 0) req_check $i "" "" ; continue ;;
+ 1) req_check $i "" "-" ; continue ;;
+ 2) req_check $i "-" "" ; continue ;;
+ 3) req_check $i "-" "-" ; continue ;;
+
+ 4) req_check $i ${IPV4[$i]} "" ; continue ;;
+ 5) req_check $i ${IPV4[$i]} "-" ; continue ;;
+ 6) req_check $i "" ${IPV6[$i]} ; continue ;;
+ 7) req_check $i "-" ${IPV6[$i]} ; continue ;;
+
+ 8) req_check $i ${IPV4[$i]} ${IPV6[$i]} ; continue;;
+ esac
+ done
+}
+
+test_random() {
+ local NCLIENTS=$1; shift
+ local n
+
+ for n in $(seq 10 $(( 9+$NCLIENTS ))); do setup_client_peer $n; done
+
+ # NOTE: When running this script a second time, doing cleanup as
+ # we exit the first invocation, ncat is hanging on receiving the
+ # response. tcpdump shows that the response is indeed sent by the
+ # server.
+ for n in $(seq 10 $(( 9+$NCLIENTS ))); do
+ req_check $n
+ #t=$(( 1 + $RANDOM % 2 ))
+ #sleep $t
+ done
+
+ while sleep 1; do
+ if [ $(( $RANDOM % 100 )) -lt 50 ]; then
+ run_k_at_random $NCLIENTS 5
+ fi
+ done
+}
+
+fail() {
+ echo "FAIL \"$1\""
+ exit 1
+}
+
+test_case_1() {
+ # One client -- 9.
+ setup_client_peer 9
+
+ pretty 9 "Badly formed request => errno=1"
+ send_cmd 9 "ip_request=\n\n"
+ [[ ${ERRNO[9]} = 1 ]] || fail "errno: ${ERRNO[9]}"
+
+ ## Check disabled 2019-09-27. Enable again when ipp_add_v4() and
+ ## ipp_add_v6() have checks.
+ #pretty 9 "Request an address we won't get => errno=2"
+ #req 9 "1.1.1.0/32" "-"
+ #[[ ${ERRNO[9]} = 2 ]] || fail "errno: ${ERRNO[9]}"
+
+ pretty "" "SUCCESS\n"
+}
+
+test_case_2() {
+ # Two clients -- 10 and 11.
+ for i in 10 11; do setup_client_peer $i; done
+
+ pretty 10 "Any v4, any v6"
+ req_check 10
+ [[ ${ERRNO[10]} = 0 ]] || fail "errno: ${ERRNO[10]}"
+ local C10_FIRST_V4=${IPV4[10]}
+ local C10_FIRST_V6=${IPV6[10]}
+
+ pretty 10 "Extend v4, extend v6"
+ req_check 10 $C10_FIRST_V4 $C10_FIRST_V6
+ [[ ${ERRNO[10]} = 0 ]] || fail "errno: ${ERRNO[10]}"
+ [[ ${IPV4[10]} = $C10_FIRST_V4 ]] || fail "ipv4: ${IPV4[10]}"
+ [[ ${IPV6[10]} = $C10_FIRST_V6 ]] || fail "ipv6: ${IPV6[10]}"
+
+ pretty 10 "Extend v4, drop v6"
+ req_check 10 $C10_FIRST_V4 "-"
+ [[ ${ERRNO[10]} = 0 ]] || fail "errno: ${ERRNO[10]}"
+ [[ ${IPV4[10]} = $C10_FIRST_V4 ]] || fail "ipv4: ${IPV4[10]}"
+ [[ -z "${IPV6[10]}" ]] || fail "ipv6: ${IPV6[10]}"
+
+ pretty 11 "Requesting the v4 of client 10 and no v6 => errno=0 and no addrs"
+ req 11 $C10_FIRST_V4 "-"
+ [[ ${ERRNO[11]} = 0 ]] || fail "errno: ${ERRNO[11]}"
+ [[ -z "${IPV4[11]}" ]] || fail "ipv4 not empty: ${IPV4[11]}"
+ [[ -z "${IPV6[11]}" ]] || fail "ipv6 not empty: ${IPV6[11]}"
+
+ pretty 11 "Wait for lease to expire and try again"
+ pp sleep ${LEASETIME[10]}
+ req_check 11 $C10_FIRST_V4 "-"
+ [[ ${ERRNO[11]} = 0 ]] || fail "errno: ${ERRNO[11]}"
+ [[ ${IPV4[11]} = $C10_FIRST_V4 ]] || fail "ipv4: ${IPV4[11]}"
+ [[ -z "${IPV6[11]}" ]] || fail "ipv6 not empty: ${IPV6[11]}"
+
+ pretty "" "SUCCESS\n"
+}
+
+#test_random 50
+
+test_case_1
+test_case_2
diff --git a/tests/netsh.sh b/tests/netsh.sh
index 984411a..9f022c8 100755
--- a/tests/netsh.sh
+++ b/tests/netsh.sh
@@ -6,6 +6,9 @@
set -e
exec 3>&1
+
+[ $# -ge 1 ] && ( n_clients="$1"; shift; )
+
export WG_HIDE_KEYS=never
netnsn() { echo wg-test-$$-$1; }
pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; }
@@ -14,25 +17,24 @@ maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; }
nn() { local netns=$(netnsn $1) n=$1; shift; pretty $n "$*"; maybe_exec ip netns exec $netns "$@"; }
ipn() { local netns=$(netnsn $1) n=$1; shift; pretty $n "ip $*"; ip -n $netns "$@"; }
+ns="0 1 2"
+
cleanup() {
set +e
exec 2>/dev/null
- ipn 0 link del dev wg0
- ipn 1 link del dev wg0
- ipn 2 link del dev wg0
- local to_kill="$(ip netns pids $(netnsn 0)) $(ip netns pids $(netnsn 1)) $(ip netns pids $(netnsn 2))"
+
+ for n in $ns; do ipn $n link del dev wg0; done
+
+ local to_kill="$(for n in $ns; do $(ip netns pids $(netnsn $n)); done)"
[[ -n $to_kill ]] && kill $to_kill
- pp ip netns del $(netnsn 0)
- pp ip netns del $(netnsn 1)
- pp ip netns del $(netnsn 2)
+
+ for n in $ns; do pp ip netns del $(netnsn $n); done
+
exit
}
trap cleanup EXIT
-ip netns del $(netnsn 0) 2>/dev/null || true
-ip netns del $(netnsn 1) 2>/dev/null || true
-ip netns del $(netnsn 2) 2>/dev/null || true
pp ip netns add $(netnsn 0)
pp ip netns add $(netnsn 1)
pp ip netns add $(netnsn 2)
@@ -79,4 +81,9 @@ nn 2 wg set wg0 peer "$server_public" endpoint [::1]:1
nn 2 ping6 -c 10 -f -W 1 fe80::%wg0
nn 1 ping6 -c 10 -f -W 1 fe80::badc:0ffe:e0dd:f00d%wg0
+pretty "" "clientsh.bash can be run with the following arguments:"
+echo
+echo wg-test-$$ $server_public
+echo
+
nn 1 ./wg-dynamic-server wg0