1# $FreeBSD$ 2# 3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4# 5# Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27 28. $(atf_get_srcdir)/utils.subr 29 30common_dir=$(atf_get_srcdir)/../common 31 32atf_test_case "v4" "cleanup" 33v4_head() 34{ 35 atf_set descr 'Test killing states by IPv4 address' 36 atf_set require.user root 37 atf_set require.progs scapy 38} 39 40v4_body() 41{ 42 pft_init 43 44 epair=$(vnet_mkepair) 45 ifconfig ${epair}a 192.0.2.1/24 up 46 47 vnet_mkjail alcatraz ${epair}b 48 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 49 jexec alcatraz pfctl -e 50 51 pft_set_rules alcatraz "block all" \ 52 "pass in proto icmp" 53 54 # Sanity check & establish state 55 # Note: use pft_ping so we always use the same ID, so pf considers all 56 # echo requests part of the same flow. 57 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 58 --sendif ${epair}a \ 59 --to 192.0.2.2 \ 60 --replyif ${epair}a 61 62 # Change rules to now deny the ICMP traffic 63 pft_set_rules noflush alcatraz "block all" 64 65 # Established state means we can still ping alcatraz 66 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 67 --sendif ${epair}a \ 68 --to 192.0.2.2 \ 69 --replyif ${epair}a 70 71 # Killing with the wrong IP doesn't affect our state 72 jexec alcatraz pfctl -k 192.0.2.3 73 74 # So we can still ping 75 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 76 --sendif ${epair}a \ 77 --to 192.0.2.2 \ 78 --replyif ${epair}a 79 80 # Killing with one correct address and one incorrect doesn't kill the state 81 jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.3 82 83 # So we can still ping 84 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 85 --sendif ${epair}a \ 86 --to 192.0.2.2 \ 87 --replyif ${epair}a 88 89 # Killing with correct address does remove the state 90 jexec alcatraz pfctl -k 192.0.2.1 91 92 # Now the ping fails 93 atf_check -s exit:1 -o ignore ${common_dir}/pft_ping.py \ 94 --sendif ${epair}a \ 95 --to 192.0.2.2 \ 96 --replyif ${epair}a 97} 98 99v4_cleanup() 100{ 101 pft_cleanup 102} 103 104atf_test_case "v6" "cleanup" 105v6_head() 106{ 107 atf_set descr 'Test killing states by IPv6 address' 108 atf_set require.user root 109 atf_set require.progs scapy 110} 111 112v6_body() 113{ 114 pft_init 115 116 epair=$(vnet_mkepair) 117 ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad 118 119 vnet_mkjail alcatraz ${epair}b 120 jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad 121 jexec alcatraz pfctl -e 122 123 pft_set_rules alcatraz "block all" \ 124 "pass in proto icmp6" 125 126 # Sanity check & establish state 127 # Note: use pft_ping so we always use the same ID, so pf considers all 128 # echo requests part of the same flow. 129 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 130 --ip6 \ 131 --sendif ${epair}a \ 132 --to 2001:db8::2 \ 133 --replyif ${epair}a 134 135 # Change rules to now deny the ICMP traffic 136 pft_set_rules noflush alcatraz "block all" 137 138 # Established state means we can still ping alcatraz 139 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 140 --ip6 \ 141 --sendif ${epair}a \ 142 --to 2001:db8::2 \ 143 --replyif ${epair}a 144 145 # Killing with the wrong IP doesn't affect our state 146 jexec alcatraz pfctl -k 2001:db8::3 147 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 148 --ip6 \ 149 --sendif ${epair}a \ 150 --to 2001:db8::2 \ 151 --replyif ${epair}a 152 153 # Killing with one correct address and one incorrect doesn't kill the state 154 jexec alcatraz pfctl -k 2001:db8::1 -k 2001:db8::3 155 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 156 --ip6 \ 157 --sendif ${epair}a \ 158 --to 2001:db8::2 \ 159 --replyif ${epair}a 160 161 # Killing with correct address does remove the state 162 jexec alcatraz pfctl -k 2001:db8::1 163 atf_check -s exit:1 -o ignore ${common_dir}/pft_ping.py \ 164 --ip6 \ 165 --sendif ${epair}a \ 166 --to 2001:db8::2 \ 167 --replyif ${epair}a 168 169} 170 171v6_cleanup() 172{ 173 pft_cleanup 174} 175 176atf_test_case "label" "cleanup" 177label_head() 178{ 179 atf_set descr 'Test killing states by label' 180 atf_set require.user root 181 atf_set require.progs scapy 182} 183 184label_body() 185{ 186 pft_init 187 188 epair=$(vnet_mkepair) 189 ifconfig ${epair}a 192.0.2.1/24 up 190 191 vnet_mkjail alcatraz ${epair}b 192 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 193 jexec alcatraz pfctl -e 194 195 pft_set_rules alcatraz "block all" \ 196 "pass in proto tcp label bar" \ 197 "pass in proto icmp label foo" 198 199 # Sanity check & establish state 200 # Note: use pft_ping so we always use the same ID, so pf considers all 201 # echo requests part of the same flow. 202 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 203 --sendif ${epair}a \ 204 --to 192.0.2.2 \ 205 --replyif ${epair}a 206 207 # Change rules to now deny the ICMP traffic 208 pft_set_rules noflush alcatraz "block all" 209 210 # Established state means we can still ping alcatraz 211 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 212 --sendif ${epair}a \ 213 --to 192.0.2.2 \ 214 --replyif ${epair}a 215 216 # Killing a label on a different rules keeps the state 217 jexec alcatraz pfctl -k label -k bar 218 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 219 --sendif ${epair}a \ 220 --to 192.0.2.2 \ 221 --replyif ${epair}a 222 223 # Killing a non-existing label keeps the state 224 jexec alcatraz pfctl -k label -k baz 225 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 226 --sendif ${epair}a \ 227 --to 192.0.2.2 \ 228 --replyif ${epair}a 229 230 # Killing the correct label kills the state 231 jexec alcatraz pfctl -k label -k foo 232 atf_check -s exit:1 -o ignore ${common_dir}/pft_ping.py \ 233 --sendif ${epair}a \ 234 --to 192.0.2.2 \ 235 --replyif ${epair}a 236} 237 238label_cleanup() 239{ 240 pft_cleanup 241} 242 243atf_test_case "multilabel" "cleanup" 244multilabel_head() 245{ 246 atf_set descr 'Test killing states with multiple labels by label' 247 atf_set require.user root 248 atf_set require.progs scapy 249} 250 251multilabel_body() 252{ 253 pft_init 254 255 epair=$(vnet_mkepair) 256 ifconfig ${epair}a 192.0.2.1/24 up 257 258 vnet_mkjail alcatraz ${epair}b 259 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 260 jexec alcatraz pfctl -e 261 262 pft_set_rules alcatraz "block all" \ 263 "pass in proto icmp label foo label bar" 264 265 # Sanity check & establish state 266 # Note: use pft_ping so we always use the same ID, so pf considers all 267 # echo requests part of the same flow. 268 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 269 --sendif ${epair}a \ 270 --to 192.0.2.2 \ 271 --replyif ${epair}a 272 273 # Change rules to now deny the ICMP traffic 274 pft_set_rules noflush alcatraz "block all" 275 276 # Established state means we can still ping alcatraz 277 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 278 --sendif ${epair}a \ 279 --to 192.0.2.2 \ 280 --replyif ${epair}a 281 282 # Killing a label on a different rules keeps the state 283 jexec alcatraz pfctl -k label -k baz 284 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 285 --sendif ${epair}a \ 286 --to 192.0.2.2 \ 287 --replyif ${epair}a 288 289 # Killing the state with the last label works 290 jexec alcatraz pfctl -k label -k bar 291 atf_check -s exit:1 -o ignore ${common_dir}/pft_ping.py \ 292 --sendif ${epair}a \ 293 --to 192.0.2.2 \ 294 --replyif ${epair}a 295 296 pft_set_rules alcatraz "block all" \ 297 "pass in proto icmp label foo label bar" 298 299 # Reestablish state 300 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 301 --sendif ${epair}a \ 302 --to 192.0.2.2 \ 303 --replyif ${epair}a 304 305 # Change rules to now deny the ICMP traffic 306 pft_set_rules noflush alcatraz "block all" 307 308 # Killing with the first label works too 309 jexec alcatraz pfctl -k label -k foo 310 atf_check -s exit:1 -o ignore ${common_dir}/pft_ping.py \ 311 --sendif ${epair}a \ 312 --to 192.0.2.2 \ 313 --replyif ${epair}a 314} 315 316multilabel_cleanup() 317{ 318 pft_cleanup 319} 320 321atf_init_test_cases() 322{ 323 atf_add_test_case "v4" 324 atf_add_test_case "v6" 325 atf_add_test_case "label" 326 atf_add_test_case "multilabel" 327} 328