xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/wireguard/netns.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# This script tests the below topology:
7*4882a593Smuzhiyun#
8*4882a593Smuzhiyun# ┌─────────────────────┐   ┌──────────────────────────────────┐   ┌─────────────────────┐
9*4882a593Smuzhiyun# │   $ns1 namespace    │   │          $ns0 namespace          │   │   $ns2 namespace    │
10*4882a593Smuzhiyun# │                     │   │                                  │   │                     │
11*4882a593Smuzhiyun# │┌────────┐           │   │            ┌────────┐            │   │           ┌────────┐│
12*4882a593Smuzhiyun# ││  wg0   │───────────┼───┼────────────│   lo   │────────────┼───┼───────────│  wg0   ││
13*4882a593Smuzhiyun# │├────────┴──────────┐│   │    ┌───────┴────────┴────────┐   │   │┌──────────┴────────┤│
14*4882a593Smuzhiyun# ││192.168.241.1/24   ││   │    │(ns1)         (ns2)      │   │   ││192.168.241.2/24   ││
15*4882a593Smuzhiyun# ││fd00::1/24         ││   │    │127.0.0.1:1   127.0.0.1:2│   │   ││fd00::2/24         ││
16*4882a593Smuzhiyun# │└───────────────────┘│   │    │[::]:1        [::]:2     │   │   │└───────────────────┘│
17*4882a593Smuzhiyun# └─────────────────────┘   │    └─────────────────────────┘   │   └─────────────────────┘
18*4882a593Smuzhiyun#                           └──────────────────────────────────┘
19*4882a593Smuzhiyun#
20*4882a593Smuzhiyun# After the topology is prepared we run a series of TCP/UDP iperf3 tests between the
21*4882a593Smuzhiyun# wireguard peers in $ns1 and $ns2. Note that $ns0 is the endpoint for the wg0
22*4882a593Smuzhiyun# interfaces in $ns1 and $ns2. See https://www.wireguard.com/netns/ for further
23*4882a593Smuzhiyun# details on how this is accomplished.
24*4882a593Smuzhiyunset -e
25*4882a593Smuzhiyun
26*4882a593Smuzhiyunexec 3>&1
27*4882a593Smuzhiyunexport LANG=C
28*4882a593Smuzhiyunexport WG_HIDE_KEYS=never
29*4882a593Smuzhiyunnetns0="wg-test-$$-0"
30*4882a593Smuzhiyunnetns1="wg-test-$$-1"
31*4882a593Smuzhiyunnetns2="wg-test-$$-2"
32*4882a593Smuzhiyunpretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; }
33*4882a593Smuzhiyunpp() { pretty "" "$*"; "$@"; }
34*4882a593Smuzhiyunmaybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; }
35*4882a593Smuzhiyunn0() { pretty 0 "$*"; maybe_exec ip netns exec $netns0 "$@"; }
36*4882a593Smuzhiyunn1() { pretty 1 "$*"; maybe_exec ip netns exec $netns1 "$@"; }
37*4882a593Smuzhiyunn2() { pretty 2 "$*"; maybe_exec ip netns exec $netns2 "$@"; }
38*4882a593Smuzhiyunip0() { pretty 0 "ip $*"; ip -n $netns0 "$@"; }
39*4882a593Smuzhiyunip1() { pretty 1 "ip $*"; ip -n $netns1 "$@"; }
40*4882a593Smuzhiyunip2() { pretty 2 "ip $*"; ip -n $netns2 "$@"; }
41*4882a593Smuzhiyunsleep() { read -t "$1" -N 1 || true; }
42*4882a593Smuzhiyunwaitiperf() { pretty "${1//*-}" "wait for iperf:${3:-5201} pid $2"; while [[ $(ss -N "$1" -tlpH "sport = ${3:-5201}") != *\"iperf3\",pid=$2,fd=* ]]; do sleep 0.1; done; }
43*4882a593Smuzhiyunwaitncatudp() { pretty "${1//*-}" "wait for udp:1111 pid $2"; while [[ $(ss -N "$1" -ulpH 'sport = 1111') != *\"ncat\",pid=$2,fd=* ]]; do sleep 0.1; done; }
44*4882a593Smuzhiyunwaitiface() { pretty "${1//*-}" "wait for $2 to come up"; ip netns exec "$1" bash -c "while [[ \$(< \"/sys/class/net/$2/operstate\") != up ]]; do read -t .1 -N 0 || true; done;"; }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyuncleanup() {
47*4882a593Smuzhiyun	set +e
48*4882a593Smuzhiyun	exec 2>/dev/null
49*4882a593Smuzhiyun	printf "$orig_message_cost" > /proc/sys/net/core/message_cost
50*4882a593Smuzhiyun	ip0 link del dev wg0
51*4882a593Smuzhiyun	ip0 link del dev wg1
52*4882a593Smuzhiyun	ip1 link del dev wg0
53*4882a593Smuzhiyun	ip1 link del dev wg1
54*4882a593Smuzhiyun	ip2 link del dev wg0
55*4882a593Smuzhiyun	ip2 link del dev wg1
56*4882a593Smuzhiyun	local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)"
57*4882a593Smuzhiyun	[[ -n $to_kill ]] && kill $to_kill
58*4882a593Smuzhiyun	pp ip netns del $netns1
59*4882a593Smuzhiyun	pp ip netns del $netns2
60*4882a593Smuzhiyun	pp ip netns del $netns0
61*4882a593Smuzhiyun	exit
62*4882a593Smuzhiyun}
63*4882a593Smuzhiyun
64*4882a593Smuzhiyunorig_message_cost="$(< /proc/sys/net/core/message_cost)"
65*4882a593Smuzhiyuntrap cleanup EXIT
66*4882a593Smuzhiyunprintf 0 > /proc/sys/net/core/message_cost
67*4882a593Smuzhiyun
68*4882a593Smuzhiyunip netns del $netns0 2>/dev/null || true
69*4882a593Smuzhiyunip netns del $netns1 2>/dev/null || true
70*4882a593Smuzhiyunip netns del $netns2 2>/dev/null || true
71*4882a593Smuzhiyunpp ip netns add $netns0
72*4882a593Smuzhiyunpp ip netns add $netns1
73*4882a593Smuzhiyunpp ip netns add $netns2
74*4882a593Smuzhiyunip0 link set up dev lo
75*4882a593Smuzhiyun
76*4882a593Smuzhiyunip0 link add dev wg0 type wireguard
77*4882a593Smuzhiyunip0 link set wg0 netns $netns1
78*4882a593Smuzhiyunip0 link add dev wg0 type wireguard
79*4882a593Smuzhiyunip0 link set wg0 netns $netns2
80*4882a593Smuzhiyunkey1="$(pp wg genkey)"
81*4882a593Smuzhiyunkey2="$(pp wg genkey)"
82*4882a593Smuzhiyunkey3="$(pp wg genkey)"
83*4882a593Smuzhiyunkey4="$(pp wg genkey)"
84*4882a593Smuzhiyunpub1="$(pp wg pubkey <<<"$key1")"
85*4882a593Smuzhiyunpub2="$(pp wg pubkey <<<"$key2")"
86*4882a593Smuzhiyunpub3="$(pp wg pubkey <<<"$key3")"
87*4882a593Smuzhiyunpub4="$(pp wg pubkey <<<"$key4")"
88*4882a593Smuzhiyunpsk="$(pp wg genpsk)"
89*4882a593Smuzhiyun[[ -n $key1 && -n $key2 && -n $psk ]]
90*4882a593Smuzhiyun
91*4882a593Smuzhiyunconfigure_peers() {
92*4882a593Smuzhiyun	ip1 addr add 192.168.241.1/24 dev wg0
93*4882a593Smuzhiyun	ip1 addr add fd00::1/112 dev wg0
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun	ip2 addr add 192.168.241.2/24 dev wg0
96*4882a593Smuzhiyun	ip2 addr add fd00::2/112 dev wg0
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun	n1 wg set wg0 \
99*4882a593Smuzhiyun		private-key <(echo "$key1") \
100*4882a593Smuzhiyun		listen-port 1 \
101*4882a593Smuzhiyun		peer "$pub2" \
102*4882a593Smuzhiyun			preshared-key <(echo "$psk") \
103*4882a593Smuzhiyun			allowed-ips 192.168.241.2/32,fd00::2/128
104*4882a593Smuzhiyun	n2 wg set wg0 \
105*4882a593Smuzhiyun		private-key <(echo "$key2") \
106*4882a593Smuzhiyun		listen-port 2 \
107*4882a593Smuzhiyun		peer "$pub1" \
108*4882a593Smuzhiyun			preshared-key <(echo "$psk") \
109*4882a593Smuzhiyun			allowed-ips 192.168.241.1/32,fd00::1/128
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun	ip1 link set up dev wg0
112*4882a593Smuzhiyun	ip2 link set up dev wg0
113*4882a593Smuzhiyun}
114*4882a593Smuzhiyunconfigure_peers
115*4882a593Smuzhiyun
116*4882a593Smuzhiyuntests() {
117*4882a593Smuzhiyun	# Ping over IPv4
118*4882a593Smuzhiyun	n2 ping -c 10 -f -W 1 192.168.241.1
119*4882a593Smuzhiyun	n1 ping -c 10 -f -W 1 192.168.241.2
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun	# Ping over IPv6
122*4882a593Smuzhiyun	n2 ping6 -c 10 -f -W 1 fd00::1
123*4882a593Smuzhiyun	n1 ping6 -c 10 -f -W 1 fd00::2
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun	# TCP over IPv4
126*4882a593Smuzhiyun	n2 iperf3 -s -1 -B 192.168.241.2 &
127*4882a593Smuzhiyun	waitiperf $netns2 $!
128*4882a593Smuzhiyun	n1 iperf3 -Z -t 3 -c 192.168.241.2
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun	# TCP over IPv6
131*4882a593Smuzhiyun	n1 iperf3 -s -1 -B fd00::1 &
132*4882a593Smuzhiyun	waitiperf $netns1 $!
133*4882a593Smuzhiyun	n2 iperf3 -Z -t 3 -c fd00::1
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun	# UDP over IPv4
136*4882a593Smuzhiyun	n1 iperf3 -s -1 -B 192.168.241.1 &
137*4882a593Smuzhiyun	waitiperf $netns1 $!
138*4882a593Smuzhiyun	n2 iperf3 -Z -t 3 -b 0 -u -c 192.168.241.1
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun	# UDP over IPv6
141*4882a593Smuzhiyun	n2 iperf3 -s -1 -B fd00::2 &
142*4882a593Smuzhiyun	waitiperf $netns2 $!
143*4882a593Smuzhiyun	n1 iperf3 -Z -t 3 -b 0 -u -c fd00::2
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun	# TCP over IPv4, in parallel
146*4882a593Smuzhiyun	for max in 4 5 50; do
147*4882a593Smuzhiyun		local pids=( )
148*4882a593Smuzhiyun		for ((i=0; i < max; ++i)) do
149*4882a593Smuzhiyun			n2 iperf3 -p $(( 5200 + i )) -s -1 -B 192.168.241.2 &
150*4882a593Smuzhiyun			pids+=( $! ); waitiperf $netns2 $! $(( 5200 + i ))
151*4882a593Smuzhiyun		done
152*4882a593Smuzhiyun		for ((i=0; i < max; ++i)) do
153*4882a593Smuzhiyun			n1 iperf3 -Z -t 3 -p $(( 5200 + i )) -c 192.168.241.2 &
154*4882a593Smuzhiyun		done
155*4882a593Smuzhiyun		wait "${pids[@]}"
156*4882a593Smuzhiyun	done
157*4882a593Smuzhiyun}
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun[[ $(ip1 link show dev wg0) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}"
160*4882a593Smuzhiyunbig_mtu=$(( 34816 - 1500 + $orig_mtu ))
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun# Test using IPv4 as outer transport
163*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
164*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
165*4882a593Smuzhiyun# Before calling tests, we first make sure that the stats counters and timestamper are working
166*4882a593Smuzhiyunn2 ping -c 10 -f -W 1 192.168.241.1
167*4882a593Smuzhiyun{ read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip2 -stats link show dev wg0)
168*4882a593Smuzhiyun(( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
169*4882a593Smuzhiyun{ read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip1 -stats link show dev wg0)
170*4882a593Smuzhiyun(( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
171*4882a593Smuzhiyunread _ rx_bytes tx_bytes < <(n2 wg show wg0 transfer)
172*4882a593Smuzhiyun(( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
173*4882a593Smuzhiyunread _ rx_bytes tx_bytes < <(n1 wg show wg0 transfer)
174*4882a593Smuzhiyun(( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
175*4882a593Smuzhiyunread _ timestamp < <(n1 wg show wg0 latest-handshakes)
176*4882a593Smuzhiyun(( timestamp != 0 ))
177*4882a593Smuzhiyun
178*4882a593Smuzhiyuntests
179*4882a593Smuzhiyunip1 link set wg0 mtu $big_mtu
180*4882a593Smuzhiyunip2 link set wg0 mtu $big_mtu
181*4882a593Smuzhiyuntests
182*4882a593Smuzhiyun
183*4882a593Smuzhiyunip1 link set wg0 mtu $orig_mtu
184*4882a593Smuzhiyunip2 link set wg0 mtu $orig_mtu
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun# Test using IPv6 as outer transport
187*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint [::1]:2
188*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint [::1]:1
189*4882a593Smuzhiyuntests
190*4882a593Smuzhiyunip1 link set wg0 mtu $big_mtu
191*4882a593Smuzhiyunip2 link set wg0 mtu $big_mtu
192*4882a593Smuzhiyuntests
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun# Test that route MTUs work with the padding
195*4882a593Smuzhiyunip1 link set wg0 mtu 1300
196*4882a593Smuzhiyunip2 link set wg0 mtu 1300
197*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
198*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
199*4882a593Smuzhiyunn0 iptables -A INPUT -m length --length 1360 -j DROP
200*4882a593Smuzhiyunn1 ip route add 192.168.241.2/32 dev wg0 mtu 1299
201*4882a593Smuzhiyunn2 ip route add 192.168.241.1/32 dev wg0 mtu 1299
202*4882a593Smuzhiyunn2 ping -c 1 -W 1 -s 1269 192.168.241.1
203*4882a593Smuzhiyunn2 ip route delete 192.168.241.1/32 dev wg0 mtu 1299
204*4882a593Smuzhiyunn1 ip route delete 192.168.241.2/32 dev wg0 mtu 1299
205*4882a593Smuzhiyunn0 iptables -F INPUT
206*4882a593Smuzhiyun
207*4882a593Smuzhiyunip1 link set wg0 mtu $orig_mtu
208*4882a593Smuzhiyunip2 link set wg0 mtu $orig_mtu
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun# Test using IPv4 that roaming works
211*4882a593Smuzhiyunip0 -4 addr del 127.0.0.1/8 dev lo
212*4882a593Smuzhiyunip0 -4 addr add 127.212.121.99/8 dev lo
213*4882a593Smuzhiyunn1 wg set wg0 listen-port 9999
214*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
215*4882a593Smuzhiyunn1 ping6 -W 1 -c 1 fd00::2
216*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	127.212.121.99:9999" ]]
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun# Test using IPv6 that roaming works
219*4882a593Smuzhiyunn1 wg set wg0 listen-port 9998
220*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint [::1]:2
221*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
222*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	[::1]:9998" ]]
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun# Test that crypto-RP filter works
225*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" allowed-ips 192.168.241.0/24
226*4882a593Smuzhiyunexec 4< <(n1 ncat -l -u -p 1111)
227*4882a593Smuzhiyunncat_pid=$!
228*4882a593Smuzhiyunwaitncatudp $netns1 $ncat_pid
229*4882a593Smuzhiyunn2 ncat -u 192.168.241.1 1111 <<<"X"
230*4882a593Smuzhiyunread -r -N 1 -t 1 out <&4 && [[ $out == "X" ]]
231*4882a593Smuzhiyunkill $ncat_pid
232*4882a593Smuzhiyunmore_specific_key="$(pp wg genkey | pp wg pubkey)"
233*4882a593Smuzhiyunn1 wg set wg0 peer "$more_specific_key" allowed-ips 192.168.241.2/32
234*4882a593Smuzhiyunn2 wg set wg0 listen-port 9997
235*4882a593Smuzhiyunexec 4< <(n1 ncat -l -u -p 1111)
236*4882a593Smuzhiyunncat_pid=$!
237*4882a593Smuzhiyunwaitncatudp $netns1 $ncat_pid
238*4882a593Smuzhiyunn2 ncat -u 192.168.241.1 1111 <<<"X"
239*4882a593Smuzhiyun! read -r -N 1 -t 1 out <&4 || false
240*4882a593Smuzhiyunkill $ncat_pid
241*4882a593Smuzhiyunn1 wg set wg0 peer "$more_specific_key" remove
242*4882a593Smuzhiyun[[ $(n1 wg show wg0 endpoints) == "$pub2	[::1]:9997" ]]
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun# Test that we can change private keys keys and immediately handshake
245*4882a593Smuzhiyunn1 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") allowed-ips 192.168.241.2/32 endpoint 127.0.0.1:2
246*4882a593Smuzhiyunn2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32
247*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
248*4882a593Smuzhiyunn1 wg set wg0 private-key <(echo "$key3")
249*4882a593Smuzhiyunn2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
250*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
251*4882a593Smuzhiyunn2 wg set wg0 peer "$pub3" remove
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun# Test that we can route wg through wg
254*4882a593Smuzhiyunip1 addr flush dev wg0
255*4882a593Smuzhiyunip2 addr flush dev wg0
256*4882a593Smuzhiyunip1 addr add fd00::5:1/112 dev wg0
257*4882a593Smuzhiyunip2 addr add fd00::5:2/112 dev wg0
258*4882a593Smuzhiyunn1 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") allowed-ips fd00::5:2/128 endpoint 127.0.0.1:2
259*4882a593Smuzhiyunn2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips fd00::5:1/128 endpoint 127.212.121.99:9998
260*4882a593Smuzhiyunip1 link add wg1 type wireguard
261*4882a593Smuzhiyunip2 link add wg1 type wireguard
262*4882a593Smuzhiyunip1 addr add 192.168.241.1/24 dev wg1
263*4882a593Smuzhiyunip1 addr add fd00::1/112 dev wg1
264*4882a593Smuzhiyunip2 addr add 192.168.241.2/24 dev wg1
265*4882a593Smuzhiyunip2 addr add fd00::2/112 dev wg1
266*4882a593Smuzhiyunip1 link set mtu 1340 up dev wg1
267*4882a593Smuzhiyunip2 link set mtu 1340 up dev wg1
268*4882a593Smuzhiyunn1 wg set wg1 listen-port 5 private-key <(echo "$key3") peer "$pub4" allowed-ips 192.168.241.2/32,fd00::2/128 endpoint [fd00::5:2]:5
269*4882a593Smuzhiyunn2 wg set wg1 listen-port 5 private-key <(echo "$key4") peer "$pub3" allowed-ips 192.168.241.1/32,fd00::1/128 endpoint [fd00::5:1]:5
270*4882a593Smuzhiyuntests
271*4882a593Smuzhiyun# Try to set up a routing loop between the two namespaces
272*4882a593Smuzhiyunip1 link set netns $netns0 dev wg1
273*4882a593Smuzhiyunip0 addr add 192.168.241.1/24 dev wg1
274*4882a593Smuzhiyunip0 link set up dev wg1
275*4882a593Smuzhiyunn0 ping -W 1 -c 1 192.168.241.2
276*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7
277*4882a593Smuzhiyunip2 link del wg0
278*4882a593Smuzhiyunip2 link del wg1
279*4882a593Smuzhiyunread _ _ tx_bytes_before < <(n0 wg show wg1 transfer)
280*4882a593Smuzhiyun! n0 ping -W 1 -c 10 -f 192.168.241.2 || false
281*4882a593Smuzhiyunsleep 1
282*4882a593Smuzhiyunread _ _ tx_bytes_after < <(n0 wg show wg1 transfer)
283*4882a593Smuzhiyun(( tx_bytes_after - tx_bytes_before < 70000 ))
284*4882a593Smuzhiyun
285*4882a593Smuzhiyunip0 link del wg1
286*4882a593Smuzhiyunip1 link del wg0
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun# Test using NAT. We now change the topology to this:
289*4882a593Smuzhiyun# ┌────────────────────────────────────────┐    ┌────────────────────────────────────────────────┐     ┌────────────────────────────────────────┐
290*4882a593Smuzhiyun# │             $ns1 namespace             │    │                 $ns0 namespace                 │     │             $ns2 namespace             │
291*4882a593Smuzhiyun# │                                        │    │                                                │     │                                        │
292*4882a593Smuzhiyun# │  ┌─────┐             ┌─────┐           │    │    ┌──────┐              ┌──────┐              │     │  ┌─────┐            ┌─────┐            │
293*4882a593Smuzhiyun# │  │ wg0 │─────────────│vethc│───────────┼────┼────│vethrc│              │vethrs│──────────────┼─────┼──│veths│────────────│ wg0 │            │
294*4882a593Smuzhiyun# │  ├─────┴──────────┐  ├─────┴──────────┐│    │    ├──────┴─────────┐    ├──────┴────────────┐ │     │  ├─────┴──────────┐ ├─────┴──────────┐ │
295*4882a593Smuzhiyun# │  │192.168.241.1/24│  │192.168.1.100/24││    │    │192.168.1.1/24  │    │10.0.0.1/24        │ │     │  │10.0.0.100/24   │ │192.168.241.2/24│ │
296*4882a593Smuzhiyun# │  │fd00::1/24      │  │                ││    │    │                │    │SNAT:192.168.1.0/24│ │     │  │                │ │fd00::2/24      │ │
297*4882a593Smuzhiyun# │  └────────────────┘  └────────────────┘│    │    └────────────────┘    └───────────────────┘ │     │  └────────────────┘ └────────────────┘ │
298*4882a593Smuzhiyun# └────────────────────────────────────────┘    └────────────────────────────────────────────────┘     └────────────────────────────────────────┘
299*4882a593Smuzhiyun
300*4882a593Smuzhiyunip1 link add dev wg0 type wireguard
301*4882a593Smuzhiyunip2 link add dev wg0 type wireguard
302*4882a593Smuzhiyunconfigure_peers
303*4882a593Smuzhiyun
304*4882a593Smuzhiyunip0 link add vethrc type veth peer name vethc
305*4882a593Smuzhiyunip0 link add vethrs type veth peer name veths
306*4882a593Smuzhiyunip0 link set vethc netns $netns1
307*4882a593Smuzhiyunip0 link set veths netns $netns2
308*4882a593Smuzhiyunip0 link set vethrc up
309*4882a593Smuzhiyunip0 link set vethrs up
310*4882a593Smuzhiyunip0 addr add 192.168.1.1/24 dev vethrc
311*4882a593Smuzhiyunip0 addr add 10.0.0.1/24 dev vethrs
312*4882a593Smuzhiyunip1 addr add 192.168.1.100/24 dev vethc
313*4882a593Smuzhiyunip1 link set vethc up
314*4882a593Smuzhiyunip1 route add default via 192.168.1.1
315*4882a593Smuzhiyunip2 addr add 10.0.0.100/24 dev veths
316*4882a593Smuzhiyunip2 link set veths up
317*4882a593Smuzhiyunwaitiface $netns0 vethrc
318*4882a593Smuzhiyunwaitiface $netns0 vethrs
319*4882a593Smuzhiyunwaitiface $netns1 vethc
320*4882a593Smuzhiyunwaitiface $netns2 veths
321*4882a593Smuzhiyun
322*4882a593Smuzhiyunn0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
323*4882a593Smuzhiyunn0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout'
324*4882a593Smuzhiyunn0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream'
325*4882a593Smuzhiyunn0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1
326*4882a593Smuzhiyun
327*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 10.0.0.100:2 persistent-keepalive 1
328*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
329*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
330*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
331*4882a593Smuzhiyun# Demonstrate n2 can still send packets to n1, since persistent-keepalive will prevent connection tracking entry from expiring (to see entries: `n0 conntrack -L`).
332*4882a593Smuzhiyunpp sleep 3
333*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
334*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" persistent-keepalive 0
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun# Test that sk_bound_dev_if works
337*4882a593Smuzhiyunn1 ping -I wg0 -c 1 -W 1 192.168.241.2
338*4882a593Smuzhiyun# What about when the mark changes and the packet must be rerouted?
339*4882a593Smuzhiyunn1 iptables -t mangle -I OUTPUT -j MARK --set-xmark 1
340*4882a593Smuzhiyunn1 ping -c 1 -W 1 192.168.241.2 # First the boring case
341*4882a593Smuzhiyunn1 ping -I wg0 -c 1 -W 1 192.168.241.2 # Then the sk_bound_dev_if case
342*4882a593Smuzhiyunn1 iptables -t mangle -D OUTPUT -j MARK --set-xmark 1
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun# Test that onion routing works, even when it loops
345*4882a593Smuzhiyunn1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
346*4882a593Smuzhiyunip1 addr add 192.168.242.1/24 dev wg0
347*4882a593Smuzhiyunip2 link add wg1 type wireguard
348*4882a593Smuzhiyunip2 addr add 192.168.242.2/24 dev wg1
349*4882a593Smuzhiyunn2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32
350*4882a593Smuzhiyunip2 link set wg1 up
351*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.242.2
352*4882a593Smuzhiyunip2 link del wg1
353*4882a593Smuzhiyunn1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5
354*4882a593Smuzhiyun! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel
355*4882a593Smuzhiyunn1 wg set wg0 peer "$pub3" remove
356*4882a593Smuzhiyunip1 addr del 192.168.242.1/24 dev wg0
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun# Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
359*4882a593Smuzhiyunip1 -6 addr add fc00::9/96 dev vethc
360*4882a593Smuzhiyunip1 -6 route add default via fc00::1
361*4882a593Smuzhiyunip2 -4 addr add 192.168.99.7/32 dev wg0
362*4882a593Smuzhiyunip2 -6 addr add abab::1111/128 dev wg0
363*4882a593Smuzhiyunn1 wg set wg0 fwmark 51820 peer "$pub2" allowed-ips 192.168.99.7,abab::1111
364*4882a593Smuzhiyunip1 -6 route add default dev wg0 table 51820
365*4882a593Smuzhiyunip1 -6 rule add not fwmark 51820 table 51820
366*4882a593Smuzhiyunip1 -6 rule add table main suppress_prefixlength 0
367*4882a593Smuzhiyunip1 -4 route add default dev wg0 table 51820
368*4882a593Smuzhiyunip1 -4 rule add not fwmark 51820 table 51820
369*4882a593Smuzhiyunip1 -4 rule add table main suppress_prefixlength 0
370*4882a593Smuzhiyunn1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/vethc/rp_filter'
371*4882a593Smuzhiyun# Flood the pings instead of sending just one, to trigger routing table reference counting bugs.
372*4882a593Smuzhiyunn1 ping -W 1 -c 100 -f 192.168.99.7
373*4882a593Smuzhiyunn1 ping -W 1 -c 100 -f abab::1111
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun# Have ns2 NAT into wg0 packets from ns0, but return an icmp error along the right route.
376*4882a593Smuzhiyunn2 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 192.168.241.0/24 -j SNAT --to 192.168.241.2
377*4882a593Smuzhiyunn0 iptables -t filter -A INPUT \! -s 10.0.0.0/24 -i vethrs -j DROP # Manual rpfilter just to be explicit.
378*4882a593Smuzhiyunn2 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
379*4882a593Smuzhiyunip0 -4 route add 192.168.241.1 via 10.0.0.100
380*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" remove
381*4882a593Smuzhiyun[[ $(! n0 ping -W 1 -c 1 192.168.241.1 || false) == *"From 10.0.0.100 icmp_seq=1 Destination Host Unreachable"* ]]
382*4882a593Smuzhiyun
383*4882a593Smuzhiyunn0 iptables -t nat -F
384*4882a593Smuzhiyunn0 iptables -t filter -F
385*4882a593Smuzhiyunn2 iptables -t nat -F
386*4882a593Smuzhiyunip0 link del vethrc
387*4882a593Smuzhiyunip0 link del vethrs
388*4882a593Smuzhiyunip1 link del wg0
389*4882a593Smuzhiyunip2 link del wg0
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun# Test that saddr routing is sticky but not too sticky, changing to this topology:
392*4882a593Smuzhiyun# ┌────────────────────────────────────────┐    ┌────────────────────────────────────────┐
393*4882a593Smuzhiyun# │             $ns1 namespace             │    │             $ns2 namespace             │
394*4882a593Smuzhiyun# │                                        │    │                                        │
395*4882a593Smuzhiyun# │  ┌─────┐             ┌─────┐           │    │  ┌─────┐            ┌─────┐            │
396*4882a593Smuzhiyun# │  │ wg0 │─────────────│veth1│───────────┼────┼──│veth2│────────────│ wg0 │            │
397*4882a593Smuzhiyun# │  ├─────┴──────────┐  ├─────┴──────────┐│    │  ├─────┴──────────┐ ├─────┴──────────┐ │
398*4882a593Smuzhiyun# │  │192.168.241.1/24│  │10.0.0.1/24     ││    │  │10.0.0.2/24     │ │192.168.241.2/24│ │
399*4882a593Smuzhiyun# │  │fd00::1/24      │  │fd00:aa::1/96   ││    │  │fd00:aa::2/96   │ │fd00::2/24      │ │
400*4882a593Smuzhiyun# │  └────────────────┘  └────────────────┘│    │  └────────────────┘ └────────────────┘ │
401*4882a593Smuzhiyun# └────────────────────────────────────────┘    └────────────────────────────────────────┘
402*4882a593Smuzhiyun
403*4882a593Smuzhiyunip1 link add dev wg0 type wireguard
404*4882a593Smuzhiyunip2 link add dev wg0 type wireguard
405*4882a593Smuzhiyunconfigure_peers
406*4882a593Smuzhiyunip1 link add veth1 type veth peer name veth2
407*4882a593Smuzhiyunip1 link set veth2 netns $netns2
408*4882a593Smuzhiyunn1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
409*4882a593Smuzhiyunn2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
410*4882a593Smuzhiyunn1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad'
411*4882a593Smuzhiyunn2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad'
412*4882a593Smuzhiyunn1 bash -c 'printf 1 > /proc/sys/net/ipv4/conf/veth1/promote_secondaries'
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun# First we check that we aren't overly sticky and can fall over to new IPs when old ones are removed
415*4882a593Smuzhiyunip1 addr add 10.0.0.1/24 dev veth1
416*4882a593Smuzhiyunip1 addr add fd00:aa::1/96 dev veth1
417*4882a593Smuzhiyunip2 addr add 10.0.0.2/24 dev veth2
418*4882a593Smuzhiyunip2 addr add fd00:aa::2/96 dev veth2
419*4882a593Smuzhiyunip1 link set veth1 up
420*4882a593Smuzhiyunip2 link set veth2 up
421*4882a593Smuzhiyunwaitiface $netns1 veth1
422*4882a593Smuzhiyunwaitiface $netns2 veth2
423*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
424*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
425*4882a593Smuzhiyunip1 addr add 10.0.0.10/24 dev veth1
426*4882a593Smuzhiyunip1 addr del 10.0.0.1/24 dev veth1
427*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
428*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2
429*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
430*4882a593Smuzhiyunip1 addr add fd00:aa::10/96 dev veth1
431*4882a593Smuzhiyunip1 addr del fd00:aa::1/96 dev veth1
432*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun# Now we show that we can successfully do reply to sender routing
435*4882a593Smuzhiyunip1 link set veth1 down
436*4882a593Smuzhiyunip2 link set veth2 down
437*4882a593Smuzhiyunip1 addr flush dev veth1
438*4882a593Smuzhiyunip2 addr flush dev veth2
439*4882a593Smuzhiyunip1 addr add 10.0.0.1/24 dev veth1
440*4882a593Smuzhiyunip1 addr add 10.0.0.2/24 dev veth1
441*4882a593Smuzhiyunip1 addr add fd00:aa::1/96 dev veth1
442*4882a593Smuzhiyunip1 addr add fd00:aa::2/96 dev veth1
443*4882a593Smuzhiyunip2 addr add 10.0.0.3/24 dev veth2
444*4882a593Smuzhiyunip2 addr add fd00:aa::3/96 dev veth2
445*4882a593Smuzhiyunip1 link set veth1 up
446*4882a593Smuzhiyunip2 link set veth2 up
447*4882a593Smuzhiyunwaitiface $netns1 veth1
448*4882a593Smuzhiyunwaitiface $netns2 veth2
449*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint 10.0.0.1:1
450*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
451*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
452*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1
453*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
454*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	[fd00:aa::1]:1" ]]
455*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint 10.0.0.2:1
456*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
457*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.2:1" ]]
458*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint [fd00:aa::2]:1
459*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
460*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	[fd00:aa::2]:1" ]]
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun# What happens if the inbound destination address belongs to a different interface as the default route?
463*4882a593Smuzhiyunip1 link add dummy0 type dummy
464*4882a593Smuzhiyunip1 addr add 10.50.0.1/24 dev dummy0
465*4882a593Smuzhiyunip1 link set dummy0 up
466*4882a593Smuzhiyunip2 route add 10.50.0.0/24 dev veth2
467*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint 10.50.0.1:1
468*4882a593Smuzhiyunn2 ping -W 1 -c 1 192.168.241.1
469*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.50.0.1:1" ]]
470*4882a593Smuzhiyun
471*4882a593Smuzhiyunip1 link del dummy0
472*4882a593Smuzhiyunip1 addr flush dev veth1
473*4882a593Smuzhiyunip2 addr flush dev veth2
474*4882a593Smuzhiyunip1 route flush dev veth1
475*4882a593Smuzhiyunip2 route flush dev veth2
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun# Now we see what happens if another interface route takes precedence over an ongoing one
478*4882a593Smuzhiyunip1 link add veth3 type veth peer name veth4
479*4882a593Smuzhiyunip1 link set veth4 netns $netns2
480*4882a593Smuzhiyunip1 addr add 10.0.0.1/24 dev veth1
481*4882a593Smuzhiyunip2 addr add 10.0.0.2/24 dev veth2
482*4882a593Smuzhiyunip1 addr add 10.0.0.3/24 dev veth3
483*4882a593Smuzhiyunip1 link set veth1 up
484*4882a593Smuzhiyunip2 link set veth2 up
485*4882a593Smuzhiyunip1 link set veth3 up
486*4882a593Smuzhiyunip2 link set veth4 up
487*4882a593Smuzhiyunwaitiface $netns1 veth1
488*4882a593Smuzhiyunwaitiface $netns2 veth2
489*4882a593Smuzhiyunwaitiface $netns1 veth3
490*4882a593Smuzhiyunwaitiface $netns2 veth4
491*4882a593Smuzhiyunip1 route flush dev veth1
492*4882a593Smuzhiyunip1 route flush dev veth3
493*4882a593Smuzhiyunip1 route add 10.0.0.0/24 dev veth1 src 10.0.0.1 metric 2
494*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
495*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
496*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
497*4882a593Smuzhiyunip1 route add 10.0.0.0/24 dev veth3 src 10.0.0.3 metric 1
498*4882a593Smuzhiyunn1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter'
499*4882a593Smuzhiyunn2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth4/rp_filter'
500*4882a593Smuzhiyunn1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
501*4882a593Smuzhiyunn2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
502*4882a593Smuzhiyunn1 ping -W 1 -c 1 192.168.241.2
503*4882a593Smuzhiyun[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.3:1" ]]
504*4882a593Smuzhiyun
505*4882a593Smuzhiyunip1 link del veth1
506*4882a593Smuzhiyunip1 link del veth3
507*4882a593Smuzhiyunip1 link del wg0
508*4882a593Smuzhiyunip2 link del wg0
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun# We test that Netlink/IPC is working properly by doing things that usually cause split responses
511*4882a593Smuzhiyunip0 link add dev wg0 type wireguard
512*4882a593Smuzhiyunconfig=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" )
513*4882a593Smuzhiyunfor a in {1..255}; do
514*4882a593Smuzhiyun	for b in {0..255}; do
515*4882a593Smuzhiyun		config+=( "AllowedIPs=$a.$b.0.0/16,$a::$b/128" )
516*4882a593Smuzhiyun	done
517*4882a593Smuzhiyundone
518*4882a593Smuzhiyunn0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
519*4882a593Smuzhiyuni=0
520*4882a593Smuzhiyunfor ip in $(n0 wg show wg0 allowed-ips); do
521*4882a593Smuzhiyun	((++i))
522*4882a593Smuzhiyundone
523*4882a593Smuzhiyun((i == 255*256*2+1))
524*4882a593Smuzhiyunip0 link del wg0
525*4882a593Smuzhiyunip0 link add dev wg0 type wireguard
526*4882a593Smuzhiyunconfig=( "[Interface]" "PrivateKey=$(wg genkey)" )
527*4882a593Smuzhiyunfor a in {1..40}; do
528*4882a593Smuzhiyun	config+=( "[Peer]" "PublicKey=$(wg genkey)" )
529*4882a593Smuzhiyun	for b in {1..52}; do
530*4882a593Smuzhiyun		config+=( "AllowedIPs=$a.$b.0.0/16" )
531*4882a593Smuzhiyun	done
532*4882a593Smuzhiyundone
533*4882a593Smuzhiyunn0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
534*4882a593Smuzhiyuni=0
535*4882a593Smuzhiyunwhile read -r line; do
536*4882a593Smuzhiyun	j=0
537*4882a593Smuzhiyun	for ip in $line; do
538*4882a593Smuzhiyun		((++j))
539*4882a593Smuzhiyun	done
540*4882a593Smuzhiyun	((j == 53))
541*4882a593Smuzhiyun	((++i))
542*4882a593Smuzhiyundone < <(n0 wg show wg0 allowed-ips)
543*4882a593Smuzhiyun((i == 40))
544*4882a593Smuzhiyunip0 link del wg0
545*4882a593Smuzhiyunip0 link add wg0 type wireguard
546*4882a593Smuzhiyunconfig=( )
547*4882a593Smuzhiyunfor i in {1..29}; do
548*4882a593Smuzhiyun	config+=( "[Peer]" "PublicKey=$(wg genkey)" )
549*4882a593Smuzhiyundone
550*4882a593Smuzhiyunconfig+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" )
551*4882a593Smuzhiyunn0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
552*4882a593Smuzhiyunn0 wg showconf wg0 > /dev/null
553*4882a593Smuzhiyunip0 link del wg0
554*4882a593Smuzhiyun
555*4882a593Smuzhiyunallowedips=( )
556*4882a593Smuzhiyunfor i in {1..197}; do
557*4882a593Smuzhiyun        allowedips+=( abcd::$i )
558*4882a593Smuzhiyundone
559*4882a593Smuzhiyunsaved_ifs="$IFS"
560*4882a593SmuzhiyunIFS=,
561*4882a593Smuzhiyunallowedips="${allowedips[*]}"
562*4882a593SmuzhiyunIFS="$saved_ifs"
563*4882a593Smuzhiyunip0 link add wg0 type wireguard
564*4882a593Smuzhiyunn0 wg set wg0 peer "$pub1"
565*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" allowed-ips "$allowedips"
566*4882a593Smuzhiyun{
567*4882a593Smuzhiyun	read -r pub allowedips
568*4882a593Smuzhiyun	[[ $pub == "$pub1" && $allowedips == "(none)" ]]
569*4882a593Smuzhiyun	read -r pub allowedips
570*4882a593Smuzhiyun	[[ $pub == "$pub2" ]]
571*4882a593Smuzhiyun	i=0
572*4882a593Smuzhiyun	for _ in $allowedips; do
573*4882a593Smuzhiyun		((++i))
574*4882a593Smuzhiyun	done
575*4882a593Smuzhiyun	((i == 197))
576*4882a593Smuzhiyun} < <(n0 wg show wg0 allowed-ips)
577*4882a593Smuzhiyunip0 link del wg0
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun! n0 wg show doesnotexist || false
580*4882a593Smuzhiyun
581*4882a593Smuzhiyunip0 link add wg0 type wireguard
582*4882a593Smuzhiyunn0 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk")
583*4882a593Smuzhiyun[[ $(n0 wg show wg0 private-key) == "$key1" ]]
584*4882a593Smuzhiyun[[ $(n0 wg show wg0 preshared-keys) == "$pub2	$psk" ]]
585*4882a593Smuzhiyunn0 wg set wg0 private-key /dev/null peer "$pub2" preshared-key /dev/null
586*4882a593Smuzhiyun[[ $(n0 wg show wg0 private-key) == "(none)" ]]
587*4882a593Smuzhiyun[[ $(n0 wg show wg0 preshared-keys) == "$pub2	(none)" ]]
588*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2"
589*4882a593Smuzhiyunn0 wg set wg0 private-key <(echo "$key2")
590*4882a593Smuzhiyun[[ $(n0 wg show wg0 public-key) == "$pub2" ]]
591*4882a593Smuzhiyun[[ -z $(n0 wg show wg0 peers) ]]
592*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2"
593*4882a593Smuzhiyun[[ -z $(n0 wg show wg0 peers) ]]
594*4882a593Smuzhiyunn0 wg set wg0 private-key <(echo "$key1")
595*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2"
596*4882a593Smuzhiyun[[ $(n0 wg show wg0 peers) == "$pub2" ]]
597*4882a593Smuzhiyunn0 wg set wg0 private-key <(echo "/${key1:1}")
598*4882a593Smuzhiyun[[ $(n0 wg show wg0 private-key) == "+${key1:1}" ]]
599*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0,10.0.0.0/8,100.0.0.0/10,172.16.0.0/12,192.168.0.0/16
600*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0
601*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75
602*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" allowed-ips ::/0
603*4882a593Smuzhiyunn0 wg set wg0 peer "$pub2" remove
604*4882a593Smuzhiyunfor low_order_point in AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38=; do
605*4882a593Smuzhiyun	n0 wg set wg0 peer "$low_order_point" persistent-keepalive 1 endpoint 127.0.0.1:1111
606*4882a593Smuzhiyundone
607*4882a593Smuzhiyun[[ -n $(n0 wg show wg0 peers) ]]
608*4882a593Smuzhiyunexec 4< <(n0 ncat -l -u -p 1111)
609*4882a593Smuzhiyunncat_pid=$!
610*4882a593Smuzhiyunwaitncatudp $netns0 $ncat_pid
611*4882a593Smuzhiyunip0 link set wg0 up
612*4882a593Smuzhiyun! read -r -n 1 -t 2 <&4 || false
613*4882a593Smuzhiyunkill $ncat_pid
614*4882a593Smuzhiyunip0 link del wg0
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun# Ensure that dst_cache references don't outlive netns lifetime
617*4882a593Smuzhiyunip1 link add dev wg0 type wireguard
618*4882a593Smuzhiyunip2 link add dev wg0 type wireguard
619*4882a593Smuzhiyunconfigure_peers
620*4882a593Smuzhiyunip1 link add veth1 type veth peer name veth2
621*4882a593Smuzhiyunip1 link set veth2 netns $netns2
622*4882a593Smuzhiyunip1 addr add fd00:aa::1/64 dev veth1
623*4882a593Smuzhiyunip2 addr add fd00:aa::2/64 dev veth2
624*4882a593Smuzhiyunip1 link set veth1 up
625*4882a593Smuzhiyunip2 link set veth2 up
626*4882a593Smuzhiyunwaitiface $netns1 veth1
627*4882a593Smuzhiyunwaitiface $netns2 veth2
628*4882a593Smuzhiyunip1 -6 route add default dev veth1 via fd00:aa::2
629*4882a593Smuzhiyunip2 -6 route add default dev veth2 via fd00:aa::1
630*4882a593Smuzhiyunn1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2
631*4882a593Smuzhiyunn2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1
632*4882a593Smuzhiyunn1 ping6 -c 1 fd00::2
633*4882a593Smuzhiyunpp ip netns delete $netns1
634*4882a593Smuzhiyunpp ip netns delete $netns2
635*4882a593Smuzhiyunpp ip netns add $netns1
636*4882a593Smuzhiyunpp ip netns add $netns2
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun# Ensure there aren't circular reference loops
639*4882a593Smuzhiyunip1 link add wg1 type wireguard
640*4882a593Smuzhiyunip2 link add wg2 type wireguard
641*4882a593Smuzhiyunip1 link set wg1 netns $netns2
642*4882a593Smuzhiyunip2 link set wg2 netns $netns1
643*4882a593Smuzhiyunpp ip netns delete $netns1
644*4882a593Smuzhiyunpp ip netns delete $netns2
645*4882a593Smuzhiyunpp ip netns add $netns1
646*4882a593Smuzhiyunpp ip netns add $netns2
647*4882a593Smuzhiyun
648*4882a593Smuzhiyunsleep 2 # Wait for cleanup and grace periods
649*4882a593Smuzhiyundeclare -A objects
650*4882a593Smuzhiyunwhile read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do
651*4882a593Smuzhiyun	[[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ ?[0-9]*)\ .*(created|destroyed).* ]] || continue
652*4882a593Smuzhiyun	objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}"
653*4882a593Smuzhiyundone < /dev/kmsg
654*4882a593Smuzhiyunalldeleted=1
655*4882a593Smuzhiyunfor object in "${!objects[@]}"; do
656*4882a593Smuzhiyun	if [[ ${objects["$object"]} != *createddestroyed && ${objects["$object"]} != *createdcreateddestroyeddestroyed ]]; then
657*4882a593Smuzhiyun		echo "Error: $object: merely ${objects["$object"]}" >&3
658*4882a593Smuzhiyun		alldeleted=0
659*4882a593Smuzhiyun	fi
660*4882a593Smuzhiyundone
661*4882a593Smuzhiyun[[ $alldeleted -eq 1 ]]
662*4882a593Smuzhiyunpretty "" "Objects that were created were also destroyed."
663