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