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