diff --git a/UPDATING b/UPDATING index 1980411c1853..f4e13d97006d 100644 --- a/UPDATING +++ b/UPDATING @@ -27,6 +27,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 14.x IS SLOW: world, or to merely disable the most expensive debugging functionality at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20230619: + To enable pf rdr rules for connections initiated from the host, pf + filter rules can be optionally enabled for packets delivered + locally. This can change the behavior of rules which match packets + delivered to lo0. To enable this feature: + + sysctl net.pf.filter_local=1 + service pf restart + + When enabled, its best to ensure that packets delivered locally are not + filtered, e.g. by adding a 'skip on lo' rule. + 20230613: Improvements to libtacplus(8) mean that tacplus.conf(5) now follows POSIX shell syntax rules. This may cause TACACS+ diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index e76a92fb7e7f..b78c30aa4b8c 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -195,6 +195,12 @@ static MALLOC_DEFINE(M_PFRULE, "pf_rule", "pf(4) rules"); #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE #endif +VNET_DEFINE_STATIC(bool, pf_filter_local) = false; +#define V_pf_filter_local VNET(pf_filter_local) +SYSCTL_BOOL(_net_pf, OID_AUTO, filter_local, CTLFLAG_VNET | CTLFLAG_RW, + &VNET_NAME(pf_filter_local), false, + "Enable filtering for packets delivered to local network stack"); + static void pf_init_tagset(struct pf_tagset *, unsigned int *, unsigned int); static void pf_cleanup_tagset(struct pf_tagset *); @@ -6682,6 +6688,13 @@ hook_pf(void) pla.pa_hook = V_pf_ip4_out_hook; ret = pfil_link(&pla); MPASS(ret == 0); + if (V_pf_filter_local) { + pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR; + pla.pa_head = V_inet_local_pfil_head; + pla.pa_hook = V_pf_ip4_out_hook; + ret = pfil_link(&pla); + MPASS(ret == 0); + } #endif #ifdef INET6 pha.pa_type = PFIL_TYPE_IP6; @@ -6703,6 +6716,13 @@ hook_pf(void) pla.pa_hook = V_pf_ip6_out_hook; ret = pfil_link(&pla); MPASS(ret == 0); + if (V_pf_filter_local) { + pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR; + pla.pa_head = V_inet6_local_pfil_head; + pla.pa_hook = V_pf_ip6_out_hook; + ret = pfil_link(&pla); + MPASS(ret == 0); + } #endif atomic_store_bool(&V_pf_pfil_hooked, true); diff --git a/tests/sys/netpfil/common/utils.subr b/tests/sys/netpfil/common/utils.subr index f4eec24618a7..e354f6638b87 100644 --- a/tests/sys/netpfil/common/utils.subr +++ b/tests/sys/netpfil/common/utils.subr @@ -55,11 +55,10 @@ firewall_config() jexec ${jname} ipfw -q -f flush jexec ${jname} /bin/sh $cwd/ipfw.rule elif [ ${fw} == "pf" ]; then + jexec ${jname} sysctl net.pf.filter_local=1 jexec ${jname} pfctl -e jexec ${jname} pfctl -F all jexec ${jname} pfctl -f $cwd/pf.rule - jexec ${jname} pfilctl link -o pf:default-out inet-local - jexec ${jname} pfilctl link -o pf:default-out6 inet6-local elif [ ${fw} == "ipf" ]; then jexec ${jname} ipf -E jexec ${jname} ipf -Fa -f $cwd/ipf.rule diff --git a/tests/sys/netpfil/pf/fragmentation_compat.sh b/tests/sys/netpfil/pf/fragmentation_compat.sh index a783755e4592..3e559a216b54 100644 --- a/tests/sys/netpfil/pf/fragmentation_compat.sh +++ b/tests/sys/netpfil/pf/fragmentation_compat.sh @@ -112,7 +112,8 @@ v6_body() "scrub fragment reassemble" \ "block in" \ "pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ - "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" + "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" \ + "set skip on lo" # Host test atf_check -s exit:0 -o ignore \ diff --git a/tests/sys/netpfil/pf/fragmentation_pass.sh b/tests/sys/netpfil/pf/fragmentation_pass.sh index d257de730d2d..e2d28c307502 100644 --- a/tests/sys/netpfil/pf/fragmentation_pass.sh +++ b/tests/sys/netpfil/pf/fragmentation_pass.sh @@ -116,7 +116,8 @@ v6_body() "pass keep state" \ "block in" \ "pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \ - "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" + "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" \ + "set skip on lo" # Host test atf_check -s exit:0 -o ignore \ diff --git a/tests/sys/netpfil/pf/killstate.sh b/tests/sys/netpfil/pf/killstate.sh index 4263938e26be..cd4eeee05a10 100644 --- a/tests/sys/netpfil/pf/killstate.sh +++ b/tests/sys/netpfil/pf/killstate.sh @@ -60,7 +60,8 @@ v4_body() jexec alcatraz pfctl -e pft_set_rules alcatraz "block all" \ - "pass in proto icmp" + "pass in proto icmp" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -126,7 +127,8 @@ v6_body() jexec alcatraz pfctl -e pft_set_rules alcatraz "block all" \ - "pass in proto icmp6" + "pass in proto icmp6" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -189,7 +191,8 @@ label_body() pft_set_rules alcatraz "block all" \ "pass in proto tcp label bar" \ - "pass in proto icmp label foo" + "pass in proto icmp label foo" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -251,7 +254,8 @@ multilabel_body() jexec alcatraz pfctl -e pft_set_rules alcatraz "block all" \ - "pass in proto icmp label foo label bar" + "pass in proto icmp label foo label bar" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -281,7 +285,8 @@ multilabel_body() fi pft_set_rules alcatraz "block all" \ - "pass in proto icmp label foo label bar" + "pass in proto icmp label foo label bar" \ + "set skip on lo" # Reestablish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -329,7 +334,8 @@ gateway_body() jexec alcatraz pfctl -e pft_set_rules alcatraz "block all" \ - "pass in reply-to (${epair}b 192.0.2.1) proto icmp" + "pass in reply-to (${epair}b 192.0.2.1) proto icmp" \ + "set skip on lo" # Sanity check & establish state # Note: use pft_ping so we always use the same ID, so pf considers all @@ -469,7 +475,8 @@ interface_body() jexec alcatraz pfctl -e pft_set_rules alcatraz "block all" \ - "pass in proto icmp" + "pass in proto icmp" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ @@ -525,7 +532,8 @@ id_body() pft_set_rules alcatraz "block all" \ "pass in proto tcp" \ - "pass in proto icmp" + "pass in proto icmp" \ + "set skip on lo" # Sanity check & establish state atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ diff --git a/tests/sys/netpfil/pf/map_e.sh b/tests/sys/netpfil/pf/map_e.sh index ce0e567ae3c8..ea8ce33bf323 100644 --- a/tests/sys/netpfil/pf/map_e.sh +++ b/tests/sys/netpfil/pf/map_e.sh @@ -66,7 +66,8 @@ map_e_body() pft_set_rules echo "block return all" \ "pass in on ${epair_echo}b inet proto tcp from 198.51.100.1 port 19720:19723 to (${epair_echo}b) port 7" \ "pass in on ${epair_echo}b inet proto tcp from 198.51.100.1 port 36104:36107 to (${epair_echo}b) port 7" \ - "pass in on ${epair_echo}b inet proto tcp from 198.51.100.1 port 52488:52491 to (${epair_echo}b) port 7" + "pass in on ${epair_echo}b inet proto tcp from 198.51.100.1 port 52488:52491 to (${epair_echo}b) port 7" \ + "set skip on lo" i=0 while [ ${i} -lt ${NC_TRY_COUNT} ] diff --git a/tests/sys/netpfil/pf/pass_block.sh b/tests/sys/netpfil/pf/pass_block.sh index 0f034b23a730..2a226f5c9651 100644 --- a/tests/sys/netpfil/pf/pass_block.sh +++ b/tests/sys/netpfil/pf/pass_block.sh @@ -230,7 +230,8 @@ urpf_body() --replyif ${epair_one}a pft_set_rules alcatraz \ - "block quick from urpf-failed" + "block quick from urpf-failed" \ + "set skip on lo" jexec alcatraz pfctl -e # Correct source still works diff --git a/tests/sys/netpfil/pf/pfsync.sh b/tests/sys/netpfil/pf/pfsync.sh index 75788eed4bbe..1b61ec4f03a0 100644 --- a/tests/sys/netpfil/pf/pfsync.sh +++ b/tests/sys/netpfil/pf/pfsync.sh @@ -152,6 +152,7 @@ defer_body() route add -net 203.0.113.0/24 198.51.100.1 # Enable pf + jexec alcatraz sysctl net.pf.filter_local=0 jexec alcatraz pfctl -e pft_set_rules alcatraz \ "set skip on ${epair_sync}a" \ diff --git a/tests/sys/netpfil/pf/route_to.sh b/tests/sys/netpfil/pf/route_to.sh index 203d0a944a5b..18e0e02db65e 100644 --- a/tests/sys/netpfil/pf/route_to.sh +++ b/tests/sys/netpfil/pf/route_to.sh @@ -230,7 +230,8 @@ multiwanlocal_body() "block in" \ "block out" \ "pass out quick route-to (${epair_cl_two}a 203.0.113.129) inet proto tcp from 203.0.113.128 to any port 7" \ - "pass out on ${epair_cl_one}a inet proto tcp from any to any port 7" + "pass out on ${epair_cl_one}a inet proto tcp from any to any port 7" \ + "set skip on lo" # This should work result=$(jexec client nc -N -w 1 192.0.2.2 7 | wc -c) diff --git a/tests/sys/netpfil/pf/set_skip.sh b/tests/sys/netpfil/pf/set_skip.sh index 9b3d655a6d1d..c666622e3d15 100644 --- a/tests/sys/netpfil/pf/set_skip.sh +++ b/tests/sys/netpfil/pf/set_skip.sh @@ -101,7 +101,7 @@ set_skip_dynamic_body() vnet_mkjail alcatraz jexec alcatraz pfctl -e pft_set_rules alcatraz "set skip on epair" \ - "block" + "block on ! lo" epair=$(vnet_mkepair) ifconfig ${epair}a 192.0.2.2/24 up diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index 64dbd3a36201..b820d0c11e75 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -52,7 +52,8 @@ v4_counters_body() "table counters { 192.0.2.1 }" \ "block all" \ "pass in from to any" \ - "pass out from any to " + "pass out from any to " \ + "set skip on lo" atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 @@ -91,7 +92,8 @@ v6_counters_body() "table counters { 2001:db8:42::1 }" \ "block all" \ "pass in from to any" \ - "pass out from any to " + "pass out from any to " \ + "set skip on lo" atf_check -s exit:0 -o ignore ping -6 -c 3 2001:db8:42::2