1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2018 Kristof Provost <kp@FreeBSD.org> 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26 27. $(atf_get_srcdir)/utils.subr 28 29common_dir=$(atf_get_srcdir)/../common 30 31atf_test_case "enable_disable" "cleanup" 32enable_disable_head() 33{ 34 atf_set descr 'Test enable/disable' 35 atf_set require.user root 36} 37 38enable_disable_body() 39{ 40 pft_init 41 42 j="pass_block:enable_disable" 43 44 vnet_mkjail ${j} 45 46 # Disable when disabled fails 47 atf_check -s exit:1 -e ignore \ 48 jexec ${j} pfctl -d 49 50 # Enable succeeds 51 atf_check -s exit:0 -e ignore \ 52 jexec ${j} pfctl -e 53 54 # Enable when enabled fails 55 atf_check -s exit:1 -e ignore \ 56 jexec ${j} pfctl -e 57 58 # Disable succeeds 59 atf_check -s exit:0 -e ignore \ 60 jexec ${j} pfctl -d 61} 62 63enable_disable_cleanup() 64{ 65 pft_cleanup 66} 67 68atf_test_case "v4" "cleanup" 69v4_head() 70{ 71 atf_set descr 'Basic pass/block test for IPv4' 72 atf_set require.user root 73} 74 75v4_body() 76{ 77 pft_init 78 79 epair=$(vnet_mkepair) 80 ifconfig ${epair}a 192.0.2.1/24 up 81 82 # Set up a simple jail with one interface 83 vnet_mkjail alcatraz ${epair}b 84 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 85 86 # Trivial ping to the jail, without pf 87 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 88 89 # pf without policy will let us ping 90 jexec alcatraz pfctl -e 91 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 92 93 # Block everything 94 pft_set_rules alcatraz "block in" 95 atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2 96 97 # Block everything but ICMP 98 pft_set_rules alcatraz "block in" "pass in proto icmp" 99 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 100} 101 102v4_cleanup() 103{ 104 pft_cleanup 105} 106 107atf_test_case "v6" "cleanup" 108v6_head() 109{ 110 atf_set descr 'Basic pass/block test for IPv6' 111 atf_set require.user root 112} 113 114v6_body() 115{ 116 pft_init 117 118 epair=$(vnet_mkepair) 119 ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad 120 121 # Set up a simple jail with one interface 122 vnet_mkjail alcatraz ${epair}b 123 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad 124 125 # Trivial ping to the jail, without pf 126 atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 127 128 # pf without policy will let us ping 129 jexec alcatraz pfctl -e 130 atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 131 132 # Block everything 133 pft_set_rules alcatraz "block in" 134 atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 135 136 # Block everything but ICMP 137 pft_set_rules alcatraz "block in" "pass in proto icmp6" 138 atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 139 140 # Allowing ICMPv4 does not allow ICMPv6 141 pft_set_rules alcatraz "block in" "pass in proto icmp" 142 atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 143} 144 145v6_cleanup() 146{ 147 pft_cleanup 148} 149 150atf_test_case "noalias" "cleanup" 151noalias_head() 152{ 153 atf_set descr 'Test the :0 noalias option' 154 atf_set require.user root 155} 156 157noalias_body() 158{ 159 pft_init 160 161 epair=$(vnet_mkepair) 162 ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad 163 164 vnet_mkjail alcatraz ${epair}b 165 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad 166 167 linklocaladdr=$(jexec alcatraz ifconfig ${epair}b inet6 \ 168 | grep %${epair}b \ 169 | awk '{ print $2; }' \ 170 | cut -d % -f 1) 171 172 # Sanity check 173 atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2 174 atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a 175 176 jexec alcatraz pfctl -e 177 pft_set_rules alcatraz "block out inet6 from (${epair}b:0) to any" 178 179 atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2 180 181 # We should still be able to ping the link-local address 182 atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a 183 184 pft_set_rules alcatraz "block out inet6 from (${epair}b) to any" 185 186 # We cannot ping to the link-local address 187 atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a 188} 189 190noalias_cleanup() 191{ 192 pft_cleanup 193} 194 195atf_test_case "nested_inline" "cleanup" 196nested_inline_head() 197{ 198 atf_set descr "Test nested inline anchors, PR196314" 199 atf_set require.user root 200} 201 202nested_inline_body() 203{ 204 pft_init 205 206 epair=$(vnet_mkepair) 207 ifconfig ${epair}a inet 192.0.2.1/24 up 208 209 vnet_mkjail alcatraz ${epair}b 210 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 211 212 jexec alcatraz pfctl -e 213 pft_set_rules alcatraz \ 214 "block in" \ 215 "anchor \"an1\" {" \ 216 "pass in quick proto tcp to port time" \ 217 "anchor \"an2\" {" \ 218 "pass in quick proto icmp" \ 219 "}" \ 220 "}" 221 222 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 223} 224 225nested_inline_cleanup() 226{ 227 pft_cleanup 228} 229 230atf_test_case "urpf" "cleanup" 231urpf_head() 232{ 233 atf_set descr "Test unicast reverse path forwarding check" 234 atf_set require.user root 235 atf_set require.progs python3 scapy 236} 237 238urpf_body() 239{ 240 pft_init 241 242 epair_one=$(vnet_mkepair) 243 epair_two=$(vnet_mkepair) 244 245 vnet_mkjail alcatraz ${epair_one}b ${epair_two}b 246 247 ifconfig ${epair_one}a 192.0.2.2/24 up 248 ifconfig ${epair_two}a 198.51.100.2/24 up 249 250 jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up 251 jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up 252 jexec alcatraz sysctl net.inet.ip.forwarding=1 253 254 # Sanity checks 255 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 256 atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 257 atf_check -s exit:0 ${common_dir}/pft_ping.py \ 258 --sendif ${epair_one}a \ 259 --to 192.0.2.1 \ 260 --fromaddr 198.51.100.2 \ 261 --replyif ${epair_two}a 262 atf_check -s exit:0 ${common_dir}/pft_ping.py \ 263 --sendif ${epair_two}a \ 264 --to 198.51.100.1 \ 265 --fromaddr 192.0.2.2 \ 266 --replyif ${epair_one}a 267 268 pft_set_rules alcatraz \ 269 "block quick from urpf-failed" \ 270 "set skip on lo" 271 jexec alcatraz pfctl -e 272 273 # Correct source still works 274 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 275 atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 276 277 # Unexpected source interface is blocked 278 atf_check -s exit:1 ${common_dir}/pft_ping.py \ 279 --sendif ${epair_one}a \ 280 --to 192.0.2.1 \ 281 --fromaddr 198.51.100.2 \ 282 --replyif ${epair_two}a 283 atf_check -s exit:1 ${common_dir}/pft_ping.py \ 284 --sendif ${epair_two}a \ 285 --to 198.51.100.1 \ 286 --fromaddr 192.0.2.2 \ 287 --replyif ${epair_one}a 288} 289 290urpf_cleanup() 291{ 292 pft_cleanup 293} 294 295atf_test_case "received_on" "cleanup" 296received_on_head() 297{ 298 atf_set descr 'Test received-on filtering' 299 atf_set require.user root 300} 301 302received_on_body() 303{ 304 pft_init 305 306 epair_one=$(vnet_mkepair) 307 epair_two=$(vnet_mkepair) 308 epair_route=$(vnet_mkepair) 309 310 vnet_mkjail alcatraz ${epair_one}b ${epair_two}b ${epair_route}a 311 vnet_mkjail srv ${epair_route}b 312 313 ifconfig ${epair_one}a 192.0.2.2/24 up 314 ifconfig ${epair_two}a 198.51.100.2/24 up 315 route add 203.0.113.2 192.0.2.1 316 route add 203.0.113.3 198.51.100.1 317 318 jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up 319 jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up 320 jexec alcatraz ifconfig ${epair_route}a 203.0.113.1/24 up 321 jexec alcatraz sysctl net.inet.ip.forwarding=1 322 323 jexec srv ifconfig ${epair_route}b 203.0.113.2/24 up 324 jexec srv ifconfig ${epair_route}b inet alias 203.0.113.3/24 up 325 jexec srv route add default 203.0.113.1 326 327 # Sanity checks 328 atf_check -s exit:0 -o ignore \ 329 ping -c 1 192.0.2.1 330 atf_check -s exit:0 -o ignore \ 331 ping -c 1 198.51.100.1 332 atf_check -s exit:0 -o ignore \ 333 ping -c 1 203.0.113.2 334 atf_check -s exit:0 -o ignore \ 335 ping -c 1 203.0.113.3 336 337 jexec alcatraz pfctl -e 338 pft_set_rules alcatraz \ 339 "block in" \ 340 "pass received-on ${epair_one}b" 341 342 atf_check -s exit:0 -o ignore \ 343 ping -c 1 192.0.2.1 344 atf_check -s exit:2 -o ignore \ 345 ping -c 1 198.51.100.1 346 347 # And ensure we can check the received-on interface after routing 348 atf_check -s exit:0 -o ignore \ 349 ping -c 1 203.0.113.2 350 atf_check -s exit:2 -o ignore \ 351 ping -c 1 203.0.113.3 352 353 # Now try this with a group instead 354 jexec alcatraz ifconfig ${epair_one}b group test 355 pft_set_rules alcatraz \ 356 "block in" \ 357 "pass received-on test" 358 359 atf_check -s exit:0 -o ignore \ 360 ping -c 1 192.0.2.1 361 atf_check -s exit:2 -o ignore \ 362 ping -c 1 198.51.100.1 363 364 # And ensure we can check the received-on interface after routing 365 atf_check -s exit:0 -o ignore \ 366 ping -c 1 203.0.113.2 367 atf_check -s exit:2 -o ignore \ 368 ping -c 1 203.0.113.3 369 370 # Test '! received-on' 371 pft_set_rules alcatraz \ 372 "pass in" \ 373 "block ! received-on ${epair_one}b" 374 375 atf_check -s exit:0 -o ignore \ 376 ping -c 1 192.0.2.1 377 atf_check -s exit:2 -o ignore \ 378 ping -c 1 198.51.100.1 379} 380 381received_on_cleanup() 382{ 383 pft_cleanup 384} 385 386atf_test_case "optimize_any" "cleanup" 387optimize_any_head() 388{ 389 atf_set descr 'Test known optimizer bug' 390 atf_set require.user root 391} 392 393optimize_any_body() 394{ 395 pft_init 396 397 epair=$(vnet_mkepair) 398 399 vnet_mkjail alcatraz ${epair}a 400 401 ifconfig ${epair}b 192.0.2.2/24 up 402 403 jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up 404 405 # Sanity check 406 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 407 408 jexec alcatraz pfctl -e 409 pft_set_rules alcatraz \ 410 "block" \ 411 "pass in inet from { any, 192.0.2.3 }" 412 413 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 414} 415 416optimize_any_cleanup() 417{ 418 pft_cleanup 419} 420 421atf_test_case "any_if" "cleanup" 422any_if_head() 423{ 424 atf_set descr 'Test the any interface keyword' 425 atf_set require.user root 426} 427 428any_if_body() 429{ 430 pft_init 431 432 epair=$(vnet_mkepair) 433 ifconfig ${epair}b 192.0.2.2/24 up 434 435 vnet_mkjail alcatraz ${epair}a 436 jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up 437 438 # Sanity check 439 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 440 441 jexec alcatraz pfctl -e 442 pft_set_rules alcatraz \ 443 "block" \ 444 "pass in on any" 445 446 atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 447} 448 449any_if_cleanup() 450{ 451 pft_cleanup 452} 453 454atf_init_test_cases() 455{ 456 atf_add_test_case "enable_disable" 457 atf_add_test_case "v4" 458 atf_add_test_case "v6" 459 atf_add_test_case "noalias" 460 atf_add_test_case "nested_inline" 461 atf_add_test_case "urpf" 462 atf_add_test_case "received_on" 463 atf_add_test_case "optimize_any" 464 atf_add_test_case "any_if" 465} 466