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