github.com/liloew/wireguard-go@v0.0.0-20220224014633-9cd745e6f114/tests/netns.sh (about) 1 #!/bin/bash 2 3 # Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 5 # This script tests the below topology: 6 # 7 # ┌─────────────────────┐ ┌──────────────────────────────────┐ ┌─────────────────────┐ 8 # │ $ns1 namespace │ │ $ns0 namespace │ │ $ns2 namespace │ 9 # │ │ │ │ │ │ 10 # │┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐│ 11 # ││ wg1 │───────────┼───┼────────────│ lo │────────────┼───┼───────────│ wg2 ││ 12 # │├────────┴──────────┐│ │ ┌───────┴────────┴────────┐ │ │┌──────────┴────────┤│ 13 # ││192.168.241.1/24 ││ │ │(ns1) (ns2) │ │ ││192.168.241.2/24 ││ 14 # ││fd00::1/24 ││ │ │127.0.0.1:1 127.0.0.1:2│ │ ││fd00::2/24 ││ 15 # │└───────────────────┘│ │ │[::]:1 [::]:2 │ │ │└───────────────────┘│ 16 # └─────────────────────┘ │ └─────────────────────────┘ │ └─────────────────────┘ 17 # └──────────────────────────────────┘ 18 # 19 # After the topology is prepared we run a series of TCP/UDP iperf3 tests between the 20 # wireguard peers in $ns1 and $ns2. Note that $ns0 is the endpoint for the wg1 21 # interfaces in $ns1 and $ns2. See https://www.wireguard.com/netns/ for further 22 # details on how this is accomplished. 23 24 # This code is ported to the WireGuard-Go directly from the kernel project. 25 # 26 # Please ensure that you have installed the newest version of the WireGuard 27 # tools from the WireGuard project and before running these tests as: 28 # 29 # ./netns.sh <path to wireguard-go> 30 31 set -e 32 33 exec 3>&1 34 export WG_HIDE_KEYS=never 35 netns0="wg-test-$$-0" 36 netns1="wg-test-$$-1" 37 netns2="wg-test-$$-2" 38 program=$1 39 export LOG_LEVEL="verbose" 40 41 pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; } 42 pp() { pretty "" "$*"; "$@"; } 43 maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; } 44 n0() { pretty 0 "$*"; maybe_exec ip netns exec $netns0 "$@"; } 45 n1() { pretty 1 "$*"; maybe_exec ip netns exec $netns1 "$@"; } 46 n2() { pretty 2 "$*"; maybe_exec ip netns exec $netns2 "$@"; } 47 ip0() { pretty 0 "ip $*"; ip -n $netns0 "$@"; } 48 ip1() { pretty 1 "ip $*"; ip -n $netns1 "$@"; } 49 ip2() { pretty 2 "ip $*"; ip -n $netns2 "$@"; } 50 sleep() { read -t "$1" -N 0 || true; } 51 waitiperf() { pretty "${1//*-}" "wait for iperf:5201"; while [[ $(ss -N "$1" -tlp 'sport = 5201') != *iperf3* ]]; do sleep 0.1; done; } 52 waitncatudp() { pretty "${1//*-}" "wait for udp:1111"; while [[ $(ss -N "$1" -ulp 'sport = 1111') != *ncat* ]]; do sleep 0.1; done; } 53 waitiface() { pretty "${1//*-}" "wait for $2 to come up"; ip netns exec "$1" bash -c "while [[ \$(< \"/sys/class/net/$2/operstate\") != up ]]; do read -t .1 -N 0 || true; done;"; } 54 55 cleanup() { 56 set +e 57 exec 2>/dev/null 58 printf "$orig_message_cost" > /proc/sys/net/core/message_cost 59 ip0 link del dev wg1 60 ip1 link del dev wg1 61 ip2 link del dev wg1 62 local to_kill="$(ip netns pids $netns0) $(ip netns pids $netns1) $(ip netns pids $netns2)" 63 [[ -n $to_kill ]] && kill $to_kill 64 pp ip netns del $netns1 65 pp ip netns del $netns2 66 pp ip netns del $netns0 67 exit 68 } 69 70 orig_message_cost="$(< /proc/sys/net/core/message_cost)" 71 trap cleanup EXIT 72 printf 0 > /proc/sys/net/core/message_cost 73 74 ip netns del $netns0 2>/dev/null || true 75 ip netns del $netns1 2>/dev/null || true 76 ip netns del $netns2 2>/dev/null || true 77 pp ip netns add $netns0 78 pp ip netns add $netns1 79 pp ip netns add $netns2 80 ip0 link set up dev lo 81 82 # ip0 link add dev wg1 type wireguard 83 n0 $program wg1 84 ip0 link set wg1 netns $netns1 85 86 # ip0 link add dev wg1 type wireguard 87 n0 $program wg2 88 ip0 link set wg2 netns $netns2 89 90 key1="$(pp wg genkey)" 91 key2="$(pp wg genkey)" 92 pub1="$(pp wg pubkey <<<"$key1")" 93 pub2="$(pp wg pubkey <<<"$key2")" 94 psk="$(pp wg genpsk)" 95 [[ -n $key1 && -n $key2 && -n $psk ]] 96 97 configure_peers() { 98 99 ip1 addr add 192.168.241.1/24 dev wg1 100 ip1 addr add fd00::1/24 dev wg1 101 102 ip2 addr add 192.168.241.2/24 dev wg2 103 ip2 addr add fd00::2/24 dev wg2 104 105 n0 wg set wg1 \ 106 private-key <(echo "$key1") \ 107 listen-port 10000 \ 108 peer "$pub2" \ 109 preshared-key <(echo "$psk") \ 110 allowed-ips 192.168.241.2/32,fd00::2/128 111 n0 wg set wg2 \ 112 private-key <(echo "$key2") \ 113 listen-port 20000 \ 114 peer "$pub1" \ 115 preshared-key <(echo "$psk") \ 116 allowed-ips 192.168.241.1/32,fd00::1/128 117 118 n0 wg showconf wg1 119 n0 wg showconf wg2 120 121 ip1 link set up dev wg1 122 ip2 link set up dev wg2 123 sleep 1 124 } 125 configure_peers 126 127 tests() { 128 # Ping over IPv4 129 n2 ping -c 10 -f -W 1 192.168.241.1 130 n1 ping -c 10 -f -W 1 192.168.241.2 131 132 # Ping over IPv6 133 n2 ping6 -c 10 -f -W 1 fd00::1 134 n1 ping6 -c 10 -f -W 1 fd00::2 135 136 # TCP over IPv4 137 n2 iperf3 -s -1 -B 192.168.241.2 & 138 waitiperf $netns2 139 n1 iperf3 -Z -n 1G -c 192.168.241.2 140 141 # TCP over IPv6 142 n1 iperf3 -s -1 -B fd00::1 & 143 waitiperf $netns1 144 n2 iperf3 -Z -n 1G -c fd00::1 145 146 # UDP over IPv4 147 n1 iperf3 -s -1 -B 192.168.241.1 & 148 waitiperf $netns1 149 n2 iperf3 -Z -n 1G -b 0 -u -c 192.168.241.1 150 151 # UDP over IPv6 152 n2 iperf3 -s -1 -B fd00::2 & 153 waitiperf $netns2 154 n1 iperf3 -Z -n 1G -b 0 -u -c fd00::2 155 } 156 157 [[ $(ip1 link show dev wg1) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}" 158 big_mtu=$(( 34816 - 1500 + $orig_mtu )) 159 160 # Test using IPv4 as outer transport 161 n0 wg set wg1 peer "$pub2" endpoint 127.0.0.1:20000 162 n0 wg set wg2 peer "$pub1" endpoint 127.0.0.1:10000 163 164 # Before calling tests, we first make sure that the stats counters are working 165 n2 ping -c 10 -f -W 1 192.168.241.1 166 { read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip2 -stats link show dev wg2) 167 ip2 -stats link show dev wg2 168 n0 wg show 169 [[ $rx_bytes -ge 840 && $tx_bytes -ge 880 && $rx_bytes -lt 2500 && $rx_bytes -lt 2500 ]] 170 echo "counters working" 171 tests 172 ip1 link set wg1 mtu $big_mtu 173 ip2 link set wg2 mtu $big_mtu 174 tests 175 176 ip1 link set wg1 mtu $orig_mtu 177 ip2 link set wg2 mtu $orig_mtu 178 179 # Test using IPv6 as outer transport 180 n0 wg set wg1 peer "$pub2" endpoint [::1]:20000 181 n0 wg set wg2 peer "$pub1" endpoint [::1]:10000 182 tests 183 ip1 link set wg1 mtu $big_mtu 184 ip2 link set wg2 mtu $big_mtu 185 tests 186 187 ip1 link set wg1 mtu $orig_mtu 188 ip2 link set wg2 mtu $orig_mtu 189 190 # Test using IPv4 that roaming works 191 ip0 -4 addr del 127.0.0.1/8 dev lo 192 ip0 -4 addr add 127.212.121.99/8 dev lo 193 n0 wg set wg1 listen-port 9999 194 n0 wg set wg1 peer "$pub2" endpoint 127.0.0.1:20000 195 n1 ping6 -W 1 -c 1 fd00::2 196 [[ $(n2 wg show wg2 endpoints) == "$pub1 127.212.121.99:9999" ]] 197 198 # Test using IPv6 that roaming works 199 n1 wg set wg1 listen-port 9998 200 n1 wg set wg1 peer "$pub2" endpoint [::1]:20000 201 n1 ping -W 1 -c 1 192.168.241.2 202 [[ $(n2 wg show wg2 endpoints) == "$pub1 [::1]:9998" ]] 203 204 # Test that crypto-RP filter works 205 n1 wg set wg1 peer "$pub2" allowed-ips 192.168.241.0/24 206 exec 4< <(n1 ncat -l -u -p 1111) 207 nmap_pid=$! 208 waitncatudp $netns1 209 n2 ncat -u 192.168.241.1 1111 <<<"X" 210 read -r -N 1 -t 1 out <&4 && [[ $out == "X" ]] 211 kill $nmap_pid 212 more_specific_key="$(pp wg genkey | pp wg pubkey)" 213 n0 wg set wg1 peer "$more_specific_key" allowed-ips 192.168.241.2/32 214 n0 wg set wg2 listen-port 9997 215 exec 4< <(n1 ncat -l -u -p 1111) 216 nmap_pid=$! 217 waitncatudp $netns1 218 n2 ncat -u 192.168.241.1 1111 <<<"X" 219 ! read -r -N 1 -t 1 out <&4 220 kill $nmap_pid 221 n0 wg set wg1 peer "$more_specific_key" remove 222 [[ $(n1 wg show wg1 endpoints) == "$pub2 [::1]:9997" ]] 223 224 ip1 link del wg1 225 ip2 link del wg2 226 227 # Test using NAT. We now change the topology to this: 228 # ┌────────────────────────────────────────┐ ┌────────────────────────────────────────────────┐ ┌────────────────────────────────────────┐ 229 # │ $ns1 namespace │ │ $ns0 namespace │ │ $ns2 namespace │ 230 # │ │ │ │ │ │ 231 # │ ┌─────┐ ┌─────┐ │ │ ┌──────┐ ┌──────┐ │ │ ┌─────┐ ┌─────┐ │ 232 # │ │ wg1 │─────────────│vethc│───────────┼────┼────│vethrc│ │vethrs│──────────────┼─────┼──│veths│────────────│ wg2 │ │ 233 # │ ├─────┴──────────┐ ├─────┴──────────┐│ │ ├──────┴─────────┐ ├──────┴────────────┐ │ │ ├─────┴──────────┐ ├─────┴──────────┐ │ 234 # │ │192.168.241.1/24│ │192.168.1.100/24││ │ │192.168.1.100/24│ │10.0.0.1/24 │ │ │ │10.0.0.100/24 │ │192.168.241.2/24│ │ 235 # │ │fd00::1/24 │ │ ││ │ │ │ │SNAT:192.168.1.0/24│ │ │ │ │ │fd00::2/24 │ │ 236 # │ └────────────────┘ └────────────────┘│ │ └────────────────┘ └───────────────────┘ │ │ └────────────────┘ └────────────────┘ │ 237 # └────────────────────────────────────────┘ └────────────────────────────────────────────────┘ └────────────────────────────────────────┘ 238 239 # ip1 link add dev wg1 type wireguard 240 # ip2 link add dev wg1 type wireguard 241 242 n1 $program wg1 243 n2 $program wg2 244 245 configure_peers 246 247 ip0 link add vethrc type veth peer name vethc 248 ip0 link add vethrs type veth peer name veths 249 ip0 link set vethc netns $netns1 250 ip0 link set veths netns $netns2 251 ip0 link set vethrc up 252 ip0 link set vethrs up 253 ip0 addr add 192.168.1.1/24 dev vethrc 254 ip0 addr add 10.0.0.1/24 dev vethrs 255 ip1 addr add 192.168.1.100/24 dev vethc 256 ip1 link set vethc up 257 ip1 route add default via 192.168.1.1 258 ip2 addr add 10.0.0.100/24 dev veths 259 ip2 link set veths up 260 waitiface $netns0 vethrc 261 waitiface $netns0 vethrs 262 waitiface $netns1 vethc 263 waitiface $netns2 veths 264 265 n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward' 266 n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout' 267 n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream' 268 n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1 269 270 n0 wg set wg1 peer "$pub2" endpoint 10.0.0.100:20000 persistent-keepalive 1 271 n1 ping -W 1 -c 1 192.168.241.2 272 n2 ping -W 1 -c 1 192.168.241.1 273 [[ $(n2 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] 274 # Demonstrate n2 can still send packets to n1, since persistent-keepalive will prevent connection tracking entry from expiring (to see entries: `n0 conntrack -L`). 275 pp sleep 3 276 n2 ping -W 1 -c 1 192.168.241.1 277 278 n0 iptables -t nat -F 279 ip0 link del vethrc 280 ip0 link del vethrs 281 ip1 link del wg1 282 ip2 link del wg2 283 284 # Test that saddr routing is sticky but not too sticky, changing to this topology: 285 # ┌────────────────────────────────────────┐ ┌────────────────────────────────────────┐ 286 # │ $ns1 namespace │ │ $ns2 namespace │ 287 # │ │ │ │ 288 # │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ ┌─────┐ │ 289 # │ │ wg1 │─────────────│veth1│───────────┼────┼──│veth2│────────────│ wg2 │ │ 290 # │ ├─────┴──────────┐ ├─────┴──────────┐│ │ ├─────┴──────────┐ ├─────┴──────────┐ │ 291 # │ │192.168.241.1/24│ │10.0.0.1/24 ││ │ │10.0.0.2/24 │ │192.168.241.2/24│ │ 292 # │ │fd00::1/24 │ │fd00:aa::1/96 ││ │ │fd00:aa::2/96 │ │fd00::2/24 │ │ 293 # │ └────────────────┘ └────────────────┘│ │ └────────────────┘ └────────────────┘ │ 294 # └────────────────────────────────────────┘ └────────────────────────────────────────┘ 295 296 # ip1 link add dev wg1 type wireguard 297 # ip2 link add dev wg1 type wireguard 298 n1 $program wg1 299 n2 $program wg2 300 301 configure_peers 302 303 ip1 link add veth1 type veth peer name veth2 304 ip1 link set veth2 netns $netns2 305 n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad' 306 n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad' 307 n1 bash -c 'printf 1 > /proc/sys/net/ipv4/conf/veth1/promote_secondaries' 308 309 # First we check that we aren't overly sticky and can fall over to new IPs when old ones are removed 310 ip1 addr add 10.0.0.1/24 dev veth1 311 ip1 addr add fd00:aa::1/96 dev veth1 312 ip2 addr add 10.0.0.2/24 dev veth2 313 ip2 addr add fd00:aa::2/96 dev veth2 314 ip1 link set veth1 up 315 ip2 link set veth2 up 316 waitiface $netns1 veth1 317 waitiface $netns2 veth2 318 n0 wg set wg1 peer "$pub2" endpoint 10.0.0.2:20000 319 n1 ping -W 1 -c 1 192.168.241.2 320 ip1 addr add 10.0.0.10/24 dev veth1 321 ip1 addr del 10.0.0.1/24 dev veth1 322 n1 ping -W 1 -c 1 192.168.241.2 323 n0 wg set wg1 peer "$pub2" endpoint [fd00:aa::2]:20000 324 n1 ping -W 1 -c 1 192.168.241.2 325 ip1 addr add fd00:aa::10/96 dev veth1 326 ip1 addr del fd00:aa::1/96 dev veth1 327 n1 ping -W 1 -c 1 192.168.241.2 328 329 # Now we show that we can successfully do reply to sender routing 330 ip1 link set veth1 down 331 ip2 link set veth2 down 332 ip1 addr flush dev veth1 333 ip2 addr flush dev veth2 334 ip1 addr add 10.0.0.1/24 dev veth1 335 ip1 addr add 10.0.0.2/24 dev veth1 336 ip1 addr add fd00:aa::1/96 dev veth1 337 ip1 addr add fd00:aa::2/96 dev veth1 338 ip2 addr add 10.0.0.3/24 dev veth2 339 ip2 addr add fd00:aa::3/96 dev veth2 340 ip1 link set veth1 up 341 ip2 link set veth2 up 342 waitiface $netns1 veth1 343 waitiface $netns2 veth2 344 n0 wg set wg2 peer "$pub1" endpoint 10.0.0.1:10000 345 n2 ping -W 1 -c 1 192.168.241.1 346 [[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] 347 n0 wg set wg2 peer "$pub1" endpoint [fd00:aa::1]:10000 348 n2 ping -W 1 -c 1 192.168.241.1 349 [[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::1]:10000" ]] 350 n0 wg set wg2 peer "$pub1" endpoint 10.0.0.2:10000 351 n2 ping -W 1 -c 1 192.168.241.1 352 [[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.2:10000" ]] 353 n0 wg set wg2 peer "$pub1" endpoint [fd00:aa::2]:10000 354 n2 ping -W 1 -c 1 192.168.241.1 355 [[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::2]:10000" ]] 356 357 ip1 link del veth1 358 ip1 link del wg1 359 ip2 link del wg2 360 361 # Test that Netlink/IPC is working properly by doing things that usually cause split responses 362 363 n0 $program wg0 364 sleep 5 365 config=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" ) 366 for a in {1..255}; do 367 for b in {0..255}; do 368 config+=( "AllowedIPs=$a.$b.0.0/16,$a::$b/128" ) 369 done 370 done 371 n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 372 i=0 373 for ip in $(n0 wg show wg0 allowed-ips); do 374 ((++i)) 375 done 376 ((i == 255*256*2+1)) 377 ip0 link del wg0 378 379 n0 $program wg0 380 config=( "[Interface]" "PrivateKey=$(wg genkey)" ) 381 for a in {1..40}; do 382 config+=( "[Peer]" "PublicKey=$(wg genkey)" ) 383 for b in {1..52}; do 384 config+=( "AllowedIPs=$a.$b.0.0/16" ) 385 done 386 done 387 n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 388 i=0 389 while read -r line; do 390 j=0 391 for ip in $line; do 392 ((++j)) 393 done 394 ((j == 53)) 395 ((++i)) 396 done < <(n0 wg show wg0 allowed-ips) 397 ((i == 40)) 398 ip0 link del wg0 399 400 n0 $program wg0 401 config=( ) 402 for i in {1..29}; do 403 config+=( "[Peer]" "PublicKey=$(wg genkey)" ) 404 done 405 config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" ) 406 n0 wg setconf wg0 <(printf '%s\n' "${config[@]}") 407 n0 wg showconf wg0 > /dev/null 408 ip0 link del wg0 409 410 ! n0 wg show doesnotexist || false 411 412 declare -A objects 413 while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do 414 [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ [0-9]+)\ .*(created|destroyed).* ]] || continue 415 objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}" 416 done < /dev/kmsg 417 alldeleted=1 418 for object in "${!objects[@]}"; do 419 if [[ ${objects["$object"]} != *createddestroyed ]]; then 420 echo "Error: $object: merely ${objects["$object"]}" >&3 421 alldeleted=0 422 fi 423 done 424 [[ $alldeleted -eq 1 ]] 425 pretty "" "Objects that were created were also destroyed."