mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-28 03:42:04 +01:00
pf: support if-bound with reply-to
On reply-to we don't know what interface to bind to when we create the state. Create any reply-to state as floating, but bind to the appropriate interface once we're handling the reply. See also: https://redmine.pfsense.org/issues/15220 Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
51c6bf0478
commit
6460322a0a
@ -423,6 +423,13 @@ BOUND_IFACE(struct pf_kstate *st, struct pfi_kkif *k)
|
||||
if (! (st->rule.ptr->rule_flag & PFRULE_IFBOUND))
|
||||
return (V_pfi_all);
|
||||
|
||||
/*
|
||||
* Initially set to all, because we don't know what interface we'll be
|
||||
* sending this out when we create the state.
|
||||
*/
|
||||
if (st->rule.ptr->rt == PF_REPLYTO)
|
||||
return (V_pfi_all);
|
||||
|
||||
/* Don't overrule the interface for states created on incoming packets. */
|
||||
if (st->direction == PF_IN)
|
||||
return (k);
|
||||
@ -7317,15 +7324,27 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
dst.sin_addr.s_addr = naddr.v4.s_addr;
|
||||
ifp = nkif ? nkif->pfik_ifp : NULL;
|
||||
} else {
|
||||
struct pfi_kkif *kif;
|
||||
|
||||
if (!PF_AZERO(&s->rt_addr, AF_INET))
|
||||
dst.sin_addr.s_addr =
|
||||
s->rt_addr.v4.s_addr;
|
||||
ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
|
||||
kif = s->rt_kif;
|
||||
/* If pfsync'd */
|
||||
if (ifp == NULL && r->rpool.cur != NULL) {
|
||||
ifp = r->rpool.cur->kif ?
|
||||
r->rpool.cur->kif->pfik_ifp : NULL;
|
||||
kif = r->rpool.cur->kif;
|
||||
}
|
||||
if (ifp != NULL && kif != NULL &&
|
||||
r->rule_flag & PFRULE_IFBOUND &&
|
||||
r->rt == PF_REPLYTO &&
|
||||
s->kif == V_pfi_all) {
|
||||
s->kif = kif;
|
||||
s->orig_kif = oifp->if_pf_kif;
|
||||
}
|
||||
|
||||
PF_STATE_UNLOCK(s);
|
||||
}
|
||||
|
||||
@ -7538,14 +7557,26 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
&naddr, AF_INET6);
|
||||
ifp = nkif ? nkif->pfik_ifp : NULL;
|
||||
} else {
|
||||
struct pfi_kkif *kif;
|
||||
|
||||
if (!PF_AZERO(&s->rt_addr, AF_INET6))
|
||||
PF_ACPY((struct pf_addr *)&dst.sin6_addr,
|
||||
&s->rt_addr, AF_INET6);
|
||||
ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
|
||||
kif = s->rt_kif;
|
||||
/* If pfsync'd */
|
||||
if (ifp == NULL && r->rpool.cur != NULL)
|
||||
if (ifp == NULL && r->rpool.cur != NULL) {
|
||||
ifp = r->rpool.cur->kif ?
|
||||
r->rpool.cur->kif->pfik_ifp : NULL;
|
||||
kif = r->rpool.cur->kif;
|
||||
}
|
||||
if (ifp != NULL && kif != NULL &&
|
||||
r->rule_flag & PFRULE_IFBOUND &&
|
||||
r->rt == PF_REPLYTO &&
|
||||
s->kif == V_pfi_all) {
|
||||
s->kif = kif;
|
||||
s->orig_kif = oifp->if_pf_kif;
|
||||
}
|
||||
}
|
||||
|
||||
if (s)
|
||||
|
@ -407,6 +407,61 @@ ifbound_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "ifbound_reply_to" "cleanup"
|
||||
ifbound_reply_to_head()
|
||||
{
|
||||
atf_set descr 'Test that reply-to states bind to the expected interface'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
ifbound_reply_to_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
j="route_to:ifbound_reply_to"
|
||||
|
||||
epair_one=$(vnet_mkepair)
|
||||
epair_two=$(vnet_mkepair)
|
||||
ifconfig ${epair_one}b inet 192.0.2.2/24 up
|
||||
ifconfig ${epair_two}b up
|
||||
|
||||
vnet_mkjail $j ${epair_one}a ${epair_two}a
|
||||
jexec $j ifconfig ${epair_one}a 192.0.2.1/24 up
|
||||
jexec $j ifconfig ${epair_two}a 198.51.100.1/24 up
|
||||
jexec $j route add default 198.51.100.254
|
||||
|
||||
jexec $j pfctl -e
|
||||
pft_set_rules $j \
|
||||
"set state-policy if-bound" \
|
||||
"block" \
|
||||
"pass in on ${epair_one}a reply-to (${epair_one}a 192.0.2.2) inet from any to 192.0.2.0/24 keep state"
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -c 3 192.0.2.1
|
||||
|
||||
atf_check -s exit:0 \
|
||||
${common_dir}/pft_ping.py \
|
||||
--to 192.0.2.1 \
|
||||
--from 203.0.113.2 \
|
||||
--sendif ${epair_one}b \
|
||||
--replyif ${epair_one}b
|
||||
|
||||
# pft_ping uses the same ID every time, so this will look like more traffic in the same state
|
||||
atf_check -s exit:0 \
|
||||
${common_dir}/pft_ping.py \
|
||||
--to 192.0.2.1 \
|
||||
--from 203.0.113.2 \
|
||||
--sendif ${epair_one}b \
|
||||
--replyif ${epair_one}b
|
||||
|
||||
jexec $j pfctl -ss -vv
|
||||
}
|
||||
|
||||
ifbound_reply_to_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "dummynet_frag" "cleanup"
|
||||
dummynet_frag_head()
|
||||
{
|
||||
@ -465,5 +520,6 @@ atf_init_test_cases()
|
||||
atf_add_test_case "icmp_nat"
|
||||
atf_add_test_case "dummynet"
|
||||
atf_add_test_case "ifbound"
|
||||
atf_add_test_case "ifbound_reply_to"
|
||||
atf_add_test_case "dummynet_frag"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user