diff options
Diffstat (limited to 'tests/sys/netpfil')
| -rw-r--r-- | tests/sys/netpfil/pf/Makefile | 2 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/ioctl/validation.c | 58 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/nat.sh | 47 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/proxy.sh | 61 | ||||
| -rwxr-xr-x | tests/sys/netpfil/pf/src_track.sh | 74 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/table.sh | 62 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/tftpd_inetd.conf | 28 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/tftpd_proxy_inetd.conf | 27 |
8 files changed, 353 insertions, 6 deletions
diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile index b363e0b17c76..9416f6abbdf1 100644 --- a/tests/sys/netpfil/pf/Makefile +++ b/tests/sys/netpfil/pf/Makefile @@ -90,6 +90,8 @@ ${PACKAGE}FILES+= \ pft_ether.py \ pft_read_ipfix.py \ rdr-srcport.py \ + tftpd_inetd.conf \ + tftpd_proxy_inetd.conf \ utils.subr \ utils.py diff --git a/tests/sys/netpfil/pf/ioctl/validation.c b/tests/sys/netpfil/pf/ioctl/validation.c index 3e03163cc752..bb060e22f3a0 100644 --- a/tests/sys/netpfil/pf/ioctl/validation.c +++ b/tests/sys/netpfil/pf/ioctl/validation.c @@ -194,6 +194,38 @@ ATF_TC_CLEANUP(gettables, tc) COMMON_CLEANUP(); } +ATF_TC_WITH_CLEANUP(clrtables); +ATF_TC_HEAD(clrtables, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.kmods", "pf"); +} + +ATF_TC_BODY(clrtables, tc) +{ + struct pfioc_table io; + struct pfr_table tbl; + int flags; + + COMMON_HEAD(); + + flags = 0; + + memset(&io, '/', sizeof(io)); + io.pfrio_flags = flags; + io.pfrio_buffer = &tbl; + io.pfrio_esize = 0; + io.pfrio_size = 1; + + if (ioctl(dev, DIOCRCLRTABLES, &io) == 0) + atf_tc_fail("Request with unterminated anchor name succeeded"); +} + +ATF_TC_CLEANUP(clrtables, tc) +{ + COMMON_CLEANUP(); +} + ATF_TC_WITH_CLEANUP(gettstats); ATF_TC_HEAD(gettstats, tc) { @@ -949,11 +981,36 @@ ATF_TC_CLEANUP(natlook, tc) COMMON_CLEANUP(); } +ATF_TC_WITH_CLEANUP(addstate); +ATF_TC_HEAD(addstate, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.kmods", "pfsync"); +} + +ATF_TC_BODY(addstate, tc) +{ + struct pfioc_state st; + + COMMON_HEAD(); + + memset(&st, 'a', sizeof(st)); + st.state.timeout = PFTM_TCP_FIRST_PACKET; + + ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCADDSTATE, &st) == -1); +} + +ATF_TC_CLEANUP(addstate, tc) +{ + COMMON_CLEANUP(); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, addtables); ATF_TP_ADD_TC(tp, deltables); ATF_TP_ADD_TC(tp, gettables); + ATF_TP_ADD_TC(tp, clrtables); ATF_TP_ADD_TC(tp, getastats); ATF_TP_ADD_TC(tp, gettstats); ATF_TP_ADD_TC(tp, clrtstats); @@ -974,6 +1031,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, rpool_mtx); ATF_TP_ADD_TC(tp, rpool_mtx2); ATF_TP_ADD_TC(tp, natlook); + ATF_TP_ADD_TC(tp, addstate); return (atf_no_error()); } diff --git a/tests/sys/netpfil/pf/nat.sh b/tests/sys/netpfil/pf/nat.sh index 1ef87cee3598..0824671fa0f1 100644 --- a/tests/sys/netpfil/pf/nat.sh +++ b/tests/sys/netpfil/pf/nat.sh @@ -477,15 +477,49 @@ no_addrs_random_cleanup() pft_cleanup } -atf_test_case "nat_pass" "cleanup" -nat_pass_head() +atf_test_case "nat_pass_in" "cleanup" +nat_pass_in_head() { - atf_set descr 'IPv4 NAT on pass rule' + atf_set descr 'IPv4 NAT on inbound pass rule' atf_set require.user root atf_set require.progs scapy } -nat_pass_body() +nat_pass_in_body() +{ + setup_router_server_ipv4 + # Delete the route back to make sure that the traffic has been NAT-ed + jexec server route del -net ${net_tester} ${net_server_host_router} + # Provide routing back to the NAT address + jexec server route add 203.0.113.0/24 ${net_server_host_router} + jexec router route add 203.0.113.0/24 -iface ${epair_tester}b + + pft_set_rules router \ + "block" \ + "pass in on ${epair_tester}b inet proto tcp nat-to 203.0.113.0 keep state" \ + "pass out on ${epair_server}a inet proto tcp keep state" + + ping_server_check_reply exit:0 --ping-type=tcp3way --send-sport=4201 + + jexec router pfctl -qvvsr + jexec router pfctl -qvvss + jexec router ifconfig + jexec router netstat -rn +} + +nat_pass_in_cleanup() +{ + pft_cleanup +} + +nat_pass_out_head() +{ + atf_set descr 'IPv4 NAT on outbound pass rule' + atf_set require.user root + atf_set require.progs scapy +} + +nat_pass_out_body() { setup_router_server_ipv4 # Delete the route back to make sure that the traffic has been NAT-ed @@ -504,7 +538,7 @@ nat_pass_body() jexec router netstat -rn } -nat_pass_cleanup() +nat_pass_out_cleanup() { pft_cleanup } @@ -874,7 +908,8 @@ atf_init_test_cases() atf_add_test_case "no_addrs_random" atf_add_test_case "map_e_compat" atf_add_test_case "map_e_pass" - atf_add_test_case "nat_pass" + atf_add_test_case "nat_pass_in" + atf_add_test_case "nat_pass_out" atf_add_test_case "nat_match" atf_add_test_case "binat_compat" atf_add_test_case "binat_match" diff --git a/tests/sys/netpfil/pf/proxy.sh b/tests/sys/netpfil/pf/proxy.sh index 78ce25930c04..a07bb259b544 100644 --- a/tests/sys/netpfil/pf/proxy.sh +++ b/tests/sys/netpfil/pf/proxy.sh @@ -88,7 +88,68 @@ ftp_cleanup() pft_cleanup } +atf_test_case "tftp" "cleanup" +tftp_head() +{ + atf_set descr 'Test tftp-proxy' + atf_set require.user root +} + +tftp_body() +{ + pft_init + + epair_client=$(vnet_mkepair) + epair_link=$(vnet_mkepair) + + ifconfig ${epair_client}a 192.0.2.2/24 up + route add -net 198.51.100.0/24 192.0.2.1 + + vnet_mkjail fwd ${epair_client}b ${epair_link}a + jexec fwd ifconfig lo0 127.0.0.1/8 up + jexec fwd ifconfig ${epair_client}b 192.0.2.1/24 up + jexec fwd ifconfig ${epair_link}a 198.51.100.1/24 up + jexec fwd ifconfig lo0 127.0.0.1/8 up + jexec fwd sysctl net.inet.ip.forwarding=1 + + vnet_mkjail srv ${epair_link}b + jexec srv ifconfig ${epair_link}b 198.51.100.2/24 up + jexec srv route add default 198.51.100.1 + + # Start tftp server in srv + jexec srv /usr/sbin/inetd -p ${PWD}/inetd-srv.pid \ + $(atf_get_srcdir)/tftpd_inetd.conf + + jexec fwd /usr/sbin/inetd -p ${PWD}/inetd-fwd.pid \ + $(atf_get_srcdir)/tftpd_proxy_inetd.conf + + jexec fwd pfctl -e + pft_set_rules fwd \ + "nat on ${epair_link}a inet from 192.0.2.0/24 to any -> (${epair_link}a)" \ + "nat-anchor \"tftp-proxy/*\"" \ + "rdr-anchor \"tftp-proxy/*\"" \ + "rdr pass on ${epair_client}b proto udp from 192.0.2.0/24 to any port 69 -> 127.0.0.1 port 69" \ + "anchor \"tftp-proxy/*\"" \ + "pass out proto udp from 127.0.0.1 to any port 69" + + # Create a dummy file to download + echo 'foo' > /tmp/remote.txt + echo 'get remote.txt local.txt' | tftp 198.51.100.2 + + # Compare the downloaded file to the original + if ! diff -q local.txt /tmp/remote.txt; + then + atf_fail 'Failed to retrieve file' + fi +} + +tftp_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "ftp" + atf_add_test_case "tftp" } diff --git a/tests/sys/netpfil/pf/src_track.sh b/tests/sys/netpfil/pf/src_track.sh index d86b4ce6c466..1b09030f6174 100755 --- a/tests/sys/netpfil/pf/src_track.sh +++ b/tests/sys/netpfil/pf/src_track.sh @@ -588,6 +588,79 @@ mixed_af_cleanup() pft_cleanup } +atf_test_case "check_valid" "cleanup" +check_valid_head() +{ + atf_set descr 'Test if source node is invalidated on change in redirection pool' + atf_set require.user root + atf_set require.progs python3 scapy +} + +check_valid_body() +{ + setup_router_server_nat64 + + # Clients will connect from another network behind the router. + # This allows for using multiple source addresses. + jexec router route add -6 ${net_clients_6}::/${net_clients_6_mask} ${net_tester_6_host_tester} + + jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6}::42:1/128 alias + jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6}::42:2/128 alias + + jexec router pfctl -e + pft_set_rules router \ + "set debug loud " \ + "set state-policy if-bound" \ + "table <targets> { ${net_server1_6}::42:1 }" \ + "pass in on ${epair_tester}b \ + route-to { (${epair_server1}a <targets>) } \ + sticky-address \ + proto tcp \ + keep state" + + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_tester}a --replyif ${epair_tester}a \ + --fromaddr ${net_clients_6}::1 --to ${host_server_6} \ + --ping-type=tcp3way --send-sport=4201 + + # A source node is created using the original redirection target + nodes=$(mktemp) || exit 1 + jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes + node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:1 .* states 1,.* route sticky-address' + grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" + + # Change contents of the redirection table + echo ${net_server1_6}::42:2 | jexec router pfctl -Tr -t targets -f - + + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_tester}a --replyif ${epair_tester}a \ + --fromaddr ${net_clients_6}::1 --to ${host_server_6} \ + --ping-type=tcp3way --send-sport=4202 + + # The original source node was deleted, a new one was created. + # It has 1 states. + jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes + node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:2 .* states 1,.* route sticky-address' + grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" + + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair_tester}a --replyif ${epair_tester}a \ + --fromaddr ${net_clients_6}::1 --to ${host_server_6} \ + --ping-type=tcp3way --send-sport=4203 + + # Without redirection table change the source node is reused. + # It has 2 states. + jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes + node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:2 .* states 2,.* route sticky-address' + grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" +} + +check_valid_cleanup() +{ + pft_cleanup +} + + atf_init_test_cases() { atf_add_test_case "source_track" @@ -598,4 +671,5 @@ atf_init_test_cases() atf_add_test_case "sn_types_compat" atf_add_test_case "sn_types_pass" atf_add_test_case "mixed_af" + atf_add_test_case "check_valid" } diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index 69fe12fc9804..6761ce652beb 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -747,6 +747,67 @@ in_anchor_cleanup() pft_cleanup } +atf_test_case "replace" "cleanup" +replace_head() +{ + atf_set descr 'Test table replace command' + atf_set require.user root +} + +replace_body() +{ + pft_init + pwd=$(pwd) + + epair_send=$(vnet_mkepair) + ifconfig ${epair_send}a 192.0.2.1/24 up + + vnet_mkjail alcatraz ${epair_send}b + jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up + jexec alcatraz pfctl -e + + pft_set_rules alcatraz \ + "table <foo> counters { 192.0.2.1 }" \ + "block all" \ + "pass in from <foo> to any" \ + "pass out from any to <foo>" \ + "set skip on lo" + + atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 + + # Replace the address + atf_check -s exit:0 -e "match:1 addresses added." -e "match:1 addresses deleted." \ + jexec alcatraz pfctl -t foo -T replace 192.0.2.3 + atf_check -s exit:0 -o "match:192.0.2.3" \ + jexec alcatraz pfctl -t foo -T show + atf_check -s exit:2 -o ignore ping -c 3 192.0.2.2 + + # Negated address + atf_check -s exit:0 -e "match:1 addresses changed." \ + jexec alcatraz pfctl -t foo -T replace "!192.0.2.3" + + # Now add 500 addresses + for i in `seq 1 2`; do + for j in `seq 1 250`; do + echo "1.${i}.${j}.1" >> ${pwd}/foo.lst + done + done + atf_check -s exit:0 -e "match:500 addresses added." -e "match:1 addresses deleted." \ + jexec alcatraz pfctl -t foo -T replace -f ${pwd}/foo.lst + + atf_check -s exit:0 -o "not-match:192.0.2.3" \ + jexec alcatraz pfctl -t foo -T show + + # Loading the same list produces no changes. + atf_check -s exit:0 -e "match:no changes." \ + jexec alcatraz pfctl -t foo -T replace -f ${pwd}/foo.lst +} + +replace_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4_counters" @@ -765,4 +826,5 @@ atf_init_test_cases() atf_add_test_case "large" atf_add_test_case "show_recursive" atf_add_test_case "in_anchor" + atf_add_test_case "replace" } diff --git a/tests/sys/netpfil/pf/tftpd_inetd.conf b/tests/sys/netpfil/pf/tftpd_inetd.conf new file mode 100644 index 000000000000..3554d0a7fb08 --- /dev/null +++ b/tests/sys/netpfil/pf/tftpd_inetd.conf @@ -0,0 +1,28 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# 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. + +tftp dgram udp wait root /usr/libexec/tftpd tftpd -l -S -s /tmp +tftp dgram udp6 wait root /usr/libexec/tftpd tftpd -l -S -s /tmp diff --git a/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf b/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf new file mode 100644 index 000000000000..aa5f000f3bba --- /dev/null +++ b/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf @@ -0,0 +1,27 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# 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. + +tftp dgram udp wait root /usr/libexec/tftp-proxy tftp-proxy |
