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:${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 sk_bound_dev_if works 333n1 ping -I wg0 -c 1 -W 1 192.168.241.2 334# What about when the mark changes and the packet must be rerouted? 335n1 iptables -t mangle -I OUTPUT -j MARK --set-xmark 1 336n1 ping -c 1 -W 1 192.168.241.2 # First the boring case 337n1 ping -I wg0 -c 1 -W 1 192.168.241.2 # Then the sk_bound_dev_if case 338n1 iptables -t mangle -D OUTPUT -j MARK --set-xmark 1 339 340# Test that onion routing works, even when it loops 341n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5 342ip1 addr add 192.168.242.1/24 dev wg0 343ip2 link add wg1 type wireguard 344ip2 addr add 192.168.242.2/24 dev wg1 345n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32 346ip2 link set wg1 up 347n1 ping -W 1 -c 1 192.168.242.2 348ip2 link del wg1 349n1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5 350! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel 351n1 wg set wg0 peer "$pub3" remove 352ip1 addr del 192.168.242.1/24 dev wg0 353 354# Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs. 355ip1 -6 addr add fc00::9/96 dev vethc 356ip1 -6 route add default via fc00::1 357ip2 -4 addr add 192.168.99.7/32 dev wg0 358ip2 -6 addr add abab::1111/128 dev wg0 359n1 wg set wg0 fwmark 51820 peer "$pub2" allowed-ips 192.168.99.7,abab::1111 360ip1 -6 route add default dev wg0 table 51820 361ip1 -6 rule add not fwmark 51820 table 51820 362ip1 -6 rule add table main suppress_prefixlength 0 363ip1 -4 route add default dev wg0 table 51820 364ip1 -4 rule add not fwmark 51820 table 51820 365ip1 -4 rule add table main suppress_prefixlength 0 366n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/vethc/rp_filter' 367# Flood the pings instead of sending just one, to trigger routing table reference counting bugs. 368n1 ping -W 1 -c 100 -f 192.168.99.7 369n1 ping -W 1 -c 100 -f abab::1111 370 371# Have ns2 NAT into wg0 packets from ns0, but return an icmp error along the right route. 372n2 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 192.168.241.0/24 -j SNAT --to 192.168.241.2 373n0 iptables -t filter -A INPUT \! -s 10.0.0.0/24 -i vethrs -j DROP # Manual rpfilter just to be explicit. 374n2 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward' 375ip0 -4 route add 192.168.241.1 via 10.0.0.100 376n2 wg set wg0 peer "$pub1" remove 377[[ $(! n0 ping -W 1 -c 1 192.168.241.1 || false) == *"From 10.0.0.100 icmp_seq=1 Destination Host Unreachable"* ]] 378 379n0 iptables -t nat -F 380n0 iptables -t filter -F 381n2 iptables -t nat -F 382ip0 link del vethrc 383ip0 link del vethrs 384ip1 link del wg0 385ip2 link del wg0 386 387# Test that saddr routing is sticky but not too sticky, changing to this topology: 388# ┌────────────────────────────────────────┐ ┌────────────────────────────────────────┐ 389# │ $ns1 namespace │ │ $ns2 namespace │ 390# │ │ │ │ 391# │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ ┌─────┐ │ 392# │ │ wg0 │─────────────│veth1│───────────┼────┼──│veth2│────────────│ wg0 │ │ 393# │ ├─────┴──────────┐ ├─────┴──────────┐│ │ ├─────┴──────────┐ ├─────┴──────────┐ │ 394# │ │192.168.241.1/24│ │10.0.0.1/24 ││ │ │10.0.0.2/24 │ │192.168.241.2/24│ │ 395# │ │fd00::1/24 │ │fd00:aa::1/96 ││ │ │fd00:aa::2/96 │ │fd00::2/24 │ │ 396# │ └────────────────┘ └────────────────┘│ │ └────────────────┘ └────────────────┘ │ 397# └────────────────────────────────────────┘ └────────────────────────────────────────┘ 398 399ip1 link add dev wg0 type wireguard 400ip2 link add dev wg0 type wireguard 401configure_peers 402ip1 link add veth1 type veth peer name veth2 403ip1 link set veth2 netns $netns2 404n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad' 405n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad' 406n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad' 407n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad' 408n1 bash -c 'printf 1 > /proc/sys/net/ipv4/conf/veth1/promote_secondaries' 409 410# First we check that we aren't overly sticky and can fall over to new IPs when old ones are removed 411ip1 addr add 10.0.0.1/24 dev veth1 412ip1 addr add fd00:aa::1/96 dev veth1 413ip2 addr add 10.0.0.2/24 dev veth2 414ip2 addr add fd00:aa::2/96 dev veth2 415ip1 link set veth1 up 416ip2 link set veth2 up 417waitiface $netns1 veth1 418waitiface $netns2 veth2 419n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2 420n1 ping -W 1 -c 1 192.168.241.2 421ip1 addr add 10.0.0.10/24 dev veth1 422ip1 addr del 10.0.0.1/24 dev veth1 423n1 ping -W 1 -c 1 192.168.241.2 424n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2 425n1 ping -W 1 -c 1 192.168.241.2 426ip1 addr add fd00:aa::10/96 dev veth1 427ip1 addr del fd00:aa::1/96 dev veth1 428n1 ping -W 1 -c 1 192.168.241.2 429 430# Now we show that we can successfully do reply to sender routing 431ip1 link set veth1 down 432ip2 link set veth2 down 433ip1 addr flush dev veth1 434ip2 addr flush dev veth2 435ip1 addr add 10.0.0.1/24 dev veth1 436ip1 addr add 10.0.0.2/24 dev veth1 437ip1 addr add fd00:aa::1/96 dev veth1 438ip1 addr add fd00:aa::2/96 dev veth1 439ip2 addr add 10.0.0.3/24 dev veth2 440ip2 addr add fd00:aa::3/96 dev veth2 441ip1 link set veth1 up 442ip2 link set veth2 up 443waitiface $netns1 veth1 444waitiface $netns2 veth2 445n2 wg set wg0 peer "$pub1" endpoint 10.0.0.1:1 446n2 ping -W 1 -c 1 192.168.241.1 447[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]] 448n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1 449n2 ping -W 1 -c 1 192.168.241.1 450[[ $(n2 wg show wg0 endpoints) == "$pub1 [fd00:aa::1]:1" ]] 451n2 wg set wg0 peer "$pub1" endpoint 10.0.0.2:1 452n2 ping -W 1 -c 1 192.168.241.1 453[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.2:1" ]] 454n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::2]:1 455n2 ping -W 1 -c 1 192.168.241.1 456[[ $(n2 wg show wg0 endpoints) == "$pub1 [fd00:aa::2]:1" ]] 457 458# What happens if the inbound destination address belongs to a different interface as the default route? 459ip1 link add dummy0 type dummy 460ip1 addr add 10.50.0.1/24 dev dummy0 461ip1 link set dummy0 up 462ip2 route add 10.50.0.0/24 dev veth2 463n2 wg set wg0 peer "$pub1" endpoint 10.50.0.1:1 464n2 ping -W 1 -c 1 192.168.241.1 465[[ $(n2 wg show wg0 endpoints) == "$pub1 10.50.0.1:1" ]] 466 467ip1 link del dummy0 468ip1 addr flush dev veth1 469ip2 addr flush dev veth2 470ip1 route flush dev veth1 471ip2 route flush dev veth2 472 473# Now we see what happens if another interface route takes precedence over an ongoing one 474ip1 link add veth3 type veth peer name veth4 475ip1 link set veth4 netns $netns2 476ip1 addr add 10.0.0.1/24 dev veth1 477ip2 addr add 10.0.0.2/24 dev veth2 478ip1 addr add 10.0.0.3/24 dev veth3 479ip1 link set veth1 up 480ip2 link set veth2 up 481ip1 link set veth3 up 482ip2 link set veth4 up 483waitiface $netns1 veth1 484waitiface $netns2 veth2 485waitiface $netns1 veth3 486waitiface $netns2 veth4 487ip1 route flush dev veth1 488ip1 route flush dev veth3 489ip1 route add 10.0.0.0/24 dev veth1 src 10.0.0.1 metric 2 490n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2 491n1 ping -W 1 -c 1 192.168.241.2 492[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]] 493ip1 route add 10.0.0.0/24 dev veth3 src 10.0.0.3 metric 1 494n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter' 495n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth4/rp_filter' 496n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter' 497n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter' 498n1 ping -W 1 -c 1 192.168.241.2 499[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.3:1" ]] 500 501ip1 link del veth1 502ip1 link del veth3 503ip1 link del wg0 504ip2 link del wg0 505 506# We test that Netlink/IPC is working properly by doing things that usually cause split responses 507ip0 link add dev wg0 type wireguard 508config=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" ) 509for a in {1..255}; do 510 for b in {0..255}; do 511 config+=( "AllowedIPs=$a.$b.0.0/16,$a::$b/128" ) 512 done 513done 514n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 515i=0 516for ip in $(n0 wg show wg0 allowed-ips); do 517 ((++i)) 518done 519((i == 255*256*2+1)) 520ip0 link del wg0 521ip0 link add dev wg0 type wireguard 522config=( "[Interface]" "PrivateKey=$(wg genkey)" ) 523for a in {1..40}; do 524 config+=( "[Peer]" "PublicKey=$(wg genkey)" ) 525 for b in {1..52}; do 526 config+=( "AllowedIPs=$a.$b.0.0/16" ) 527 done 528done 529n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 530i=0 531while read -r line; do 532 j=0 533 for ip in $line; do 534 ((++j)) 535 done 536 ((j == 53)) 537 ((++i)) 538done < <(n0 wg show wg0 allowed-ips) 539((i == 40)) 540ip0 link del wg0 541ip0 link add wg0 type wireguard 542config=( ) 543for i in {1..29}; do 544 config+=( "[Peer]" "PublicKey=$(wg genkey)" ) 545done 546config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" ) 547n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 548n0 wg showconf wg0 > /dev/null 549ip0 link del wg0 550 551allowedips=( ) 552for i in {1..197}; do 553 allowedips+=( abcd::$i ) 554done 555saved_ifs="$IFS" 556IFS=, 557allowedips="${allowedips[*]}" 558IFS="$saved_ifs" 559ip0 link add wg0 type wireguard 560n0 wg set wg0 peer "$pub1" 561n0 wg set wg0 peer "$pub2" allowed-ips "$allowedips" 562{ 563 read -r pub allowedips 564 [[ $pub == "$pub1" && $allowedips == "(none)" ]] 565 read -r pub allowedips 566 [[ $pub == "$pub2" ]] 567 i=0 568 for _ in $allowedips; do 569 ((++i)) 570 done 571 ((i == 197)) 572} < <(n0 wg show wg0 allowed-ips) 573ip0 link del wg0 574 575! n0 wg show doesnotexist || false 576 577ip0 link add wg0 type wireguard 578n0 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk") 579[[ $(n0 wg show wg0 private-key) == "$key1" ]] 580[[ $(n0 wg show wg0 preshared-keys) == "$pub2 $psk" ]] 581n0 wg set wg0 private-key /dev/null peer "$pub2" preshared-key /dev/null 582[[ $(n0 wg show wg0 private-key) == "(none)" ]] 583[[ $(n0 wg show wg0 preshared-keys) == "$pub2 (none)" ]] 584n0 wg set wg0 peer "$pub2" 585n0 wg set wg0 private-key <(echo "$key2") 586[[ $(n0 wg show wg0 public-key) == "$pub2" ]] 587[[ -z $(n0 wg show wg0 peers) ]] 588n0 wg set wg0 peer "$pub2" 589[[ -z $(n0 wg show wg0 peers) ]] 590n0 wg set wg0 private-key <(echo "$key1") 591n0 wg set wg0 peer "$pub2" 592[[ $(n0 wg show wg0 peers) == "$pub2" ]] 593n0 wg set wg0 private-key <(echo "/${key1:1}") 594[[ $(n0 wg show wg0 private-key) == "+${key1:1}" ]] 595n0 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 596n0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0 597n0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75 598n0 wg set wg0 peer "$pub2" allowed-ips ::/0 599n0 wg set wg0 peer "$pub2" remove 600for low_order_point in AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38=; do 601 n0 wg set wg0 peer "$low_order_point" persistent-keepalive 1 endpoint 127.0.0.1:1111 602done 603[[ -n $(n0 wg show wg0 peers) ]] 604exec 4< <(n0 ncat -l -u -p 1111) 605ncat_pid=$! 606waitncatudp $netns0 $ncat_pid 607ip0 link set wg0 up 608! read -r -n 1 -t 2 <&4 || false 609kill $ncat_pid 610ip0 link del wg0 611 612# Ensure there aren't circular reference loops 613ip1 link add wg1 type wireguard 614ip2 link add wg2 type wireguard 615ip1 link set wg1 netns $netns2 616ip2 link set wg2 netns $netns1 617pp ip netns delete $netns1 618pp ip netns delete $netns2 619pp ip netns add $netns1 620pp ip netns add $netns2 621 622sleep 2 # Wait for cleanup and grace periods 623declare -A objects 624while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do 625 [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ ?[0-9]*)\ .*(created|destroyed).* ]] || continue 626 objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}" 627done < /dev/kmsg 628alldeleted=1 629for object in "${!objects[@]}"; do 630 if [[ ${objects["$object"]} != *createddestroyed ]]; then 631 echo "Error: $object: merely ${objects["$object"]}" >&3 632 alldeleted=0 633 fi 634done 635[[ $alldeleted -eq 1 ]] 636pretty "" "Objects that were created were also destroyed." 637