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 onion routing works, even when it loops 320n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5 321ip1 addr add 192.168.242.1/24 dev wg0 322ip2 link add wg1 type wireguard 323ip2 addr add 192.168.242.2/24 dev wg1 324n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32 325ip2 link set wg1 up 326n1 ping -W 1 -c 1 192.168.242.2 327ip2 link del wg1 328n1 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 330n1 wg set wg0 peer "$pub3" remove 331ip1 addr del 192.168.242.1/24 dev wg0 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. 334ip1 -6 addr add fc00::9/96 dev vethc 335ip1 -6 route add default via fc00::1 336ip2 -4 addr add 192.168.99.7/32 dev wg0 337ip2 -6 addr add abab::1111/128 dev wg0 338n1 wg set wg0 fwmark 51820 peer "$pub2" allowed-ips 192.168.99.7,abab::1111 339ip1 -6 route add default dev wg0 table 51820 340ip1 -6 rule add not fwmark 51820 table 51820 341ip1 -6 rule add table main suppress_prefixlength 0 342ip1 -4 route add default dev wg0 table 51820 343ip1 -4 rule add not fwmark 51820 table 51820 344ip1 -4 rule add table main suppress_prefixlength 0 345# Flood the pings instead of sending just one, to trigger routing table reference counting bugs. 346n1 ping -W 1 -c 100 -f 192.168.99.7 347n1 ping -W 1 -c 100 -f abab::1111 348 349# Have ns2 NAT into wg0 packets from ns0, but return an icmp error along the right route. 350n2 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 192.168.241.0/24 -j SNAT --to 192.168.241.2 351n0 iptables -t filter -A INPUT \! -s 10.0.0.0/24 -i vethrs -j DROP # Manual rpfilter just to be explicit. 352n2 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward' 353ip0 -4 route add 192.168.241.1 via 10.0.0.100 354n2 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 357n0 iptables -t nat -F 358n0 iptables -t filter -F 359n2 iptables -t nat -F 360ip0 link del vethrc 361ip0 link del vethrs 362ip1 link del wg0 363ip2 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 377ip1 link add dev wg0 type wireguard 378ip2 link add dev wg0 type wireguard 379configure_peers 380ip1 link add veth1 type veth peer name veth2 381ip1 link set veth2 netns $netns2 382n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad' 383n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad' 384n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad' 385n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad' 386n1 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 389ip1 addr add 10.0.0.1/24 dev veth1 390ip1 addr add fd00:aa::1/96 dev veth1 391ip2 addr add 10.0.0.2/24 dev veth2 392ip2 addr add fd00:aa::2/96 dev veth2 393ip1 link set veth1 up 394ip2 link set veth2 up 395waitiface $netns1 veth1 396waitiface $netns2 veth2 397n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2 398n1 ping -W 1 -c 1 192.168.241.2 399ip1 addr add 10.0.0.10/24 dev veth1 400ip1 addr del 10.0.0.1/24 dev veth1 401n1 ping -W 1 -c 1 192.168.241.2 402n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2 403n1 ping -W 1 -c 1 192.168.241.2 404ip1 addr add fd00:aa::10/96 dev veth1 405ip1 addr del fd00:aa::1/96 dev veth1 406n1 ping -W 1 -c 1 192.168.241.2 407 408# Now we show that we can successfully do reply to sender routing 409ip1 link set veth1 down 410ip2 link set veth2 down 411ip1 addr flush dev veth1 412ip2 addr flush dev veth2 413ip1 addr add 10.0.0.1/24 dev veth1 414ip1 addr add 10.0.0.2/24 dev veth1 415ip1 addr add fd00:aa::1/96 dev veth1 416ip1 addr add fd00:aa::2/96 dev veth1 417ip2 addr add 10.0.0.3/24 dev veth2 418ip2 addr add fd00:aa::3/96 dev veth2 419ip1 link set veth1 up 420ip2 link set veth2 up 421waitiface $netns1 veth1 422waitiface $netns2 veth2 423n2 wg set wg0 peer "$pub1" endpoint 10.0.0.1:1 424n2 ping -W 1 -c 1 192.168.241.1 425[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]] 426n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1 427n2 ping -W 1 -c 1 192.168.241.1 428[[ $(n2 wg show wg0 endpoints) == "$pub1 [fd00:aa::1]:1" ]] 429n2 wg set wg0 peer "$pub1" endpoint 10.0.0.2:1 430n2 ping -W 1 -c 1 192.168.241.1 431[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.2:1" ]] 432n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::2]:1 433n2 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? 437ip1 link add dummy0 type dummy 438ip1 addr add 10.50.0.1/24 dev dummy0 439ip1 link set dummy0 up 440ip2 route add 10.50.0.0/24 dev veth2 441n2 wg set wg0 peer "$pub1" endpoint 10.50.0.1:1 442n2 ping -W 1 -c 1 192.168.241.1 443[[ $(n2 wg show wg0 endpoints) == "$pub1 10.50.0.1:1" ]] 444 445ip1 link del dummy0 446ip1 addr flush dev veth1 447ip2 addr flush dev veth2 448ip1 route flush dev veth1 449ip2 route flush dev veth2 450 451# Now we see what happens if another interface route takes precedence over an ongoing one 452ip1 link add veth3 type veth peer name veth4 453ip1 link set veth4 netns $netns2 454ip1 addr add 10.0.0.1/24 dev veth1 455ip2 addr add 10.0.0.2/24 dev veth2 456ip1 addr add 10.0.0.3/24 dev veth3 457ip1 link set veth1 up 458ip2 link set veth2 up 459ip1 link set veth3 up 460ip2 link set veth4 up 461waitiface $netns1 veth1 462waitiface $netns2 veth2 463waitiface $netns1 veth3 464waitiface $netns2 veth4 465ip1 route flush dev veth1 466ip1 route flush dev veth3 467ip1 route add 10.0.0.0/24 dev veth1 src 10.0.0.1 metric 2 468n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2 469n1 ping -W 1 -c 1 192.168.241.2 470[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]] 471ip1 route add 10.0.0.0/24 dev veth3 src 10.0.0.3 metric 1 472n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter' 473n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth4/rp_filter' 474n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter' 475n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter' 476n1 ping -W 1 -c 1 192.168.241.2 477[[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.3:1" ]] 478 479ip1 link del veth1 480ip1 link del veth3 481ip1 link del wg0 482ip2 link del wg0 483 484# We test that Netlink/IPC is working properly by doing things that usually cause split responses 485ip0 link add dev wg0 type wireguard 486config=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" ) 487for 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 491done 492n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 493i=0 494for ip in $(n0 wg show wg0 allowed-ips); do 495 ((++i)) 496done 497((i == 255*256*2+1)) 498ip0 link del wg0 499ip0 link add dev wg0 type wireguard 500config=( "[Interface]" "PrivateKey=$(wg genkey)" ) 501for 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 506done 507n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 508i=0 509while read -r line; do 510 j=0 511 for ip in $line; do 512 ((++j)) 513 done 514 ((j == 53)) 515 ((++i)) 516done < <(n0 wg show wg0 allowed-ips) 517((i == 40)) 518ip0 link del wg0 519ip0 link add wg0 type wireguard 520config=( ) 521for i in {1..29}; do 522 config+=( "[Peer]" "PublicKey=$(wg genkey)" ) 523done 524config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" ) 525n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 526n0 wg showconf wg0 > /dev/null 527ip0 link del wg0 528 529allowedips=( ) 530for i in {1..197}; do 531 allowedips+=( abcd::$i ) 532done 533saved_ifs="$IFS" 534IFS=, 535allowedips="${allowedips[*]}" 536IFS="$saved_ifs" 537ip0 link add wg0 type wireguard 538n0 wg set wg0 peer "$pub1" 539n0 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) 551ip0 link del wg0 552 553! n0 wg show doesnotexist || false 554 555ip0 link add wg0 type wireguard 556n0 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" ]] 559n0 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)" ]] 562n0 wg set wg0 peer "$pub2" 563n0 wg set wg0 private-key <(echo "$key2") 564[[ $(n0 wg show wg0 public-key) == "$pub2" ]] 565[[ -z $(n0 wg show wg0 peers) ]] 566n0 wg set wg0 peer "$pub2" 567[[ -z $(n0 wg show wg0 peers) ]] 568n0 wg set wg0 private-key <(echo "$key1") 569n0 wg set wg0 peer "$pub2" 570[[ $(n0 wg show wg0 peers) == "$pub2" ]] 571n0 wg set wg0 private-key <(echo "/${key1:1}") 572[[ $(n0 wg show wg0 private-key) == "+${key1:1}" ]] 573n0 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 574n0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0 575n0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75 576n0 wg set wg0 peer "$pub2" allowed-ips ::/0 577n0 wg set wg0 peer "$pub2" remove 578for 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 580done 581[[ -n $(n0 wg show wg0 peers) ]] 582exec 4< <(n0 ncat -l -u -p 1111) 583ncat_pid=$! 584waitncatudp $netns0 $ncat_pid 585ip0 link set wg0 up 586! read -r -n 1 -t 2 <&4 || false 587kill $ncat_pid 588ip0 link del wg0 589 590# Ensure there aren't circular reference loops 591ip1 link add wg1 type wireguard 592ip2 link add wg2 type wireguard 593ip1 link set wg1 netns $netns2 594ip2 link set wg2 netns $netns1 595pp ip netns delete $netns1 596pp ip netns delete $netns2 597pp ip netns add $netns1 598pp ip netns add $netns2 599 600sleep 2 # Wait for cleanup and grace periods 601declare -A objects 602while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do 603 [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ ?[0-9]*)\ .*(created|destroyed).* ]] || continue 604 objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}" 605done < /dev/kmsg 606alldeleted=1 607for object in "${!objects[@]}"; do 608 if [[ ${objects["$object"]} != *createddestroyed ]]; then 609 echo "Error: $object: merely ${objects["$object"]}" >&3 610 alldeleted=0 611 fi 612done 613[[ $alldeleted -eq 1 ]] 614pretty "" "Objects that were created were also destroyed." 615