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