pf: Add code to enable filtering for locally delivered packets
This is disabled by default since it potentially changes the behavior of existing filter rule sets. To enable this extra filter for packets being delivered locally, use: sysctl net.pf.filter_local=1 service pf restart PR: 268717 Reviewed-by: kp MFC-after: 2 weeks Differential Revision: https://reviews.freebsd.org/D40373
This commit is contained in:
parent
9aca30d878
commit
3a1f834b52
12
UPDATING
12
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
|
world, or to merely disable the most expensive debugging functionality
|
||||||
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
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:
|
20230613:
|
||||||
Improvements to libtacplus(8) mean that tacplus.conf(5) now
|
Improvements to libtacplus(8) mean that tacplus.conf(5) now
|
||||||
follows POSIX shell syntax rules. This may cause TACACS+
|
follows POSIX shell syntax rules. This may cause TACACS+
|
||||||
|
@ -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
|
#error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
|
||||||
#endif
|
#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 *,
|
static void pf_init_tagset(struct pf_tagset *, unsigned int *,
|
||||||
unsigned int);
|
unsigned int);
|
||||||
static void pf_cleanup_tagset(struct pf_tagset *);
|
static void pf_cleanup_tagset(struct pf_tagset *);
|
||||||
@ -6682,6 +6688,13 @@ hook_pf(void)
|
|||||||
pla.pa_hook = V_pf_ip4_out_hook;
|
pla.pa_hook = V_pf_ip4_out_hook;
|
||||||
ret = pfil_link(&pla);
|
ret = pfil_link(&pla);
|
||||||
MPASS(ret == 0);
|
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
|
#endif
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
pha.pa_type = PFIL_TYPE_IP6;
|
pha.pa_type = PFIL_TYPE_IP6;
|
||||||
@ -6703,6 +6716,13 @@ hook_pf(void)
|
|||||||
pla.pa_hook = V_pf_ip6_out_hook;
|
pla.pa_hook = V_pf_ip6_out_hook;
|
||||||
ret = pfil_link(&pla);
|
ret = pfil_link(&pla);
|
||||||
MPASS(ret == 0);
|
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
|
#endif
|
||||||
|
|
||||||
atomic_store_bool(&V_pf_pfil_hooked, true);
|
atomic_store_bool(&V_pf_pfil_hooked, true);
|
||||||
|
@ -55,11 +55,10 @@ firewall_config()
|
|||||||
jexec ${jname} ipfw -q -f flush
|
jexec ${jname} ipfw -q -f flush
|
||||||
jexec ${jname} /bin/sh $cwd/ipfw.rule
|
jexec ${jname} /bin/sh $cwd/ipfw.rule
|
||||||
elif [ ${fw} == "pf" ]; then
|
elif [ ${fw} == "pf" ]; then
|
||||||
|
jexec ${jname} sysctl net.pf.filter_local=1
|
||||||
jexec ${jname} pfctl -e
|
jexec ${jname} pfctl -e
|
||||||
jexec ${jname} pfctl -F all
|
jexec ${jname} pfctl -F all
|
||||||
jexec ${jname} pfctl -f $cwd/pf.rule
|
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
|
elif [ ${fw} == "ipf" ]; then
|
||||||
jexec ${jname} ipf -E
|
jexec ${jname} ipf -E
|
||||||
jexec ${jname} ipf -Fa -f $cwd/ipf.rule
|
jexec ${jname} ipf -Fa -f $cwd/ipf.rule
|
||||||
|
@ -112,7 +112,8 @@ v6_body()
|
|||||||
"scrub fragment reassemble" \
|
"scrub fragment reassemble" \
|
||||||
"block in" \
|
"block in" \
|
||||||
"pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
|
"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
|
# Host test
|
||||||
atf_check -s exit:0 -o ignore \
|
atf_check -s exit:0 -o ignore \
|
||||||
|
@ -116,7 +116,8 @@ v6_body()
|
|||||||
"pass keep state" \
|
"pass keep state" \
|
||||||
"block in" \
|
"block in" \
|
||||||
"pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
|
"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
|
# Host test
|
||||||
atf_check -s exit:0 -o ignore \
|
atf_check -s exit:0 -o ignore \
|
||||||
|
@ -60,7 +60,8 @@ v4_body()
|
|||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
pft_set_rules alcatraz "block all" \
|
||||||
"pass in proto icmp"
|
"pass in proto icmp" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
# Sanity check & establish state
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -126,7 +127,8 @@ v6_body()
|
|||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
pft_set_rules alcatraz "block all" \
|
||||||
"pass in proto icmp6"
|
"pass in proto icmp6" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
# Sanity check & establish state
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -189,7 +191,8 @@ label_body()
|
|||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
pft_set_rules alcatraz "block all" \
|
||||||
"pass in proto tcp label bar" \
|
"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
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -251,7 +254,8 @@ multilabel_body()
|
|||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
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
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -281,7 +285,8 @@ multilabel_body()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
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
|
# Reestablish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -329,7 +334,8 @@ gateway_body()
|
|||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
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
|
# Sanity check & establish state
|
||||||
# Note: use pft_ping so we always use the same ID, so pf considers all
|
# 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
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
pft_set_rules alcatraz "block all" \
|
||||||
"pass in proto icmp"
|
"pass in proto icmp" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
# Sanity check & establish state
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
@ -525,7 +532,8 @@ id_body()
|
|||||||
|
|
||||||
pft_set_rules alcatraz "block all" \
|
pft_set_rules alcatraz "block all" \
|
||||||
"pass in proto tcp" \
|
"pass in proto tcp" \
|
||||||
"pass in proto icmp"
|
"pass in proto icmp" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
# Sanity check & establish state
|
# Sanity check & establish state
|
||||||
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
|
||||||
|
@ -66,7 +66,8 @@ map_e_body()
|
|||||||
pft_set_rules echo "block return all" \
|
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 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 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
|
i=0
|
||||||
while [ ${i} -lt ${NC_TRY_COUNT} ]
|
while [ ${i} -lt ${NC_TRY_COUNT} ]
|
||||||
|
@ -230,7 +230,8 @@ urpf_body()
|
|||||||
--replyif ${epair_one}a
|
--replyif ${epair_one}a
|
||||||
|
|
||||||
pft_set_rules alcatraz \
|
pft_set_rules alcatraz \
|
||||||
"block quick from urpf-failed"
|
"block quick from urpf-failed" \
|
||||||
|
"set skip on lo"
|
||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
|
|
||||||
# Correct source still works
|
# Correct source still works
|
||||||
|
@ -152,6 +152,7 @@ defer_body()
|
|||||||
route add -net 203.0.113.0/24 198.51.100.1
|
route add -net 203.0.113.0/24 198.51.100.1
|
||||||
|
|
||||||
# Enable pf
|
# Enable pf
|
||||||
|
jexec alcatraz sysctl net.pf.filter_local=0
|
||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
pft_set_rules alcatraz \
|
pft_set_rules alcatraz \
|
||||||
"set skip on ${epair_sync}a" \
|
"set skip on ${epair_sync}a" \
|
||||||
|
@ -230,7 +230,8 @@ multiwanlocal_body()
|
|||||||
"block in" \
|
"block in" \
|
||||||
"block out" \
|
"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 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
|
# This should work
|
||||||
result=$(jexec client nc -N -w 1 192.0.2.2 7 | wc -c)
|
result=$(jexec client nc -N -w 1 192.0.2.2 7 | wc -c)
|
||||||
|
@ -101,7 +101,7 @@ set_skip_dynamic_body()
|
|||||||
vnet_mkjail alcatraz
|
vnet_mkjail alcatraz
|
||||||
jexec alcatraz pfctl -e
|
jexec alcatraz pfctl -e
|
||||||
pft_set_rules alcatraz "set skip on epair" \
|
pft_set_rules alcatraz "set skip on epair" \
|
||||||
"block"
|
"block on ! lo"
|
||||||
|
|
||||||
epair=$(vnet_mkepair)
|
epair=$(vnet_mkepair)
|
||||||
ifconfig ${epair}a 192.0.2.2/24 up
|
ifconfig ${epair}a 192.0.2.2/24 up
|
||||||
|
@ -52,7 +52,8 @@ v4_counters_body()
|
|||||||
"table <foo> counters { 192.0.2.1 }" \
|
"table <foo> counters { 192.0.2.1 }" \
|
||||||
"block all" \
|
"block all" \
|
||||||
"pass in from <foo> to any" \
|
"pass in from <foo> to any" \
|
||||||
"pass out from any to <foo>"
|
"pass out from any to <foo>" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2
|
atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2
|
||||||
|
|
||||||
@ -91,7 +92,8 @@ v6_counters_body()
|
|||||||
"table <foo6> counters { 2001:db8:42::1 }" \
|
"table <foo6> counters { 2001:db8:42::1 }" \
|
||||||
"block all" \
|
"block all" \
|
||||||
"pass in from <foo6> to any" \
|
"pass in from <foo6> to any" \
|
||||||
"pass out from any to <foo6>"
|
"pass out from any to <foo6>" \
|
||||||
|
"set skip on lo"
|
||||||
|
|
||||||
atf_check -s exit:0 -o ignore ping -6 -c 3 2001:db8:42::2
|
atf_check -s exit:0 -o ignore ping -6 -c 3 2001:db8:42::2
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user