mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-04 23:50:27 +00:00
pf: fix reply-to after rdr and dummynet
If we redirect a packet to localhost and it gets dummynet'd it may be re-injected later (e.g. when delayed) which means it will be passed through ip_input() again. ip_input() will then reject the packet because it's directed to the loopback address, but did not arrive on a loopback interface. Fix this by having pf set the rcvif to V_iflo if we redirect to loopback. See also: https://redmine.pfsense.org/issues/15363 Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
5aaef5a600
commit
a983cea4e9
|
@ -7954,6 +7954,18 @@ pf_dummynet_route(struct pf_pdesc *pd, struct pf_kstate *s,
|
|||
sizeof(struct sockaddr_in6));
|
||||
}
|
||||
|
||||
if (s != NULL && s->nat_rule.ptr != NULL &&
|
||||
s->nat_rule.ptr->action == PF_RDR &&
|
||||
((pd->af == AF_INET && IN_LOOPBACK(ntohl(pd->dst->v4.s_addr))) ||
|
||||
(pd->af == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&pd->dst->v6)))) {
|
||||
/*
|
||||
* If we're redirecting to loopback mark this packet
|
||||
* as being local. Otherwise it might get dropped
|
||||
* if dummynet re-injects.
|
||||
*/
|
||||
(*m0)->m_pkthdr.rcvif = V_loif;
|
||||
}
|
||||
|
||||
if (pf_pdesc_to_dnflow(pd, r, s, &dnflow)) {
|
||||
pd->pf_mtag->flags |= PF_MTAG_FLAG_DUMMYNET;
|
||||
pd->pf_mtag->flags |= PF_MTAG_FLAG_DUMMYNETED;
|
||||
|
|
|
@ -626,6 +626,66 @@ ifbound_reply_to_v6_cleanup()
|
|||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "ifbound_reply_to_rdr_dummynet" "cleanup"
|
||||
ifbound_reply_to_rdr_dummynet_head()
|
||||
{
|
||||
atf_set descr 'Test that reply-to states bind to the expected non-default-route interface after rdr and dummynet'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
ifbound_reply_to_rdr_dummynet_body()
|
||||
{
|
||||
dummynet_init
|
||||
|
||||
j="route_to:ifbound_reply_to_rdr_dummynet"
|
||||
|
||||
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 lo0 inet 127.0.0.1/8 up
|
||||
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
|
||||
jexec $j dnctl pipe 1 config delay 1
|
||||
pft_set_rules $j \
|
||||
"set state-policy if-bound" \
|
||||
"rdr on ${epair_one}a proto icmp from any to 192.0.2.1 -> 127.0.0.1" \
|
||||
"rdr on ${epair_two}a proto icmp from any to 198.51.100.1 -> 127.0.0.1" \
|
||||
"match in on ${epair_one}a inet all dnpipe (1, 1)" \
|
||||
"pass in on ${epair_one}a reply-to (${epair_one}a 192.0.2.2) inet from any to 127.0.0.1 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 -sr -vv
|
||||
jexec $j pfctl -ss -vv
|
||||
}
|
||||
|
||||
ifbound_reply_to_rdr_dummynet_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "dummynet_frag" "cleanup"
|
||||
dummynet_frag_head()
|
||||
{
|
||||
|
@ -740,6 +800,7 @@ atf_init_test_cases()
|
|||
atf_add_test_case "ifbound_v6"
|
||||
atf_add_test_case "ifbound_reply_to"
|
||||
atf_add_test_case "ifbound_reply_to_v6"
|
||||
atf_add_test_case "ifbound_reply_to_rdr_dummynet"
|
||||
atf_add_test_case "dummynet_frag"
|
||||
atf_add_test_case "dummynet_double"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue