mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-26 19:03:48 +01:00
pf: bind route-to states to their route-to interface
When we route-to the state should be bound to the route-to interface, not the default route interface. However, we should only do so for outbound traffic, because inbound traffic should bind on the arriving interface, not the one we eventually transmit on. Explicitly check for this in BOUND_IFACE(). We must also extend pf_find_state(), because subsequent packets within the established state will attempt to match the original interface, not the route-to interface. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43589
This commit is contained in:
parent
ffeab76b68
commit
31828075e4
@ -412,8 +412,27 @@ VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]);
|
||||
return (PF_PASS); \
|
||||
} while (0)
|
||||
|
||||
#define BOUND_IFACE(r, k) \
|
||||
((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all
|
||||
static struct pfi_kkif *
|
||||
BOUND_IFACE(struct pf_krule *r, struct pfi_kkif *k, struct pf_pdesc *pd)
|
||||
{
|
||||
/* Floating unless otherwise specified. */
|
||||
if (! (r->rule_flag & PFRULE_IFBOUND))
|
||||
return (V_pfi_all);
|
||||
|
||||
/* Don't overrule the interface for states created on incoming packets. */
|
||||
if (pd->dir == PF_IN)
|
||||
return (k);
|
||||
|
||||
/* No route-to, so don't overrrule. */
|
||||
if (r->rt != PF_ROUTETO)
|
||||
return (k);
|
||||
|
||||
if (r->rpool.cur == NULL)
|
||||
return (k);
|
||||
|
||||
/* Bind to the route-to interface. */
|
||||
return (r->rpool.cur->kif);
|
||||
}
|
||||
|
||||
#define STATE_INC_COUNTERS(s) \
|
||||
do { \
|
||||
@ -1600,7 +1619,7 @@ pf_find_state(struct pfi_kkif *kif, struct pf_state_key_cmp *key, u_int dir)
|
||||
|
||||
/* List is sorted, if-bound states before floating ones. */
|
||||
TAILQ_FOREACH(s, &sk->states[idx], key_list[idx])
|
||||
if (s->kif == V_pfi_all || s->kif == kif) {
|
||||
if (s->kif == V_pfi_all || s->kif == kif || s->orig_kif == kif) {
|
||||
PF_STATE_LOCK(s);
|
||||
PF_HASHROW_UNLOCK(kh);
|
||||
if (__predict_false(s->timeout >= PFTM_MAX)) {
|
||||
@ -4999,7 +5018,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
|
||||
__func__, nr, sk, nk));
|
||||
|
||||
/* Swap sk/nk for PF_OUT. */
|
||||
if (pf_state_insert(BOUND_IFACE(r, kif), kif,
|
||||
if (pf_state_insert(BOUND_IFACE(r, kif, pd), kif,
|
||||
(pd->dir == PF_IN) ? sk : nk,
|
||||
(pd->dir == PF_IN) ? nk : sk, s)) {
|
||||
REASON_SET(&reason, PFRES_STATEINS);
|
||||
|
@ -365,6 +365,48 @@ dummynet_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "ifbound" "cleanup"
|
||||
ifbound_head()
|
||||
{
|
||||
atf_set descr 'Test that route-to states bind the expected interface'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
ifbound_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
j="route_to:ifbound"
|
||||
|
||||
epair_one=$(vnet_mkepair)
|
||||
epair_two=$(vnet_mkepair)
|
||||
ifconfig ${epair_one}b up
|
||||
|
||||
vnet_mkjail ${j}2 ${epair_two}b
|
||||
jexec ${j}2 ifconfig ${epair_two}b inet 198.51.100.2/24 up
|
||||
jexec ${j}2 ifconfig ${epair_two}b inet alias 203.0.113.1/24
|
||||
jexec ${j}2 route add default 198.51.100.1
|
||||
|
||||
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 192.0.2.2
|
||||
|
||||
jexec $j pfctl -e
|
||||
pft_set_rules $j \
|
||||
"set state-policy if-bound" \
|
||||
"block" \
|
||||
"pass out route-to (${epair_two}a 198.51.100.2)"
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
jexec $j ping -c 3 203.0.113.1
|
||||
}
|
||||
|
||||
ifbound_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "v4"
|
||||
@ -373,4 +415,5 @@ atf_init_test_cases()
|
||||
atf_add_test_case "multiwanlocal"
|
||||
atf_add_test_case "icmp_nat"
|
||||
atf_add_test_case "dummynet"
|
||||
atf_add_test_case "ifbound"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user