netns.sh 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  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.
  24. set -e
  25. shopt -s extglob
  26. exec 3>&1
  27. export LANG=C
  28. export WG_HIDE_KEYS=never
  29. NPROC=( /sys/devices/system/cpu/cpu+([0-9]) ); NPROC=${#NPROC[@]}
  30. netns0="wg-test-$$-0"
  31. netns1="wg-test-$$-1"
  32. netns2="wg-test-$$-2"
  33. pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; }
  34. pp() { pretty "" "$*"; "$@"; }
  35. maybe_exec() { if [[ $BASHPID -eq $$ ]]; then "$@"; else exec "$@"; fi; }
  36. n0() { pretty 0 "$*"; maybe_exec ip netns exec $netns0 "$@"; }
  37. n1() { pretty 1 "$*"; maybe_exec ip netns exec $netns1 "$@"; }
  38. n2() { pretty 2 "$*"; maybe_exec ip netns exec $netns2 "$@"; }
  39. ip0() { pretty 0 "ip $*"; ip -n $netns0 "$@"; }
  40. ip1() { pretty 1 "ip $*"; ip -n $netns1 "$@"; }
  41. ip2() { pretty 2 "ip $*"; ip -n $netns2 "$@"; }
  42. sleep() { read -t "$1" -N 1 || true; }
  43. waitiperf() { 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; }
  44. waitncatudp() { pretty "${1//*-}" "wait for udp:1111 pid $2"; while [[ $(ss -N "$1" -ulpH 'sport = 1111') != *\"ncat\",pid=$2,fd=* ]]; do sleep 0.1; done; }
  45. 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;"; }
  46. cleanup() {
  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. orig_message_cost="$(< /proc/sys/net/core/message_cost)"
  64. trap cleanup EXIT
  65. printf 0 > /proc/sys/net/core/message_cost
  66. ip netns del $netns0 2>/dev/null || true
  67. ip netns del $netns1 2>/dev/null || true
  68. ip netns del $netns2 2>/dev/null || true
  69. pp ip netns add $netns0
  70. pp ip netns add $netns1
  71. pp ip netns add $netns2
  72. ip0 link set up dev lo
  73. ip0 link add dev wg0 type wireguard
  74. ip0 link set wg0 netns $netns1
  75. ip0 link add dev wg0 type wireguard
  76. ip0 link set wg0 netns $netns2
  77. key1="$(pp wg genkey)"
  78. key2="$(pp wg genkey)"
  79. key3="$(pp wg genkey)"
  80. key4="$(pp wg genkey)"
  81. pub1="$(pp wg pubkey <<<"$key1")"
  82. pub2="$(pp wg pubkey <<<"$key2")"
  83. pub3="$(pp wg pubkey <<<"$key3")"
  84. pub4="$(pp wg pubkey <<<"$key4")"
  85. psk="$(pp wg genpsk)"
  86. [[ -n $key1 && -n $key2 && -n $psk ]]
  87. configure_peers() {
  88. ip1 addr add 192.168.241.1/24 dev wg0
  89. ip1 addr add fd00::1/112 dev wg0
  90. ip2 addr add 192.168.241.2/24 dev wg0
  91. ip2 addr add fd00::2/112 dev wg0
  92. n1 wg set wg0 \
  93. private-key <(echo "$key1") \
  94. listen-port 1 \
  95. peer "$pub2" \
  96. preshared-key <(echo "$psk") \
  97. allowed-ips 192.168.241.2/32,fd00::2/128
  98. n2 wg set wg0 \
  99. private-key <(echo "$key2") \
  100. listen-port 2 \
  101. peer "$pub1" \
  102. preshared-key <(echo "$psk") \
  103. allowed-ips 192.168.241.1/32,fd00::1/128
  104. ip1 link set up dev wg0
  105. ip2 link set up dev wg0
  106. }
  107. configure_peers
  108. tests() {
  109. # Ping over IPv4
  110. n2 ping -c 10 -f -W 1 192.168.241.1
  111. n1 ping -c 10 -f -W 1 192.168.241.2
  112. # Ping over IPv6
  113. n2 ping6 -c 10 -f -W 1 fd00::1
  114. n1 ping6 -c 10 -f -W 1 fd00::2
  115. # TCP over IPv4
  116. n2 iperf3 -s -1 -B 192.168.241.2 &
  117. waitiperf $netns2 $!
  118. n1 iperf3 -Z -t 3 -c 192.168.241.2
  119. # TCP over IPv6
  120. n1 iperf3 -s -1 -B fd00::1 &
  121. waitiperf $netns1 $!
  122. n2 iperf3 -Z -t 3 -c fd00::1
  123. # UDP over IPv4
  124. n1 iperf3 -s -1 -B 192.168.241.1 &
  125. waitiperf $netns1 $!
  126. n2 iperf3 -Z -t 3 -b 0 -u -c 192.168.241.1
  127. # UDP over IPv6
  128. n2 iperf3 -s -1 -B fd00::2 &
  129. waitiperf $netns2 $!
  130. n1 iperf3 -Z -t 3 -b 0 -u -c fd00::2
  131. # TCP over IPv4, in parallel
  132. local pids=( ) i
  133. for ((i=0; i < NPROC; ++i)) do
  134. n2 iperf3 -p $(( 5200 + i )) -s -1 -B 192.168.241.2 &
  135. pids+=( $! ); waitiperf $netns2 $! $(( 5200 + i ))
  136. done
  137. for ((i=0; i < NPROC; ++i)) do
  138. n1 iperf3 -Z -t 3 -p $(( 5200 + i )) -c 192.168.241.2 &
  139. done
  140. wait "${pids[@]}"
  141. }
  142. [[ $(ip1 link show dev wg0) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}"
  143. big_mtu=$(( 34816 - 1500 + $orig_mtu ))
  144. # Test using IPv4 as outer transport
  145. n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
  146. n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
  147. # Before calling tests, we first make sure that the stats counters and timestamper are working
  148. n2 ping -c 10 -f -W 1 192.168.241.1
  149. { read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip2 -stats link show dev wg0)
  150. (( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
  151. { read _; read _; read _; read rx_bytes _; read _; read tx_bytes _; } < <(ip1 -stats link show dev wg0)
  152. (( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
  153. read _ rx_bytes tx_bytes < <(n2 wg show wg0 transfer)
  154. (( rx_bytes == 1372 && (tx_bytes == 1428 || tx_bytes == 1460) ))
  155. read _ rx_bytes tx_bytes < <(n1 wg show wg0 transfer)
  156. (( tx_bytes == 1372 && (rx_bytes == 1428 || rx_bytes == 1460) ))
  157. read _ timestamp < <(n1 wg show wg0 latest-handshakes)
  158. (( timestamp != 0 ))
  159. tests
  160. ip1 link set wg0 mtu $big_mtu
  161. ip2 link set wg0 mtu $big_mtu
  162. tests
  163. ip1 link set wg0 mtu $orig_mtu
  164. ip2 link set wg0 mtu $orig_mtu
  165. # Test using IPv6 as outer transport
  166. n1 wg set wg0 peer "$pub2" endpoint [::1]:2
  167. n2 wg set wg0 peer "$pub1" endpoint [::1]:1
  168. tests
  169. ip1 link set wg0 mtu $big_mtu
  170. ip2 link set wg0 mtu $big_mtu
  171. tests
  172. # Test that route MTUs work with the padding
  173. ip1 link set wg0 mtu 1300
  174. ip2 link set wg0 mtu 1300
  175. n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
  176. n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
  177. n0 iptables -A INPUT -m length --length 1360 -j DROP
  178. n1 ip route add 192.168.241.2/32 dev wg0 mtu 1299
  179. n2 ip route add 192.168.241.1/32 dev wg0 mtu 1299
  180. n2 ping -c 1 -W 1 -s 1269 192.168.241.1
  181. n2 ip route delete 192.168.241.1/32 dev wg0 mtu 1299
  182. n1 ip route delete 192.168.241.2/32 dev wg0 mtu 1299
  183. n0 iptables -F INPUT
  184. ip1 link set wg0 mtu $orig_mtu
  185. ip2 link set wg0 mtu $orig_mtu
  186. # Test using IPv4 that roaming works
  187. ip0 -4 addr del 127.0.0.1/8 dev lo
  188. ip0 -4 addr add 127.212.121.99/8 dev lo
  189. n1 wg set wg0 listen-port 9999
  190. n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
  191. n1 ping6 -W 1 -c 1 fd00::2
  192. [[ $(n2 wg show wg0 endpoints) == "$pub1 127.212.121.99:9999" ]]
  193. # Test using IPv6 that roaming works
  194. n1 wg set wg0 listen-port 9998
  195. n1 wg set wg0 peer "$pub2" endpoint [::1]:2
  196. n1 ping -W 1 -c 1 192.168.241.2
  197. [[ $(n2 wg show wg0 endpoints) == "$pub1 [::1]:9998" ]]
  198. # Test that crypto-RP filter works
  199. n1 wg set wg0 peer "$pub2" allowed-ips 192.168.241.0/24
  200. exec 4< <(n1 ncat -l -u -p 1111)
  201. ncat_pid=$!
  202. waitncatudp $netns1 $ncat_pid
  203. n2 ncat -u 192.168.241.1 1111 <<<"X"
  204. read -r -N 1 -t 1 out <&4 && [[ $out == "X" ]]
  205. kill $ncat_pid
  206. more_specific_key="$(pp wg genkey | pp wg pubkey)"
  207. n1 wg set wg0 peer "$more_specific_key" allowed-ips 192.168.241.2/32
  208. n2 wg set wg0 listen-port 9997
  209. exec 4< <(n1 ncat -l -u -p 1111)
  210. ncat_pid=$!
  211. waitncatudp $netns1 $ncat_pid
  212. n2 ncat -u 192.168.241.1 1111 <<<"X"
  213. ! read -r -N 1 -t 1 out <&4 || false
  214. kill $ncat_pid
  215. n1 wg set wg0 peer "$more_specific_key" remove
  216. [[ $(n1 wg show wg0 endpoints) == "$pub2 [::1]:9997" ]]
  217. # Test that we can change private keys keys and immediately handshake
  218. n1 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
  219. n2 wg set wg0 private-key <(echo "$key2") listen-port 2 peer "$pub1" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32
  220. n1 ping -W 1 -c 1 192.168.241.2
  221. n1 wg set wg0 private-key <(echo "$key3")
  222. n2 wg set wg0 peer "$pub3" preshared-key <(echo "$psk") allowed-ips 192.168.241.1/32 peer "$pub1" remove
  223. n1 ping -W 1 -c 1 192.168.241.2
  224. n2 wg set wg0 peer "$pub3" remove
  225. # Test that we can route wg through wg
  226. ip1 addr flush dev wg0
  227. ip2 addr flush dev wg0
  228. ip1 addr add fd00::5:1/112 dev wg0
  229. ip2 addr add fd00::5:2/112 dev wg0
  230. n1 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
  231. n2 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
  232. ip1 link add wg1 type wireguard
  233. ip2 link add wg1 type wireguard
  234. ip1 addr add 192.168.241.1/24 dev wg1
  235. ip1 addr add fd00::1/112 dev wg1
  236. ip2 addr add 192.168.241.2/24 dev wg1
  237. ip2 addr add fd00::2/112 dev wg1
  238. ip1 link set mtu 1340 up dev wg1
  239. ip2 link set mtu 1340 up dev wg1
  240. n1 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
  241. n2 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
  242. tests
  243. # Try to set up a routing loop between the two namespaces
  244. ip1 link set netns $netns0 dev wg1
  245. ip0 addr add 192.168.241.1/24 dev wg1
  246. ip0 link set up dev wg1
  247. n0 ping -W 1 -c 1 192.168.241.2
  248. n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7
  249. ip2 link del wg0
  250. ip2 link del wg1
  251. read _ _ tx_bytes_before < <(n0 wg show wg1 transfer)
  252. ! n0 ping -W 1 -c 10 -f 192.168.241.2 || false
  253. sleep 1
  254. read _ _ tx_bytes_after < <(n0 wg show wg1 transfer)
  255. if ! (( tx_bytes_after - tx_bytes_before < 70000 )); then
  256. errstart=$'\x1b[37m\x1b[41m\x1b[1m'
  257. errend=$'\x1b[0m'
  258. echo "${errstart} ${errend}"
  259. echo "${errstart} E R R O R ${errend}"
  260. echo "${errstart} ${errend}"
  261. echo "${errstart} This architecture does not do the right thing ${errend}"
  262. echo "${errstart} with cross-namespace routing loops. This test ${errend}"
  263. echo "${errstart} has thus technically failed but, as this issue ${errend}"
  264. echo "${errstart} is as yet unsolved, these tests will continue ${errend}"
  265. echo "${errstart} onward. :( ${errend}"
  266. echo "${errstart} ${errend}"
  267. fi
  268. ip0 link del wg1
  269. ip1 link del wg0
  270. # Test using NAT. We now change the topology to this:
  271. # ┌────────────────────────────────────────┐ ┌────────────────────────────────────────────────┐ ┌────────────────────────────────────────┐
  272. # │ $ns1 namespace │ │ $ns0 namespace │ │ $ns2 namespace │
  273. # │ │ │ │ │ │
  274. # │ ┌─────┐ ┌─────┐ │ │ ┌──────┐ ┌──────┐ │ │ ┌─────┐ ┌─────┐ │
  275. # │ │ wg0 │─────────────│vethc│───────────┼────┼────│vethrc│ │vethrs│──────────────┼─────┼──│veths│────────────│ wg0 │ │
  276. # │ ├─────┴──────────┐ ├─────┴──────────┐│ │ ├──────┴─────────┐ ├──────┴────────────┐ │ │ ├─────┴──────────┐ ├─────┴──────────┐ │
  277. # │ │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│ │
  278. # │ │fd00::1/24 │ │ ││ │ │ │ │SNAT:192.168.1.0/24│ │ │ │ │ │fd00::2/24 │ │
  279. # │ └────────────────┘ └────────────────┘│ │ └────────────────┘ └───────────────────┘ │ │ └────────────────┘ └────────────────┘ │
  280. # └────────────────────────────────────────┘ └────────────────────────────────────────────────┘ └────────────────────────────────────────┘
  281. ip1 link add dev wg0 type wireguard
  282. ip2 link add dev wg0 type wireguard
  283. configure_peers
  284. ip0 link add vethrc type veth peer name vethc
  285. ip0 link add vethrs type veth peer name veths
  286. ip0 link set vethc netns $netns1
  287. ip0 link set veths netns $netns2
  288. ip0 link set vethrc up
  289. ip0 link set vethrs up
  290. ip0 addr add 192.168.1.1/24 dev vethrc
  291. ip0 addr add 10.0.0.1/24 dev vethrs
  292. ip1 addr add 192.168.1.100/24 dev vethc
  293. ip1 link set vethc up
  294. ip1 route add default via 192.168.1.1
  295. ip2 addr add 10.0.0.100/24 dev veths
  296. ip2 link set veths up
  297. waitiface $netns0 vethrc
  298. waitiface $netns0 vethrs
  299. waitiface $netns1 vethc
  300. waitiface $netns2 veths
  301. n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
  302. [[ -e /proc/sys/net/netfilter/nf_conntrack_udp_timeout ]] || modprobe nf_conntrack
  303. n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout'
  304. n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream'
  305. 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
  306. n1 wg set wg0 peer "$pub2" endpoint 10.0.0.100:2 persistent-keepalive 1
  307. n1 ping -W 1 -c 1 192.168.241.2
  308. n2 ping -W 1 -c 1 192.168.241.1
  309. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]]
  310. # Demonstrate n2 can still send packets to n1, since persistent-keepalive will prevent connection tracking entry from expiring (to see entries: `n0 conntrack -L`).
  311. pp sleep 3
  312. n2 ping -W 1 -c 1 192.168.241.1
  313. n1 wg set wg0 peer "$pub2" persistent-keepalive 0
  314. # Test that sk_bound_dev_if works
  315. n1 ping -I wg0 -c 1 -W 1 192.168.241.2
  316. # What about when the mark changes and the packet must be rerouted?
  317. n1 iptables -t mangle -I OUTPUT -j MARK --set-xmark 1
  318. n1 ping -c 1 -W 1 192.168.241.2 # First the boring case
  319. n1 ping -I wg0 -c 1 -W 1 192.168.241.2 # Then the sk_bound_dev_if case
  320. n1 iptables -t mangle -D OUTPUT -j MARK --set-xmark 1
  321. # Test that onion routing works, even when it loops
  322. n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
  323. ip1 addr add 192.168.242.1/24 dev wg0
  324. ip2 link add wg1 type wireguard
  325. ip2 addr add 192.168.242.2/24 dev wg1
  326. n2 wg set wg1 private-key <(echo "$key3") listen-port 5 peer "$pub1" allowed-ips 192.168.242.1/32
  327. ip2 link set wg1 up
  328. n1 ping -W 1 -c 1 192.168.242.2
  329. ip2 link del wg1
  330. n1 wg set wg0 peer "$pub3" endpoint 192.168.242.2:5
  331. ! n1 ping -W 1 -c 1 192.168.242.2 || false # Should not crash kernel
  332. n1 wg set wg0 peer "$pub3" remove
  333. ip1 addr del 192.168.242.1/24 dev wg0
  334. # Do a wg-quick(8)-style policy routing for the default route, making sure vethc has a v6 address to tease out bugs.
  335. ip1 -6 addr add fc00::9/96 dev vethc
  336. ip1 -6 route add default via fc00::1
  337. ip2 -4 addr add 192.168.99.7/32 dev wg0
  338. ip2 -6 addr add abab::1111/128 dev wg0
  339. n1 wg set wg0 fwmark 51820 peer "$pub2" allowed-ips 192.168.99.7,abab::1111
  340. ip1 -6 route add default dev wg0 table 51820
  341. ip1 -6 rule add not fwmark 51820 table 51820
  342. ip1 -6 rule add table main suppress_prefixlength 0
  343. ip1 -4 route add default dev wg0 table 51820
  344. ip1 -4 rule add not fwmark 51820 table 51820
  345. ip1 -4 rule add table main suppress_prefixlength 0
  346. n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/vethc/rp_filter'
  347. # Flood the pings instead of sending just one, to trigger routing table reference counting bugs.
  348. n1 ping -W 1 -c 100 -f 192.168.99.7
  349. n1 ping -W 1 -c 100 -f abab::1111
  350. # Have ns2 NAT into wg0 packets from ns0, but return an icmp error along the right route.
  351. n2 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 192.168.241.0/24 -j SNAT --to 192.168.241.2
  352. n0 iptables -t filter -A INPUT \! -s 10.0.0.0/24 -i vethrs -j DROP # Manual rpfilter just to be explicit.
  353. n2 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
  354. ip0 -4 route add 192.168.241.1 via 10.0.0.100
  355. n2 wg set wg0 peer "$pub1" remove
  356. [[ $(! n0 ping -W 1 -c 1 192.168.241.1 || false) == *"From 10.0.0.100 icmp_seq=1 Destination Host Unreachable"* ]]
  357. n0 iptables -t nat -F
  358. n0 iptables -t filter -F
  359. n2 iptables -t nat -F
  360. ip0 link del vethrc
  361. ip0 link del vethrs
  362. ip1 link del wg0
  363. ip2 link del wg0
  364. # Test that saddr routing is sticky but not too sticky, changing to this topology:
  365. # ┌────────────────────────────────────────┐ ┌────────────────────────────────────────┐
  366. # │ $ns1 namespace │ │ $ns2 namespace │
  367. # │ │ │ │
  368. # │ ┌─────┐ ┌─────┐ │ │ ┌─────┐ ┌─────┐ │
  369. # │ │ wg0 │─────────────│veth1│───────────┼────┼──│veth2│────────────│ wg0 │ │
  370. # │ ├─────┴──────────┐ ├─────┴──────────┐│ │ ├─────┴──────────┐ ├─────┴──────────┐ │
  371. # │ │192.168.241.1/24│ │10.0.0.1/24 ││ │ │10.0.0.2/24 │ │192.168.241.2/24│ │
  372. # │ │fd00::1/24 │ │fd00:aa::1/96 ││ │ │fd00:aa::2/96 │ │fd00::2/24 │ │
  373. # │ └────────────────┘ └────────────────┘│ │ └────────────────┘ └────────────────┘ │
  374. # └────────────────────────────────────────┘ └────────────────────────────────────────┘
  375. ip1 link add dev wg0 type wireguard
  376. ip2 link add dev wg0 type wireguard
  377. configure_peers
  378. ip1 link add veth1 type veth peer name veth2
  379. ip1 link set veth2 netns $netns2
  380. n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
  381. n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/all/accept_dad'
  382. n1 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth1/accept_dad'
  383. n2 bash -c 'printf 0 > /proc/sys/net/ipv6/conf/veth2/accept_dad'
  384. n1 bash -c 'printf 1 > /proc/sys/net/ipv4/conf/veth1/promote_secondaries'
  385. # First we check that we aren't overly sticky and can fall over to new IPs when old ones are removed
  386. ip1 addr add 10.0.0.1/24 dev veth1
  387. ip1 addr add fd00:aa::1/96 dev veth1
  388. ip2 addr add 10.0.0.2/24 dev veth2
  389. ip2 addr add fd00:aa::2/96 dev veth2
  390. ip1 link set veth1 up
  391. ip2 link set veth2 up
  392. waitiface $netns1 veth1
  393. waitiface $netns2 veth2
  394. n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
  395. n1 ping -W 1 -c 1 192.168.241.2
  396. ip1 addr add 10.0.0.10/24 dev veth1
  397. ip1 addr del 10.0.0.1/24 dev veth1
  398. n1 ping -W 1 -c 1 192.168.241.2
  399. n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2
  400. n1 ping -W 1 -c 1 192.168.241.2
  401. ip1 addr add fd00:aa::10/96 dev veth1
  402. ip1 addr del fd00:aa::1/96 dev veth1
  403. n1 ping -W 1 -c 1 192.168.241.2
  404. # Now we show that we can successfully do reply to sender routing
  405. ip1 link set veth1 down
  406. ip2 link set veth2 down
  407. ip1 addr flush dev veth1
  408. ip2 addr flush dev veth2
  409. ip1 addr add 10.0.0.1/24 dev veth1
  410. ip1 addr add 10.0.0.2/24 dev veth1
  411. ip1 addr add fd00:aa::1/96 dev veth1
  412. ip1 addr add fd00:aa::2/96 dev veth1
  413. ip2 addr add 10.0.0.3/24 dev veth2
  414. ip2 addr add fd00:aa::3/96 dev veth2
  415. ip1 link set veth1 up
  416. ip2 link set veth2 up
  417. waitiface $netns1 veth1
  418. waitiface $netns2 veth2
  419. n2 wg set wg0 peer "$pub1" endpoint 10.0.0.1:1
  420. n2 ping -W 1 -c 1 192.168.241.1
  421. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]]
  422. n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1
  423. n2 ping -W 1 -c 1 192.168.241.1
  424. [[ $(n2 wg show wg0 endpoints) == "$pub1 [fd00:aa::1]:1" ]]
  425. n2 wg set wg0 peer "$pub1" endpoint 10.0.0.2:1
  426. n2 ping -W 1 -c 1 192.168.241.1
  427. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.2:1" ]]
  428. n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::2]:1
  429. n2 ping -W 1 -c 1 192.168.241.1
  430. [[ $(n2 wg show wg0 endpoints) == "$pub1 [fd00:aa::2]:1" ]]
  431. # What happens if the inbound destination address belongs to a different interface as the default route?
  432. ip1 link add dummy0 type dummy
  433. ip1 addr add 10.50.0.1/24 dev dummy0
  434. ip1 link set dummy0 up
  435. ip2 route add 10.50.0.0/24 dev veth2
  436. n2 wg set wg0 peer "$pub1" endpoint 10.50.0.1:1
  437. n2 ping -W 1 -c 1 192.168.241.1
  438. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.50.0.1:1" ]]
  439. ip1 link del dummy0
  440. ip1 addr flush dev veth1
  441. ip2 addr flush dev veth2
  442. ip1 route flush dev veth1
  443. ip2 route flush dev veth2
  444. # Now we see what happens if another interface route takes precedence over an ongoing one
  445. ip1 link add veth3 type veth peer name veth4
  446. ip1 link set veth4 netns $netns2
  447. ip1 addr add 10.0.0.1/24 dev veth1
  448. ip2 addr add 10.0.0.2/24 dev veth2
  449. ip1 addr add 10.0.0.3/24 dev veth3
  450. ip1 link set veth1 up
  451. ip2 link set veth2 up
  452. ip1 link set veth3 up
  453. ip2 link set veth4 up
  454. waitiface $netns1 veth1
  455. waitiface $netns2 veth2
  456. waitiface $netns1 veth3
  457. waitiface $netns2 veth4
  458. ip1 route flush dev veth1
  459. ip1 route flush dev veth3
  460. ip1 route add 10.0.0.0/24 dev veth1 src 10.0.0.1 metric 2
  461. n1 wg set wg0 peer "$pub2" endpoint 10.0.0.2:2
  462. n1 ping -W 1 -c 1 192.168.241.2
  463. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.1:1" ]]
  464. ip1 route add 10.0.0.0/24 dev veth3 src 10.0.0.3 metric 1
  465. n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter'
  466. n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/veth4/rp_filter'
  467. n1 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
  468. n2 bash -c 'printf 0 > /proc/sys/net/ipv4/conf/all/rp_filter'
  469. n1 ping -W 1 -c 1 192.168.241.2
  470. [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.3:1" ]]
  471. ip1 link del dev veth3
  472. ip1 link del dev wg0
  473. ip2 link del dev wg0
  474. # Make sure persistent keep alives are sent when an adapter comes up
  475. ip1 link add dev wg0 type wireguard
  476. n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1
  477. read _ _ tx_bytes < <(n1 wg show wg0 transfer)
  478. [[ $tx_bytes -eq 0 ]]
  479. ip1 link set dev wg0 up
  480. read _ _ tx_bytes < <(n1 wg show wg0 transfer)
  481. [[ $tx_bytes -gt 0 ]]
  482. ip1 link del dev wg0
  483. # This should also happen even if the private key is set later
  484. ip1 link add dev wg0 type wireguard
  485. n1 wg set wg0 peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1
  486. read _ _ tx_bytes < <(n1 wg show wg0 transfer)
  487. [[ $tx_bytes -eq 0 ]]
  488. ip1 link set dev wg0 up
  489. read _ _ tx_bytes < <(n1 wg show wg0 transfer)
  490. [[ $tx_bytes -eq 0 ]]
  491. n1 wg set wg0 private-key <(echo "$key1")
  492. read _ _ tx_bytes < <(n1 wg show wg0 transfer)
  493. [[ $tx_bytes -gt 0 ]]
  494. ip1 link del dev veth1
  495. ip1 link del dev wg0
  496. # We test that Netlink/IPC is working properly by doing things that usually cause split responses
  497. ip0 link add dev wg0 type wireguard
  498. config=( "[Interface]" "PrivateKey=$(wg genkey)" "[Peer]" "PublicKey=$(wg genkey)" )
  499. for a in {1..255}; do
  500. for b in {0..255}; do
  501. config+=( "AllowedIPs=$a.$b.0.0/16,$a::$b/128" )
  502. done
  503. done
  504. n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
  505. i=0
  506. for ip in $(n0 wg show wg0 allowed-ips); do
  507. ((++i))
  508. done
  509. ((i == 255*256*2+1))
  510. ip0 link del wg0
  511. ip0 link add dev wg0 type wireguard
  512. config=( "[Interface]" "PrivateKey=$(wg genkey)" )
  513. for a in {1..40}; do
  514. config+=( "[Peer]" "PublicKey=$(wg genkey)" )
  515. for b in {1..52}; do
  516. config+=( "AllowedIPs=$a.$b.0.0/16" )
  517. done
  518. done
  519. n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
  520. i=0
  521. while read -r line; do
  522. j=0
  523. for ip in $line; do
  524. ((++j))
  525. done
  526. ((j == 53))
  527. ((++i))
  528. done < <(n0 wg show wg0 allowed-ips)
  529. ((i == 40))
  530. ip0 link del wg0
  531. ip0 link add wg0 type wireguard
  532. config=( )
  533. for i in {1..29}; do
  534. config+=( "[Peer]" "PublicKey=$(wg genkey)" )
  535. done
  536. config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" )
  537. n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
  538. n0 wg showconf wg0 > /dev/null
  539. ip0 link del wg0
  540. allowedips=( )
  541. for i in {1..197}; do
  542. allowedips+=( abcd::$i )
  543. done
  544. saved_ifs="$IFS"
  545. IFS=,
  546. allowedips="${allowedips[*]}"
  547. IFS="$saved_ifs"
  548. ip0 link add wg0 type wireguard
  549. n0 wg set wg0 peer "$pub1"
  550. n0 wg set wg0 peer "$pub2" allowed-ips "$allowedips"
  551. {
  552. read -r pub allowedips
  553. [[ $pub == "$pub1" && $allowedips == "(none)" ]]
  554. read -r pub allowedips
  555. [[ $pub == "$pub2" ]]
  556. i=0
  557. for _ in $allowedips; do
  558. ((++i))
  559. done
  560. ((i == 197))
  561. } < <(n0 wg show wg0 allowed-ips)
  562. ip0 link del wg0
  563. allowedips=( )
  564. for i in {1..197}; do
  565. allowedips+=( 192.168.0.$i )
  566. allowedips+=( abcd::$i )
  567. done
  568. saved_ifs="$IFS"
  569. IFS=,
  570. allowedips="${allowedips[*]}"
  571. IFS="$saved_ifs"
  572. ip0 link add wg0 type wireguard
  573. n0 wg set wg0 peer "$pub1" allowed-ips "$allowedips"
  574. n0 wg set wg0 peer "$pub1" allowed-ips -192.168.0.1/32,-192.168.0.20/32,-192.168.0.100/32,-abcd::1/128,-abcd::20/128,-abcd::100/128
  575. {
  576. read -r pub allowedips
  577. [[ $pub == "$pub1" ]]
  578. i=0
  579. for ip in $allowedips; do
  580. [[ $ip != "192.168.0.1" ]]
  581. [[ $ip != "192.168.0.20" ]]
  582. [[ $ip != "192.168.0.100" ]]
  583. [[ $ip != "abcd::1" ]]
  584. [[ $ip != "abcd::20" ]]
  585. [[ $ip != "abcd::100" ]]
  586. ((++i))
  587. done
  588. ((i == 388))
  589. } < <(n0 wg show wg0 allowed-ips)
  590. ip0 link del wg0
  591. ! n0 wg show doesnotexist || false
  592. ip0 link add wg0 type wireguard
  593. n0 wg set wg0 private-key <(echo "$key1") peer "$pub2" preshared-key <(echo "$psk")
  594. [[ $(n0 wg show wg0 private-key) == "$key1" ]]
  595. [[ $(n0 wg show wg0 preshared-keys) == "$pub2 $psk" ]]
  596. n0 wg set wg0 private-key /dev/null peer "$pub2" preshared-key /dev/null
  597. [[ $(n0 wg show wg0 private-key) == "(none)" ]]
  598. [[ $(n0 wg show wg0 preshared-keys) == "$pub2 (none)" ]]
  599. n0 wg set wg0 peer "$pub2"
  600. n0 wg set wg0 private-key <(echo "$key2")
  601. [[ $(n0 wg show wg0 public-key) == "$pub2" ]]
  602. [[ -z $(n0 wg show wg0 peers) ]]
  603. n0 wg set wg0 peer "$pub2"
  604. [[ -z $(n0 wg show wg0 peers) ]]
  605. n0 wg set wg0 private-key <(echo "$key1")
  606. n0 wg set wg0 peer "$pub2"
  607. [[ $(n0 wg show wg0 peers) == "$pub2" ]]
  608. n0 wg set wg0 private-key <(echo "/${key1:1}")
  609. [[ $(n0 wg show wg0 private-key) == "+${key1:1}" ]]
  610. n0 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
  611. n0 wg set wg0 peer "$pub2" allowed-ips 0.0.0.0/0
  612. n0 wg set wg0 peer "$pub2" allowed-ips ::/0,1700::/111,5000::/4,e000::/37,9000::/75
  613. n0 wg set wg0 peer "$pub2" allowed-ips ::/0
  614. n0 wg set wg0 peer "$pub2" remove
  615. for low_order_point in AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= 4Ot6fDtBuK4WVuP68Z/EatoJjeucMrH9hmIFFl9JuAA= X5yVvKNQjCSx0LFVnIPvWwREXMRYHI6G2CJO3dCfEVc= 7P///////////////////////////////////////38= 7f///////////////////////////////////////38= 7v///////////////////////////////////////38=; do
  616. n0 wg set wg0 peer "$low_order_point" persistent-keepalive 1 endpoint 127.0.0.1:1111
  617. done
  618. [[ -n $(n0 wg show wg0 peers) ]]
  619. exec 4< <(n0 ncat -l -u -p 1111)
  620. ncat_pid=$!
  621. waitncatudp $netns0 $ncat_pid
  622. ip0 link set wg0 up
  623. ! read -r -n 1 -t 2 <&4 || false
  624. kill $ncat_pid
  625. ip0 link del wg0
  626. # Ensure that dst_cache references don't outlive netns lifetime
  627. ip1 link add dev wg0 type wireguard
  628. ip2 link add dev wg0 type wireguard
  629. configure_peers
  630. ip1 link add veth1 type veth peer name veth2
  631. ip1 link set veth2 netns $netns2
  632. ip1 addr add fd00:aa::1/64 dev veth1
  633. ip2 addr add fd00:aa::2/64 dev veth2
  634. ip1 link set veth1 up
  635. ip2 link set veth2 up
  636. waitiface $netns1 veth1
  637. waitiface $netns2 veth2
  638. ip1 -6 route add default dev veth1 via fd00:aa::2
  639. ip2 -6 route add default dev veth2 via fd00:aa::1
  640. n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2
  641. n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1
  642. n1 ping6 -c 1 fd00::2
  643. pp ip netns delete $netns1
  644. pp ip netns delete $netns2
  645. pp ip netns add $netns1
  646. pp ip netns add $netns2
  647. # Ensure there aren't circular reference loops
  648. ip1 link add wg1 type wireguard
  649. ip2 link add wg2 type wireguard
  650. ip1 link set wg1 netns $netns2
  651. ip2 link set wg2 netns $netns1
  652. pp ip netns delete $netns1
  653. pp ip netns delete $netns2
  654. pp ip netns add $netns1
  655. pp ip netns add $netns2
  656. sleep 2 # Wait for cleanup and grace periods
  657. declare -A objects
  658. while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do
  659. [[ $line =~ .*(wg[0-9]+:\ [A-Z][a-z]+\ ?[0-9]*)\ .*(created|destroyed).* ]] || continue
  660. objects["${BASH_REMATCH[1]}"]+="${BASH_REMATCH[2]}"
  661. done < /dev/kmsg
  662. alldeleted=1
  663. for object in "${!objects[@]}"; do
  664. if [[ ${objects["$object"]} != *createddestroyed && ${objects["$object"]} != *createdcreateddestroyeddestroyed ]]; then
  665. echo "Error: $object: merely ${objects["$object"]}" >&3
  666. alldeleted=0
  667. fi
  668. done
  669. [[ $alldeleted -eq 1 ]]
  670. pretty "" "Objects that were created were also destroyed."