1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2021 The FreeBSD Foundation 5# 6# This software was developed by Mark Johnston under sponsorship 7# from the FreeBSD Foundation. 8# 9# Redistribution and use in source and binary forms, with or without 10# modification, are permitted provided that the following conditions 11# are met: 12# 1. Redistributions of source code must retain the above copyright 13# notice, this list of conditions and the following disclaimer. 14# 2. Redistributions in binary form must reproduce the above copyright 15# notice, this list of conditions and the following disclaimer in the 16# documentation and/or other materials provided with the distribution. 17# 18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28# SUCH DAMAGE. 29 30. $(atf_get_srcdir)/../common/vnet.subr 31 32atf_test_case "wg_basic" "cleanup" 33wg_basic_head() 34{ 35 atf_set descr 'Create a wg(4) tunnel over an epair and pass traffic between jails' 36 atf_set require.user root 37} 38 39wg_basic_body() 40{ 41 local epair pri1 pri2 pub1 pub2 wg1 wg2 42 local endpoint1 endpoint2 tunnel1 tunnel2 43 44 kldload -n if_wg || atf_skip "This test requires if_wg and could not load it" 45 46 pri1=$(wg genkey) 47 pri2=$(wg genkey) 48 49 endpoint1=192.168.2.1 50 endpoint2=192.168.2.2 51 tunnel1=169.254.0.1 52 tunnel2=169.254.0.2 53 54 epair=$(vnet_mkepair) 55 56 vnet_init 57 58 vnet_mkjail wgtest1 ${epair}a 59 vnet_mkjail wgtest2 ${epair}b 60 61 jexec wgtest1 ifconfig ${epair}a ${endpoint1}/24 up 62 jexec wgtest2 ifconfig ${epair}b ${endpoint2}/24 up 63 64 wg1=$(jexec wgtest1 ifconfig wg create) 65 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 66 private-key /dev/stdin 67 pub1=$(jexec wgtest1 wg show $wg1 public-key) 68 wg2=$(jexec wgtest2 ifconfig wg create) 69 echo "$pri2" | jexec wgtest2 wg set $wg2 listen-port 12345 \ 70 private-key /dev/stdin 71 pub2=$(jexec wgtest2 wg show $wg2 public-key) 72 73 atf_check -s exit:0 -o ignore \ 74 jexec wgtest1 wg set $wg1 peer "$pub2" \ 75 endpoint ${endpoint2}:12345 allowed-ips ${tunnel2}/32 76 atf_check -s exit:0 \ 77 jexec wgtest1 ifconfig $wg1 inet ${tunnel1}/24 up 78 79 atf_check -s exit:0 -o ignore \ 80 jexec wgtest2 wg set $wg2 peer "$pub1" \ 81 endpoint ${endpoint1}:12345 allowed-ips ${tunnel1}/32 82 atf_check -s exit:0 \ 83 jexec wgtest2 ifconfig $wg2 inet ${tunnel2}/24 up 84 85 # Generous timeout since the handshake takes some time. 86 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 -t 5 $tunnel2 87 atf_check -s exit:0 -o ignore jexec wgtest2 ping -c 1 $tunnel1 88} 89 90wg_basic_cleanup() 91{ 92 vnet_cleanup 93} 94 95atf_test_case "wg_basic_crossaf" "cleanup" 96wg_basic_crossaf_head() 97{ 98 atf_set descr 'Create a wg(4) tunnel and pass IPv4 traffic over an IPv6 nexthop' 99 atf_set require.user root 100} 101 102wg_basic_crossaf_body() 103{ 104 local epair pri1 pri2 pub1 pub2 wg1 wg2 105 local endpoint1 endpoint2 tunnel1 tunnel2 106 local testnet testlocal testremote 107 108 kldload -n if_wg || atf_skip "This test requires if_wg and could not load it" 109 110 pri1=$(wg genkey) 111 pri2=$(wg genkey) 112 113 endpoint1=192.168.2.1 114 endpoint2=192.168.2.2 115 tunnel1=2001:db8:1::1 116 tunnel2=2001:db8:1::2 117 118 testnet=192.168.3.0/24 119 testlocal=192.168.3.1 120 testremote=192.168.3.2 121 122 epair=$(vnet_mkepair) 123 124 vnet_init 125 126 vnet_mkjail wgtest1 ${epair}a 127 vnet_mkjail wgtest2 ${epair}b 128 129 jexec wgtest1 ifconfig ${epair}a ${endpoint1}/24 up 130 jexec wgtest2 ifconfig ${epair}b ${endpoint2}/24 up 131 132 wg1=$(jexec wgtest1 ifconfig wg create) 133 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 134 private-key /dev/stdin 135 pub1=$(jexec wgtest1 wg show $wg1 public-key) 136 wg2=$(jexec wgtest2 ifconfig wg create) 137 echo "$pri2" | jexec wgtest2 wg set $wg2 listen-port 12345 \ 138 private-key /dev/stdin 139 pub2=$(jexec wgtest2 wg show $wg2 public-key) 140 141 atf_check -s exit:0 -o ignore \ 142 jexec wgtest1 wg set $wg1 peer "$pub2" \ 143 endpoint ${endpoint2}:12345 allowed-ips ${tunnel2}/128,${testnet} 144 atf_check -s exit:0 \ 145 jexec wgtest1 ifconfig $wg1 inet6 ${tunnel1}/64 up 146 147 atf_check -s exit:0 -o ignore \ 148 jexec wgtest2 wg set $wg2 peer "$pub1" \ 149 endpoint ${endpoint1}:12345 allowed-ips ${tunnel1}/128,${testnet} 150 atf_check -s exit:0 \ 151 jexec wgtest2 ifconfig $wg2 inet6 ${tunnel2}/64 up 152 153 atf_check -s exit:0 jexec wgtest1 ifconfig $wg1 inet ${testlocal}/32 154 atf_check -s exit:0 jexec wgtest2 ifconfig $wg2 inet ${testremote}/32 155 156 # Generous timeout since the handshake takes some time. 157 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 -t 5 "$tunnel2" 158 159 # Setup our IPv6 endpoint and routing 160 atf_check -s exit:0 -o ignore \ 161 jexec wgtest1 route add -inet ${testnet} -inet6 "$tunnel2" 162 atf_check -s exit:0 -o ignore \ 163 jexec wgtest2 route add -inet ${testnet} -inet6 "$tunnel1" 164 # Now ping an address on the other side 165 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 -t 3 ${testremote} 166} 167 168wg_basic_crossaf_cleanup() 169{ 170 vnet_cleanup 171} 172 173atf_test_case "wg_basic_netmap" "cleanup" 174wg_basic_netmap_head() 175{ 176 atf_set descr 'Create a wg(4) tunnel over an epair and pass traffic between jails with netmap' 177 atf_set require.user root 178} 179 180wg_basic_netmap_body() 181{ 182 local epair pri1 pri2 pub1 pub2 wg1 wg2 183 local endpoint1 endpoint2 tunnel1 tunnel2 tunnel3 tunnel4 184 local pid status 185 186 kldload -n if_wg || atf_skip "This test requires if_wg and could not load it" 187 kldload -n netmap || atf_skip "This test requires netmap and could not load it" 188 189 pri1=$(wg genkey) 190 pri2=$(wg genkey) 191 192 endpoint1=192.168.2.1 193 endpoint2=192.168.2.2 194 tunnel1=192.168.3.1 195 tunnel2=192.168.3.2 196 tunnel3=192.168.3.3 197 tunnel4=192.168.3.4 198 199 epair=$(vnet_mkepair) 200 201 vnet_init 202 203 vnet_mkjail wgtest1 ${epair}a 204 vnet_mkjail wgtest2 ${epair}b 205 206 jexec wgtest1 ifconfig ${epair}a ${endpoint1}/24 up 207 jexec wgtest2 ifconfig ${epair}b ${endpoint2}/24 up 208 209 wg1=$(jexec wgtest1 ifconfig wg create) 210 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 211 private-key /dev/stdin 212 pub1=$(jexec wgtest1 wg show $wg1 public-key) 213 wg2=$(jexec wgtest2 ifconfig wg create) 214 echo "$pri2" | jexec wgtest2 wg set $wg2 listen-port 12345 \ 215 private-key /dev/stdin 216 pub2=$(jexec wgtest2 wg show $wg2 public-key) 217 218 atf_check -s exit:0 -o ignore \ 219 jexec wgtest1 wg set $wg1 peer "$pub2" \ 220 endpoint ${endpoint2}:12345 allowed-ips ${tunnel2}/32,${tunnel4}/32 221 atf_check -s exit:0 \ 222 jexec wgtest1 ifconfig $wg1 inet ${tunnel1}/24 up 223 224 atf_check -s exit:0 -o ignore \ 225 jexec wgtest2 wg set $wg2 peer "$pub1" \ 226 endpoint ${endpoint1}:12345 allowed-ips ${tunnel1}/32,${tunnel3}/32 227 atf_check -s exit:0 \ 228 jexec wgtest2 ifconfig $wg2 inet ${tunnel2}/24 up 229 230 atf_check -s exit:0 -o ignore \ 231 jexec wgtest1 sysctl net.inet.ip.forwarding=1 232 atf_check -s exit:0 -o ignore \ 233 jexec wgtest2 sysctl net.inet.ip.forwarding=1 234 235 jexec wgtest1 $(atf_get_srcdir)/bridge -w 0 -i netmap:wg0 -i netmap:wg0^ & 236 pid=$! 237 238 # Generous timeout since the handshake takes some time. 239 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 -t 5 $tunnel2 240 atf_check -s exit:0 -o ignore jexec wgtest2 ping -c 1 $tunnel1 241 242 # Verify that we cannot ping non-existent tunnel addresses. In general 243 # the remote side should respond with an ICMP message. 244 atf_check -s exit:2 -o ignore jexec wgtest1 ping -c 1 -t 2 $tunnel4 245 atf_check -s exit:2 -o ignore jexec wgtest2 ping -c 1 -t 2 $tunnel3 246 247 # Make sure that the bridge is still functional. 248 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 $tunnel2 249 atf_check -s exit:0 -o ignore jexec wgtest2 ping -c 1 $tunnel1 250 251 atf_check -s exit:0 kill -TERM $pid 252 wait $pid 253 status=$? 254 255 # Make sure that SIGTERM was received and handled. 256 atf_check_equal $status 143 257} 258 259wg_basic_netmap_cleanup() 260{ 261 vnet_cleanup 262} 263 264# The kernel is expected to silently ignore any attempt to add a peer with a 265# public key identical to the host's. 266atf_test_case "wg_key_peerdev_shared" "cleanup" 267wg_key_peerdev_shared_head() 268{ 269 atf_set descr 'Create a wg(4) interface with a shared pubkey between device and a peer' 270 atf_set require.user root 271} 272 273wg_key_peerdev_shared_body() 274{ 275 local epair pri1 pub1 wg1 276 local endpoint1 tunnel1 277 278 kldload -n if_wg || atf_skip "This test requires if_wg and could not load it" 279 280 pri1=$(wg genkey) 281 282 endpoint1=192.168.2.1 283 tunnel1=169.254.0.1 284 285 vnet_mkjail wgtest1 286 287 wg1=$(jexec wgtest1 ifconfig wg create) 288 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 289 private-key /dev/stdin 290 pub1=$(jexec wgtest1 wg show $wg1 public-key) 291 292 atf_check -s exit:0 \ 293 jexec wgtest1 wg set ${wg1} peer "${pub1}" \ 294 allowed-ips "${tunnel1}/32" 295 296 atf_check -o empty jexec wgtest1 wg show ${wg1} peers 297} 298 299wg_key_peerdev_shared_cleanup() 300{ 301 vnet_cleanup 302} 303 304# When a wg(8) interface has a private key reassigned that corresponds to the 305# public key already on a peer, the kernel is expected to deconfigure the peer 306# to resolve the conflict. 307atf_test_case "wg_key_peerdev_makeshared" "cleanup" 308wg_key_peerdev_makeshared_head() 309{ 310 atf_set descr 'Create a wg(4) interface and assign peer key to device' 311 atf_set require.progs wg 312} 313 314wg_key_peerdev_makeshared_body() 315{ 316 local epair pri1 pub1 pri2 wg1 wg2 317 local endpoint1 tunnel1 318 319 kldload -n if_wg || atf_skip "This test requires if_wg and could not load it" 320 321 pri1=$(wg genkey) 322 pri2=$(wg genkey) 323 324 endpoint1=192.168.2.1 325 tunnel1=169.254.0.1 326 327 vnet_mkjail wgtest1 328 329 wg1=$(jexec wgtest1 ifconfig wg create) 330 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 331 private-key /dev/stdin 332 pub1=$(jexec wgtest1 wg show $wg1 public-key) 333 wg2=$(jexec wgtest1 ifconfig wg create) 334 echo "$pri2" | jexec wgtest1 wg set $wg2 listen-port 12345 \ 335 private-key /dev/stdin 336 337 atf_check -s exit:0 -o ignore \ 338 jexec wgtest1 wg set ${wg2} peer "${pub1}" \ 339 allowed-ips "${tunnel1}/32" 340 341 atf_check -o not-empty jexec wgtest1 wg show ${wg2} peers 342 343 jexec wgtest1 sh -c "echo '${pri1}' > pri1" 344 345 atf_check -s exit:0 \ 346 jexec wgtest1 wg set ${wg2} private-key pri1 347 348 atf_check -o empty jexec wgtest1 wg show ${wg2} peers 349} 350 351wg_key_peerdev_makeshared_cleanup() 352{ 353 vnet_cleanup 354} 355 356# The kernel is expected to create the wg socket in the jail context that the 357# wg interface was created in, even if the interface is moved to a different 358# vnet. 359atf_test_case "wg_vnet_parent_routing" "cleanup" 360wg_vnet_parent_routing_head() 361{ 362 atf_set descr 'Create a wg(4) tunnel without epairs and pass traffic between jails' 363 atf_set require.user root 364} 365 366wg_vnet_parent_routing_body() 367{ 368 local pri1 pri2 pub1 pub2 wg1 wg2 369 local tunnel1 tunnel2 370 371 kldload -n if_wg 372 373 pri1=$(wg genkey) 374 pri2=$(wg genkey) 375 376 tunnel1=169.254.0.1 377 tunnel2=169.254.0.2 378 379 vnet_init 380 381 wg1=$(ifconfig wg create) 382 wg2=$(ifconfig wg create) 383 384 vnet_mkjail wgtest1 ${wg1} 385 vnet_mkjail wgtest2 ${wg2} 386 387 echo "$pri1" | jexec wgtest1 wg set $wg1 listen-port 12345 \ 388 private-key /dev/stdin 389 pub1=$(jexec wgtest1 wg show $wg1 public-key) 390 echo "$pri2" | jexec wgtest2 wg set $wg2 listen-port 12346 \ 391 private-key /dev/stdin 392 pub2=$(jexec wgtest2 wg show $wg2 public-key) 393 394 atf_check -s exit:0 -o ignore \ 395 jexec wgtest1 wg set $wg1 peer "$pub2" \ 396 endpoint 127.0.0.1:12346 allowed-ips ${tunnel2}/32 397 atf_check -s exit:0 \ 398 jexec wgtest1 ifconfig $wg1 inet ${tunnel1}/24 up 399 400 atf_check -s exit:0 -o ignore \ 401 jexec wgtest2 wg set $wg2 peer "$pub1" \ 402 endpoint 127.0.0.1:12345 allowed-ips ${tunnel1}/32 403 atf_check -s exit:0 \ 404 jexec wgtest2 ifconfig $wg2 inet ${tunnel2}/24 up 405 406 # Sanity check ICMP counters; should clearly be nothing on these new 407 # jails. We'll check them as we go to ensure that the ICMP packets 408 # generated really are being handled by the jails' vnets. 409 atf_check -o not-match:"histogram" jexec wgtest1 netstat -s -p icmp 410 atf_check -o not-match:"histogram" jexec wgtest2 netstat -s -p icmp 411 412 # Generous timeout since the handshake takes some time. 413 atf_check -s exit:0 -o ignore jexec wgtest1 ping -c 1 -t 5 $tunnel2 414 atf_check -o match:"echo reply: 1" jexec wgtest1 netstat -s -p icmp 415 atf_check -o match:"echo: 1" jexec wgtest2 netstat -s -p icmp 416 417 atf_check -s exit:0 -o ignore jexec wgtest2 ping -c 1 $tunnel1 418 atf_check -o match:"echo reply: 1" jexec wgtest2 netstat -s -p icmp 419 atf_check -o match:"echo: 1" jexec wgtest1 netstat -s -p icmp 420} 421 422wg_vnet_parent_routing_cleanup() 423{ 424 vnet_cleanup 425} 426 427atf_init_test_cases() 428{ 429 atf_add_test_case "wg_basic" 430 atf_add_test_case "wg_basic_crossaf" 431 atf_add_test_case "wg_basic_netmap" 432 atf_add_test_case "wg_key_peerdev_shared" 433 atf_add_test_case "wg_key_peerdev_makeshared" 434 atf_add_test_case "wg_vnet_parent_routing" 435} 436