diff --git a/sbin/pfctl/tests/files/pf1022.in b/sbin/pfctl/tests/files/pf1022.in new file mode 100644 index 000000000000..640eb1334100 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1022.in @@ -0,0 +1 @@ +pass out on em0 from 192.0.2.1 to 198.51.100.1 received-on fxp0 diff --git a/sbin/pfctl/tests/files/pf1022.ok b/sbin/pfctl/tests/files/pf1022.ok new file mode 100644 index 000000000000..2f7b4a5bd616 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1022.ok @@ -0,0 +1 @@ +pass out on em0 inet from 192.0.2.1 to 198.51.100.1 received-on fxp0 flags S/SA keep state diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc index 1fd31de6ccc4..0ab336ec100d 100644 --- a/sbin/pfctl/tests/pfctl_test_list.inc +++ b/sbin/pfctl/tests/pfctl_test_list.inc @@ -1,132 +1,133 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright 2020 Alex Richardson * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory (Department of Computer Science and * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the * DARPA SSITH research programme. * * This work was supported by Innovate UK project 105694, "Digital Security by * Design (DSbD) Technology Platform Prototype". * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * No include guards since this file is included multiple times by pfctl_test * to avoid duplicating code. */ PFCTL_TEST(0001, "Pass with labels") PFCTL_TEST(0002, "Block/pass") PFCTL_TEST(0003, "Block/pass with flags") PFCTL_TEST(0004, "Block") PFCTL_TEST(0005, "Block with variables") PFCTL_TEST(0006, "Variables") PFCTL_TEST(0007, "Block/pass with return") PFCTL_TEST(0008, "Block with address list") PFCTL_TEST(0009, "Block with interface list") PFCTL_TEST(0010, "Block/pass with return") PFCTL_TEST(0011, "Block/pass ICMP") PFCTL_TEST(0012, "Pass to subnets") PFCTL_TEST(0013, "Pass quick") PFCTL_TEST(0014, "Pass quick IPv6") PFCTL_TEST(0016, "Pass with no state") PFCTL_TEST(0018, "Address lists") PFCTL_TEST(0019, "Lists") PFCTL_TEST(0020, "Lists") PFCTL_TEST(0022, "Set options") PFCTL_TEST(0023, "Block on negated interface") PFCTL_TEST(0024, "Variable concatenation") PFCTL_TEST(0025, "Antispoof") PFCTL_TEST(0026, "Block from negated interface") PFCTL_TEST(0028, "Block with log and quick") PFCTL_TEST(0030, "Line continuation") PFCTL_TEST(0031, "Block policy") PFCTL_TEST(0032, "Pass to any") PFCTL_TEST(0034, "Pass with probability") PFCTL_TEST(0035, "Matching on TOS") PFCTL_TEST(0038, "Pass with user") PFCTL_TEST(0039, "Ordered opts") PFCTL_TEST(0040, "Block/pass") PFCTL_TEST(0041, "Anchors") PFCTL_TEST(0047, "Pass with labels") PFCTL_TEST(0048, "Tables") PFCTL_TEST(0049, "Broadcast and network modifiers") PFCTL_TEST(0050, "Double macro set") PFCTL_TEST(0052, "Set optimization") PFCTL_TEST(0053, "Pass with labels") PFCTL_TEST(0055, "Set options") PFCTL_TEST(0056, "State opts") PFCTL_TEST(0057, "Variables") PFCTL_TEST(0060, "Pass from multicast") PFCTL_TEST(0061, "Dynaddr with netmask") PFCTL_TEST(0065, "Antispoof with labels") PFCTL_TEST(0067, "Tags") PFCTL_TEST(0069, "Tags") PFCTL_TEST(0070, "Tags") PFCTL_TEST(0071, "Tags") PFCTL_TEST(0072, "Tags") PFCTL_TEST(0074, "Synproxy") PFCTL_TEST(0075, "Block quick with tags") PFCTL_TEST(0077, "Dynaddr with netmask") PFCTL_TEST(0078, "Table with label") PFCTL_TEST(0079, "No-route with label") PFCTL_TEST(0081, "Address list and table list with no-route") PFCTL_TEST(0082, "Pass with interface, table and no-route") PFCTL_TEST(0084, "Source track") PFCTL_TEST(0085, "Tag macro expansion") PFCTL_TEST(0087, "Optimization rule reordering") PFCTL_TEST(0088, "Optimization duplicate rules handling") PFCTL_TEST(0089, "TCP connection tracking") PFCTL_TEST(0090, "Log opts") PFCTL_TEST(0091, "Nested anchors") PFCTL_TEST(0092, "Comments") PFCTL_TEST(0094, "Address ranges") PFCTL_TEST(0095, "Include") PFCTL_TEST(0096, "Variables") PFCTL_TEST(0097, "Divert-to") PFCTL_TEST(0098, "Pass") PFCTL_TEST(0100, "Anchor with multiple path components") PFCTL_TEST(0101, "Prio") PFCTL_TEST(0102, "Address lists with mixed address family") PFCTL_TEST(0104, "Divert-to with localhost") PFCTL_TEST(1001, "Binat") PFCTL_TEST(1002, "Set timeout interval") PFCTL_TEST(1003, "ALTQ") PFCTL_TEST(1004, "ALTQ with Codel") PFCTL_TEST(1005, "PR 231323") PFCTL_TEST(1006, "pfctl crashes with certain fairq configurations") PFCTL_TEST(1007, "Basic ethernet rule") PFCTL_TEST(1008, "Ethernet rule with mask length") PFCTL_TEST(1009, "Ethernet rule with mask") PFCTL_TEST(1010, "POM_STICKYADDRESS test") PFCTL_TEST(1011, "Test disabling scrub fragment reassemble") PFCTL_TEST(1012, "Test scrub fragment reassemble is default") PFCTL_TEST(1013, "Ethernet rule with ridentifier") PFCTL_TEST(1014, "Ethernet rule with one label") PFCTL_TEST(1015, "Ethernet rule with several labels") PFCTL_TEST(1016, "Ethernet rule with ridentifier and one label") PFCTL_TEST(1017, "Ethernet rule with ridentifier and several labels") PFCTL_TEST(1018, "Test dynamic address mask") PFCTL_TEST(1019, "Test pflow option") PFCTL_TEST(1020, "Test hashmark and semicolon comment") PFCTL_TEST(1021, "Endpoint-independent") +PFCTL_TEST(1022, "Test received-on") diff --git a/tests/sys/netpfil/pf/pass_block.sh b/tests/sys/netpfil/pf/pass_block.sh index faf5c2de4de2..36218d8e673f 100644 --- a/tests/sys/netpfil/pf/pass_block.sh +++ b/tests/sys/netpfil/pf/pass_block.sh @@ -1,303 +1,385 @@ # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Kristof Provost # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. . $(atf_get_srcdir)/utils.subr common_dir=$(atf_get_srcdir)/../common atf_test_case "enable_disable" "cleanup" enable_disable_head() { atf_set descr 'Test enable/disable' atf_set require.user root } enable_disable_body() { pft_init j="pass_block:enable_disable" vnet_mkjail ${j} # Disable when disabled fails atf_check -s exit:1 -e ignore \ jexec ${j} pfctl -d # Enable succeeds atf_check -s exit:0 -e ignore \ jexec ${j} pfctl -e # Enable when enabled fails atf_check -s exit:1 -e ignore \ jexec ${j} pfctl -e # Disable succeeds atf_check -s exit:0 -e ignore \ jexec ${j} pfctl -d } enable_disable_cleanup() { pft_cleanup } atf_test_case "v4" "cleanup" v4_head() { atf_set descr 'Basic pass/block test for IPv4' atf_set require.user root } v4_body() { pft_init epair=$(vnet_mkepair) ifconfig ${epair}a 192.0.2.1/24 up # Set up a simple jail with one interface vnet_mkjail alcatraz ${epair}b jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up # Trivial ping to the jail, without pf atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 # pf without policy will let us ping jexec alcatraz pfctl -e atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 # Block everything pft_set_rules alcatraz "block in" atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2 # Block everything but ICMP pft_set_rules alcatraz "block in" "pass in proto icmp" atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 } v4_cleanup() { pft_cleanup } atf_test_case "v6" "cleanup" v6_head() { atf_set descr 'Basic pass/block test for IPv6' atf_set require.user root } v6_body() { pft_init epair=$(vnet_mkepair) ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad # Set up a simple jail with one interface vnet_mkjail alcatraz ${epair}b jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad # Trivial ping to the jail, without pf atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 # pf without policy will let us ping jexec alcatraz pfctl -e atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 # Block everything pft_set_rules alcatraz "block in" atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 # Block everything but ICMP pft_set_rules alcatraz "block in" "pass in proto icmp6" atf_check -s exit:0 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 # Allowing ICMPv4 does not allow ICMPv6 pft_set_rules alcatraz "block in" "pass in proto icmp" atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:42::2 } v6_cleanup() { pft_cleanup } atf_test_case "noalias" "cleanup" noalias_head() { atf_set descr 'Test the :0 noalias option' atf_set require.user root } noalias_body() { pft_init epair=$(vnet_mkepair) ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad vnet_mkjail alcatraz ${epair}b jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad linklocaladdr=$(jexec alcatraz ifconfig ${epair}b inet6 \ | grep %${epair}b \ | awk '{ print $2; }' \ | cut -d % -f 1) # Sanity check atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2 atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a jexec alcatraz pfctl -e pft_set_rules alcatraz "block out inet6 from (${epair}b:0) to any" atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 2001:db8:42::2 # We should still be able to ping the link-local address atf_check -s exit:0 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a pft_set_rules alcatraz "block out inet6 from (${epair}b) to any" # We cannot ping to the link-local address atf_check -s exit:2 -o ignore ping -6 -c 3 -W 1 ${linklocaladdr}%${epair}a } noalias_cleanup() { pft_cleanup } atf_test_case "nested_inline" "cleanup" nested_inline_head() { atf_set descr "Test nested inline anchors, PR196314" atf_set require.user root } nested_inline_body() { pft_init epair=$(vnet_mkepair) ifconfig ${epair}a inet 192.0.2.1/24 up vnet_mkjail alcatraz ${epair}b jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up jexec alcatraz pfctl -e pft_set_rules alcatraz \ "block in" \ "anchor \"an1\" {" \ "pass in quick proto tcp to port time" \ "anchor \"an2\" {" \ "pass in quick proto icmp" \ "}" \ "}" atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2 } nested_inline_cleanup() { pft_cleanup } atf_test_case "urpf" "cleanup" urpf_head() { atf_set descr "Test unicast reverse path forwarding check" atf_set require.user root atf_set require.progs scapy } urpf_body() { pft_init epair_one=$(vnet_mkepair) epair_two=$(vnet_mkepair) vnet_mkjail alcatraz ${epair_one}b ${epair_two}b ifconfig ${epair_one}a 192.0.2.2/24 up ifconfig ${epair_two}a 198.51.100.2/24 up jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up jexec alcatraz sysctl net.inet.ip.forwarding=1 # Sanity checks atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 atf_check -s exit:0 ${common_dir}/pft_ping.py \ --sendif ${epair_one}a \ --to 192.0.2.1 \ --fromaddr 198.51.100.2 \ --replyif ${epair_two}a atf_check -s exit:0 ${common_dir}/pft_ping.py \ --sendif ${epair_two}a \ --to 198.51.100.1 \ --fromaddr 192.0.2.2 \ --replyif ${epair_one}a pft_set_rules alcatraz \ "block quick from urpf-failed" \ "set skip on lo" jexec alcatraz pfctl -e # Correct source still works atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1 atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1 # Unexpected source interface is blocked atf_check -s exit:1 ${common_dir}/pft_ping.py \ --sendif ${epair_one}a \ --to 192.0.2.1 \ --fromaddr 198.51.100.2 \ --replyif ${epair_two}a atf_check -s exit:1 ${common_dir}/pft_ping.py \ --sendif ${epair_two}a \ --to 198.51.100.1 \ --fromaddr 192.0.2.2 \ --replyif ${epair_one}a } urpf_cleanup() { pft_cleanup } +atf_test_case "received_on" "cleanup" +received_on_head() +{ + atf_set descr 'Test received-on filtering' + atf_set require.user root +} + +received_on_body() +{ + pft_init + + epair_one=$(vnet_mkepair) + epair_two=$(vnet_mkepair) + epair_route=$(vnet_mkepair) + + vnet_mkjail alcatraz ${epair_one}b ${epair_two}b ${epair_route}a + vnet_mkjail srv ${epair_route}b + + ifconfig ${epair_one}a 192.0.2.2/24 up + ifconfig ${epair_two}a 198.51.100.2/24 up + route add 203.0.113.2 192.0.2.1 + route add 203.0.113.3 198.51.100.1 + + jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up + jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up + jexec alcatraz ifconfig ${epair_route}a 203.0.113.1/24 up + jexec alcatraz sysctl net.inet.ip.forwarding=1 + + jexec srv ifconfig ${epair_route}b 203.0.113.2/24 up + jexec srv ifconfig ${epair_route}b inet alias 203.0.113.3/24 up + jexec srv route add default 203.0.113.1 + + # Sanity checks + atf_check -s exit:0 -o ignore \ + ping -c 1 192.0.2.1 + atf_check -s exit:0 -o ignore \ + ping -c 1 198.51.100.1 + atf_check -s exit:0 -o ignore \ + ping -c 1 203.0.113.2 + atf_check -s exit:0 -o ignore \ + ping -c 1 203.0.113.3 + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "block in" \ + "pass received-on ${epair_one}b" + + atf_check -s exit:0 -o ignore \ + ping -c 1 192.0.2.1 + atf_check -s exit:2 -o ignore \ + ping -c 1 198.51.100.1 + + # And ensure we can check the received-on interface after routing + atf_check -s exit:0 -o ignore \ + ping -c 1 203.0.113.2 + atf_check -s exit:2 -o ignore \ + ping -c 1 203.0.113.3 + + # Now try this with a group instead + jexec alcatraz ifconfig ${epair_one}b group test + pft_set_rules alcatraz \ + "block in" \ + "pass received-on test" + + atf_check -s exit:0 -o ignore \ + ping -c 1 192.0.2.1 + atf_check -s exit:2 -o ignore \ + ping -c 1 198.51.100.1 + + # And ensure we can check the received-on interface after routing + atf_check -s exit:0 -o ignore \ + ping -c 1 203.0.113.2 + atf_check -s exit:2 -o ignore \ + ping -c 1 203.0.113.3 +} + +received_on_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "enable_disable" atf_add_test_case "v4" atf_add_test_case "v6" atf_add_test_case "noalias" atf_add_test_case "nested_inline" atf_add_test_case "urpf" + atf_add_test_case "received_on" }