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