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.
24set -e
25
26exec 3>&1
27export LANG=C
28export WG_HIDE_KEYS=never
29netns0="wg-test-$$-0"
30netns1="wg-test-$$-1"
31netns2="wg-test-$$-2"
32pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; }
33pp() { pretty "" "$*"; "$@"; }
34maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; }
35n0() { pretty 0 "$*"; maybe_exec ip netns exec $netns0 "$@"; }
36n1() { pretty 1 "$*"; maybe_exec ip netns exec $netns1 "$@"; }
37n2() { pretty 2 "$*"; maybe_exec ip netns exec $netns2 "$@"; }
38ip0() { pretty 0 "ip $*"; ip -n $netns0 "$@"; }
39ip1() { pretty 1 "ip $*"; ip -n $netns1 "$@"; }
40ip2() { pretty 2 "ip $*"; ip -n $netns2 "$@"; }
41sleep() { read -t "$1" -N 1 || true; }
42waitiperf() { pretty "${1//*-}" "wait for iperf:5201 pid $2"; while [[ $(ss -N "$1" -tlpH 'sport = 5201') != *\"iperf3\",pid=$2,fd=* ]]; do sleep 0.1; done; }
43waitncatudp() { pretty "${1//*-}" "wait for udp:1111 pid $2"; while [[ $(ss -N "$1" -ulpH 'sport = 1111') != *\"ncat\",pid=$2,fd=* ]]; do sleep 0.1; done; }
44waitiface() { 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
46cleanup() {
47	set +e
48	exec 2>/dev/null
49	printf "$orig_message_cost" > /proc/sys/net/core/message_cost
50	ip0 link del dev wg0
51	ip1 link del dev wg0
52	ip2 link del dev wg0
53	local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)"
54	[[ -n $to_kill ]] && kill $to_kill
55	pp ip netns del $netns1
56	pp ip netns del $netns2
57	pp ip netns del $netns0
58	exit
59}
60
61orig_message_cost="$(< /proc/sys/net/core/message_cost)"
62trap cleanup EXIT
63printf 0 > /proc/sys/net/core/message_cost
64
65ip netns del $netns0 2>/dev/null || true
66ip netns del $netns1 2>/dev/null || true
67ip netns del $netns2 2>/dev/null || true
68pp ip netns add $netns0
69pp ip netns add $netns1
70pp ip netns add $netns2
71ip0 link set up dev lo
72
73ip0 link add dev wg0 type wireguard
74ip0 link set wg0 netns $netns1
75ip0 link add dev wg0 type wireguard
76ip0 link set wg0 netns $netns2
77key1="$(pp wg genkey)"
78key2="$(pp wg genkey)"
79key3="$(pp wg genkey)"
80pub1="$(pp wg pubkey <<<"$key1")"
81pub2="$(pp wg pubkey <<<"$key2")"
82pub3="$(pp wg pubkey <<<"$key3")"
83psk="$(pp wg genpsk)"
84[[ -n $key1 && -n $key2 && -n $psk ]]
85
86configure_peers() {
87	ip1 addr add 192.168.241.1/24 dev wg0
88	ip1 addr add fd00::1/24 dev wg0
89
90	ip2 addr add 192.168.241.2/24 dev wg0
91	ip2 addr add fd00::2/24 dev wg0
92
93	n1 wg set wg0 \
94		private-key <(echo "$key1") \
95		listen-port 1 \
96		peer "$pub2" \
97			preshared-key <(echo "$psk") \
98			allowed-ips 192.168.241.2/32,fd00::2/128
99	n2 wg set wg0 \
100		private-key <(echo "$key2") \
101		listen-port 2 \
102		peer "$pub1" \
103			preshared-key <(echo "$psk") \
104			allowed-ips 192.168.241.1/32,fd00::1/128
105
106	ip1 link set up dev wg0
107	ip2 link set up dev wg0
108}
109configure_peers
110
111tests() {
112	# Ping over IPv4
113	n2 ping -c 10 -f -W 1 192.168.241.1
114	n1 ping -c 10 -f -W 1 192.168.241.2
115
116	# Ping over IPv6
117	n2 ping6 -c 10 -f -W 1 fd00::1
118	n1 ping6 -c 10 -f -W 1 fd00::2
119
120	# TCP over IPv4
121	n2 iperf3 -s -1 -B 192.168.241.2 &
122	waitiperf $netns2 $!
123	n1 iperf3 -Z -t 3 -c 192.168.241.2
124
125	# TCP over IPv6
126	n1 iperf3 -s -1 -B fd00::1 &
127	waitiperf $netns1 $!
128	n2 iperf3 -Z -t 3 -c fd00::1
129
130	# UDP over IPv4
131	n1 iperf3 -s -1 -B 192.168.241.1 &
132	waitiperf $netns1 $!
133	n2 iperf3 -Z -t 3 -b 0 -u -c 192.168.241.1
134
135	# UDP over IPv6
136	n2 iperf3 -s -1 -B fd00::2 &
137	waitiperf $netns2 $!
138	n1 iperf3 -Z -t 3 -b 0 -u -c fd00::2
139}
140
141[[ $(ip1 link show dev wg0) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}"
142big_mtu=$(( 34816 - 1500 + $orig_mtu ))
143
144# Test using IPv4 as outer transport
145n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
146n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
147# Before calling tests, we first make sure that the stats counters and timestamper are working
148n2 ping -c 10 -f -W 1 192.168.241.1
149{ read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip2 -stats link show dev wg0)
150(( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
151{ read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip1 -stats link show dev wg0)
152(( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
153read _ rx_bytes tx_bytes < <(n2 wg show wg0 transfer)
154(( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
155read _ rx_bytes tx_bytes < <(n1 wg show wg0 transfer)
156(( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
157read _ timestamp < <(n1 wg show wg0 latest-handshakes)
158(( timestamp != 0 ))
159
160tests
161ip1 link set wg0 mtu $big_mtu
162ip2 link set wg0 mtu $big_mtu
163tests
164
165ip1 link set wg0 mtu $orig_mtu
166ip2 link set wg0 mtu $orig_mtu
167
168# Test using IPv6 as outer transport
169n1 wg set wg0 peer "$pub2" endpoint [::1]:2
170n2 wg set wg0 peer "$pub1" endpoint [::1]:1
171tests
172ip1 link set wg0 mtu $big_mtu
173ip2 link set wg0 mtu $big_mtu
174tests
175
176# Test that route MTUs work with the padding
177ip1 link set wg0 mtu 1300
178ip2 link set wg0 mtu 1300
179n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
180n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
181n0 iptables -A INPUT -m length --length 1360 -j DROP
182n1 ip route add 192.168.241.2/32 dev wg0 mtu 1299
183n2 ip route add 192.168.241.1/32 dev wg0 mtu 1299
184n2 ping -c 1 -W 1 -s 1269 192.168.241.1
185n2 ip route delete 192.168.241.1/32 dev wg0 mtu 1299
186n1 ip route delete 192.168.241.2/32 dev wg0 mtu 1299
187n0 iptables -F INPUT
188
189ip1 link set wg0 mtu $orig_mtu
190ip2 link set wg0 mtu $orig_mtu
191
192# Test using IPv4 that roaming works
193ip0 -4 addr del 127.0.0.1/8 dev lo
194ip0 -4 addr add 127.212.121.99/8 dev lo
195n1 wg set wg0 listen-port 9999
196n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
197n1 ping6 -W 1 -c 1 fd00::2
198[[ $(n2 wg show wg0 endpoints) == "$pub1	127.212.121.99:9999" ]]
199
200# Test using IPv6 that roaming works
201n1 wg set wg0 listen-port 9998
202n1 wg set wg0 peer "$pub2" endpoint [::1]:2
203n1 ping -W 1 -c 1 192.168.241.2
204[[ $(n2 wg show wg0 endpoints) == "$pub1	[::1]:9998" ]]
205
206# Test that crypto-RP filter works
207n1 wg set wg0 peer "$pub2" allowed-ips 192.168.241.0/24
208exec 4< <(n1 ncat -l -u -p 1111)
209ncat_pid=$!
210waitncatudp $netns1 $ncat_pid
211n2 ncat -u 192.168.241.1 1111 <<<"X"
212read -r -N 1 -t 1 out <&4 && [[ $out == "X" ]]
213kill $ncat_pid
214more_specific_key="$(pp wg genkey | pp wg pubkey)"
215n1 wg set wg0 peer "$more_specific_key" allowed-ips 192.168.241.2/32
216n2 wg set wg0 listen-port 9997
217exec 4< <(n1 ncat -l -u -p 1111)
218ncat_pid=$!
219waitncatudp $netns1 $ncat_pid
220n2 ncat -u 192.168.241.1 1111 <<<"X"
221! read -r -N 1 -t 1 out <&4 || false
222kill $ncat_pid
223n1 wg set wg0 peer "$more_specific_key" remove
224[[ $(n1 wg show wg0 endpoints) == "$pub2	[::1]:9997" ]]
225
226# Test that we can change private keys keys and immediately handshake
227n1 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
228n2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32
229n1 ping -W 1 -c 1 192.168.241.2
230n1 wg set wg0 private-key <(echo "$key3")
231n2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
232n1 ping -W 1 -c 1 192.168.241.2
233
234ip1 link del wg0
235ip2 link del wg0
236
237# Test using NAT. We now change the topology to this:
238# ┌────────────────────────────────────────┐    ┌────────────────────────────────────────────────┐     ┌────────────────────────────────────────┐
239# │             $ns1 namespace             │    │                 $ns0 namespace                 │     │             $ns2 namespace             │
240# │                                        │    │                                                │     │                                        │
241# │  ┌─────┐             ┌─────┐           │    │    ┌──────┐              ┌──────┐              │     │  ┌─────┐            ┌─────┐            │
242# │  │ wg0 │─────────────│vethc│───────────┼────┼────│vethrc│              │vethrs│──────────────┼─────┼──│veths│────────────│ wg0 │            │
243# │  ├─────┴──────────┐  ├─────┴──────────┐│    │    ├──────┴─────────┐    ├──────┴────────────┐ │     │  ├─────┴──────────┐ ├─────┴──────────┐ │
244# │  │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│ │
245# │  │fd00::1/24      │  │                ││    │    │                │    │SNAT:192.168.1.0/24│ │     │  │                │ │fd00::2/24      │ │
246# │  └────────────────┘  └────────────────┘│    │    └────────────────┘    └───────────────────┘ │     │  └────────────────┘ └────────────────┘ │
247# └────────────────────────────────────────┘    └────────────────────────────────────────────────┘     └────────────────────────────────────────┘
248
249ip1 link add dev wg0 type wireguard
250ip2 link add dev wg0 type wireguard
251configure_peers
252
253ip0 link add vethrc type veth peer name vethc
254ip0 link add vethrs type veth peer name veths
255ip0 link set vethc netns $netns1
256ip0 link set veths netns $netns2
257ip0 link set vethrc up
258ip0 link set vethrs up
259ip0 addr add 192.168.1.1/24 dev vethrc
260ip0 addr add 10.0.0.1/24 dev vethrs
261ip1 addr add 192.168.1.100/24 dev vethc
262ip1 link set vethc up
263ip1 route add default via 192.168.1.1
264ip2 addr add 10.0.0.100/24 dev veths
265ip2 link set veths up
266waitiface $netns0 vethrc
267waitiface $netns0 vethrs
268waitiface $netns1 vethc
269waitiface $netns2 veths
270
271n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
272n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout'
273n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream'
274n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1
275
276n1 wg set wg0 peer "$pub2" endpoint 10.0.0.100:2 persistent-keepalive 1
277n1 ping -W 1 -c 1 192.168.241.2
278n2 ping -W 1 -c 1 192.168.241.1
279[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
280# Demonstrate n2 can still send packets to n1, since persistent-keepalive will prevent connection tracking entry from expiring (to see entries: `n0 conntrack -L`).
281pp sleep 3
282n2 ping -W 1 -c 1 192.168.241.1
283n1 wg set wg0 peer "$pub2" persistent-keepalive 0
284
285# Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
286ip1 -6 addr add fc00::9/96 dev vethc
287ip1 -6 route add default via fc00::1
288ip2 -4 addr add 192.168.99.7/32 dev wg0
289ip2 -6 addr add abab::1111/128 dev wg0
290n1 wg set wg0 fwmark 51820 peer "$pub2" allowed-ips 192.168.99.7,abab::1111
291ip1 -6 route add default dev wg0 table 51820
292ip1 -6 rule add not fwmark 51820 table 51820
293ip1 -6 rule add table main suppress_prefixlength 0
294ip1 -4 route add default dev wg0 table 51820
295ip1 -4 rule add not fwmark 51820 table 51820
296ip1 -4 rule add table main suppress_prefixlength 0
297# Flood the pings instead of sending just one, to trigger routing table reference counting bugs.
298n1 ping -W 1 -c 100 -f 192.168.99.7
299n1 ping -W 1 -c 100 -f abab::1111
300
301# Have ns2 NAT into wg0 packets from ns0, but return an icmp error along the right route.
302n2 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 192.168.241.0/24 -j SNAT --to 192.168.241.2
303n0 iptables -t filter -A INPUT \! -s 10.0.0.0/24 -i vethrs -j DROP # Manual rpfilter just to be explicit.
304n2 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
305ip0 -4 route add 192.168.241.1 via 10.0.0.100
306n2 wg set wg0 peer "$pub1" remove
307[[ $(! n0 ping -W 1 -c 1 192.168.241.1 || false) == *"From 10.0.0.100 icmp_seq=1 Destination Host Unreachable"* ]]
308
309n0 iptables -t nat -F
310n0 iptables -t filter -F
311n2 iptables -t nat -F
312ip0 link del vethrc
313ip0 link del vethrs
314ip1 link del wg0
315ip2 link del wg0
316
317# Test that saddr routing is sticky but not too sticky, changing to this topology:
318# ┌────────────────────────────────────────┐    ┌────────────────────────────────────────┐
319# │             $ns1 namespace             │    │             $ns2 namespace             │
320# │                                        │    │                                        │
321# │  ┌─────┐             ┌─────┐           │    │  ┌─────┐            ┌─────┐            │
322# │  │ wg0 │─────────────│veth1│───────────┼────┼──│veth2│────────────│ wg0 │            │
323# │  ├─────┴──────────┐  ├─────┴──────────┐│    │  ├─────┴──────────┐ ├─────┴──────────┐ │
324# │  │192.168.241.1/24│  │10.0.0.1/24     ││    │  │10.0.0.2/24     │ │192.168.241.2/24│ │
325# │  │fd00::1/24      │  │fd00:aa::1/96   ││    │  │fd00:aa::2/96   │ │fd00::2/24      │ │
326# │  └────────────────┘  └────────────────┘│    │  └────────────────┘ └────────────────┘ │
327# └────────────────────────────────────────┘    └────────────────────────────────────────┘
328
329ip1 link add dev wg0 type wireguard
330ip2 link add dev wg0 type wireguard
331configure_peers
332ip1 link add veth1 type veth peer name veth2
333ip1 link set veth2 netns $netns2
334n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
335n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
336n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad'
337n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad'
338n1 bash -c 'printf 1 > /proc/sys/net/ipv4/conf/veth1/promote_secondaries'
339
340# First we check that we aren't overly sticky and can fall over to new IPs when old ones are removed
341ip1 addr add 10.0.0.1/24 dev veth1
342ip1 addr add fd00:aa::1/96 dev veth1
343ip2 addr add 10.0.0.2/24 dev veth2
344ip2 addr add fd00:aa::2/96 dev veth2
345ip1 link set veth1 up
346ip2 link set veth2 up
347waitiface $netns1 veth1
348waitiface $netns2 veth2
349n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
350n1 ping -W 1 -c 1 192.168.241.2
351ip1 addr add 10.0.0.10/24 dev veth1
352ip1 addr del 10.0.0.1/24 dev veth1
353n1 ping -W 1 -c 1 192.168.241.2
354n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2
355n1 ping -W 1 -c 1 192.168.241.2
356ip1 addr add fd00:aa::10/96 dev veth1
357ip1 addr del fd00:aa::1/96 dev veth1
358n1 ping -W 1 -c 1 192.168.241.2
359
360# Now we show that we can successfully do reply to sender routing
361ip1 link set veth1 down
362ip2 link set veth2 down
363ip1 addr flush dev veth1
364ip2 addr flush dev veth2
365ip1 addr add 10.0.0.1/24 dev veth1
366ip1 addr add 10.0.0.2/24 dev veth1
367ip1 addr add fd00:aa::1/96 dev veth1
368ip1 addr add fd00:aa::2/96 dev veth1
369ip2 addr add 10.0.0.3/24 dev veth2
370ip2 addr add fd00:aa::3/96 dev veth2
371ip1 link set veth1 up
372ip2 link set veth2 up
373waitiface $netns1 veth1
374waitiface $netns2 veth2
375n2 wg set wg0 peer "$pub1" endpoint 10.0.0.1:1
376n2 ping -W 1 -c 1 192.168.241.1
377[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
378n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1
379n2 ping -W 1 -c 1 192.168.241.1
380[[ $(n2 wg show wg0 endpoints) == "$pub1	[fd00:aa::1]:1" ]]
381n2 wg set wg0 peer "$pub1" endpoint 10.0.0.2:1
382n2 ping -W 1 -c 1 192.168.241.1
383[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.2:1" ]]
384n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::2]:1
385n2 ping -W 1 -c 1 192.168.241.1
386[[ $(n2 wg show wg0 endpoints) == "$pub1	[fd00:aa::2]:1" ]]
387
388# What happens if the inbound destination address belongs to a different interface as the default route?
389ip1 link add dummy0 type dummy
390ip1 addr add 10.50.0.1/24 dev dummy0
391ip1 link set dummy0 up
392ip2 route add 10.50.0.0/24 dev veth2
393n2 wg set wg0 peer "$pub1" endpoint 10.50.0.1:1
394n2 ping -W 1 -c 1 192.168.241.1
395[[ $(n2 wg show wg0 endpoints) == "$pub1	10.50.0.1:1" ]]
396
397ip1 link del dummy0
398ip1 addr flush dev veth1
399ip2 addr flush dev veth2
400ip1 route flush dev veth1
401ip2 route flush dev veth2
402
403# Now we see what happens if another interface route takes precedence over an ongoing one
404ip1 link add veth3 type veth peer name veth4
405ip1 link set veth4 netns $netns2
406ip1 addr add 10.0.0.1/24 dev veth1
407ip2 addr add 10.0.0.2/24 dev veth2
408ip1 addr add 10.0.0.3/24 dev veth3
409ip1 link set veth1 up
410ip2 link set veth2 up
411ip1 link set veth3 up
412ip2 link set veth4 up
413waitiface $netns1 veth1
414waitiface $netns2 veth2
415waitiface $netns1 veth3
416waitiface $netns2 veth4
417ip1 route flush dev veth1
418ip1 route flush dev veth3
419ip1 route add 10.0.0.0/24 dev veth1 src 10.0.0.1 metric 2
420n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
421n1 ping -W 1 -c 1 192.168.241.2
422[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.1:1" ]]
423ip1 route add 10.0.0.0/24 dev veth3 src 10.0.0.3 metric 1
424n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter'
425n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth4/rp_filter'
426n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
427n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
428n1 ping -W 1 -c 1 192.168.241.2
429[[ $(n2 wg show wg0 endpoints) == "$pub1	10.0.0.3:1" ]]
430
431ip1 link del veth1
432ip1 link del veth3
433ip1 link del wg0
434ip2 link del wg0
435
436# We test that Netlink/IPC is working properly by doing things that usually cause split responses
437ip0 link add dev wg0 type wireguard
438config=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" )
439for a in {1..255}; do
440	for b in {0..255}; do
441		config+=( "AllowedIPs=$a.$b.0.0/16,$a::$b/128" )
442	done
443done
444n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
445i=0
446for ip in $(n0 wg show wg0 allowed-ips); do
447	((++i))
448done
449((i == 255*256*2+1))
450ip0 link del wg0
451ip0 link add dev wg0 type wireguard
452config=( "[Interface]" "PrivateKey=$(wg genkey)" )
453for a in {1..40}; do
454	config+=( "[Peer]" "PublicKey=$(wg genkey)" )
455	for b in {1..52}; do
456		config+=( "AllowedIPs=$a.$b.0.0/16" )
457	done
458done
459n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
460i=0
461while read -r line; do
462	j=0
463	for ip in $line; do
464		((++j))
465	done
466	((j == 53))
467	((++i))
468done < <(n0 wg show wg0 allowed-ips)
469((i == 40))
470ip0 link del wg0
471ip0 link add wg0 type wireguard
472config=( )
473for i in {1..29}; do
474	config+=( "[Peer]" "PublicKey=$(wg genkey)" )
475done
476config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" )
477n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
478n0 wg showconf wg0 > /dev/null
479ip0 link del wg0
480
481allowedips=( )
482for i in {1..197}; do
483        allowedips+=( abcd::$i )
484done
485saved_ifs="$IFS"
486IFS=,
487allowedips="${allowedips[*]}"
488IFS="$saved_ifs"
489ip0 link add wg0 type wireguard
490n0 wg set wg0 peer "$pub1"
491n0 wg set wg0 peer "$pub2" allowed-ips "$allowedips"
492{
493	read -r pub allowedips
494	[[ $pub == "$pub1" && $allowedips == "(none)" ]]
495	read -r pub allowedips
496	[[ $pub == "$pub2" ]]
497	i=0
498	for _ in $allowedips; do
499		((++i))
500	done
501	((i == 197))
502} < <(n0 wg show wg0 allowed-ips)
503ip0 link del wg0
504
505! n0 wg show doesnotexist || false
506
507ip0 link add wg0 type wireguard
508n0 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk")
509[[ $(n0 wg show wg0 private-key) == "$key1" ]]
510[[ $(n0 wg show wg0 preshared-keys) == "$pub2	$psk" ]]
511n0 wg set wg0 private-key /dev/null peer "$pub2" preshared-key /dev/null
512[[ $(n0 wg show wg0 private-key) == "(none)" ]]
513[[ $(n0 wg show wg0 preshared-keys) == "$pub2	(none)" ]]
514n0 wg set wg0 peer "$pub2"
515n0 wg set wg0 private-key <(echo "$key2")
516[[ $(n0 wg show wg0 public-key) == "$pub2" ]]
517[[ -z $(n0 wg show wg0 peers) ]]
518n0 wg set wg0 peer "$pub2"
519[[ -z $(n0 wg show wg0 peers) ]]
520n0 wg set wg0 private-key <(echo "$key1")
521n0 wg set wg0 peer "$pub2"
522[[ $(n0 wg show wg0 peers) == "$pub2" ]]
523n0 wg set wg0 private-key <(echo "/${key1:1}")
524[[ $(n0 wg show wg0 private-key) == "+${key1:1}" ]]
525n0 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
526n0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0
527n0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75
528n0 wg set wg0 peer "$pub2" allowed-ips ::/0
529n0 wg set wg0 peer "$pub2" remove
530for low_order_point in AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38=; do
531	n0 wg set wg0 peer "$low_order_point" persistent-keepalive 1 endpoint 127.0.0.1:1111
532done
533[[ -n $(n0 wg show wg0 peers) ]]
534exec 4< <(n0 ncat -l -u -p 1111)
535ncat_pid=$!
536waitncatudp $netns0 $ncat_pid
537ip0 link set wg0 up
538! read -r -n 1 -t 2 <&4 || false
539kill $ncat_pid
540ip0 link del wg0
541
542declare -A objects
543while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do
544	[[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ [0-9]+)\ .*(created|destroyed).* ]] || continue
545	objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}"
546done < /dev/kmsg
547alldeleted=1
548for object in "${!objects[@]}"; do
549	if [[ ${objects["$object"]} != *createddestroyed ]]; then
550		echo "Error: $object: merely ${objects["$object"]}" >&3
551		alldeleted=0
552	fi
553done
554[[ $alldeleted -eq 1 ]]
555pretty "" "Objects that were created were also destroyed."
556