pf: Make nat-to and rdr-to work properly both on in and out rules
New-style address translation is done by nat-to and rdr-to actions on normal match and pass rules. Those rules, when used without address translation, can be specified without direction. But that allows users to specify pre-routing nat and post-routing rdr. This case is not handled properly and causes pre-routing nat to modify destination address, as if it was a rdr rule, and post-routing rdr to modify source address, as if it was a nat rule. Ensure that nat-to action modifies source address and rdr-to destination address no matter in which direction the rule is applied. The man page for pf.conf already specifies that nat-to and rdr-to rules should be limited to respective directions. PR: 288577 Reviewed by: kp MFC after: 3 days Sponsored by: InnoGames GmbH Differential Revision: https://reviews.freebsd.org/D53216
This commit is contained in:
+14
-2
@@ -974,6 +974,7 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,
|
||||
{
|
||||
struct pf_pdesc *pd = ctx->pd;
|
||||
struct pf_addr *naddr;
|
||||
int idx;
|
||||
uint16_t *nportp;
|
||||
uint16_t low, high;
|
||||
u_short reason;
|
||||
@@ -988,8 +989,19 @@ pf_get_transaddr(struct pf_test_ctx *ctx, struct pf_krule *r,
|
||||
return (PFRES_MEMORY);
|
||||
}
|
||||
|
||||
naddr = &ctx->nk->addr[1];
|
||||
nportp = &ctx->nk->port[1];
|
||||
switch (nat_action) {
|
||||
case PF_NAT:
|
||||
idx = pd->sidx;
|
||||
break;
|
||||
case PF_BINAT:
|
||||
idx = 1;
|
||||
break;
|
||||
case PF_RDR:
|
||||
idx = pd->didx;
|
||||
break;
|
||||
}
|
||||
naddr = &ctx->nk->addr[idx];
|
||||
nportp = &ctx->nk->port[idx];
|
||||
|
||||
switch (nat_action) {
|
||||
case PF_NAT:
|
||||
|
||||
@@ -477,15 +477,49 @@ no_addrs_random_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "nat_pass" "cleanup"
|
||||
nat_pass_head()
|
||||
atf_test_case "nat_pass_in" "cleanup"
|
||||
nat_pass_in_head()
|
||||
{
|
||||
atf_set descr 'IPv4 NAT on pass rule'
|
||||
atf_set descr 'IPv4 NAT on inbound pass rule'
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
nat_pass_body()
|
||||
nat_pass_in_body()
|
||||
{
|
||||
setup_router_server_ipv4
|
||||
# Delete the route back to make sure that the traffic has been NAT-ed
|
||||
jexec server route del -net ${net_tester} ${net_server_host_router}
|
||||
# Provide routing back to the NAT address
|
||||
jexec server route add 203.0.113.0/24 ${net_server_host_router}
|
||||
jexec router route add 203.0.113.0/24 -iface ${epair_tester}b
|
||||
|
||||
pft_set_rules router \
|
||||
"block" \
|
||||
"pass in on ${epair_tester}b inet proto tcp nat-to 203.0.113.0 keep state" \
|
||||
"pass out on ${epair_server}a inet proto tcp keep state"
|
||||
|
||||
ping_server_check_reply exit:0 --ping-type=tcp3way --send-sport=4201
|
||||
|
||||
jexec router pfctl -qvvsr
|
||||
jexec router pfctl -qvvss
|
||||
jexec router ifconfig
|
||||
jexec router netstat -rn
|
||||
}
|
||||
|
||||
nat_pass_in_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
nat_pass_out_head()
|
||||
{
|
||||
atf_set descr 'IPv4 NAT on outbound pass rule'
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
nat_pass_out_body()
|
||||
{
|
||||
setup_router_server_ipv4
|
||||
# Delete the route back to make sure that the traffic has been NAT-ed
|
||||
@@ -504,7 +538,7 @@ nat_pass_body()
|
||||
jexec router netstat -rn
|
||||
}
|
||||
|
||||
nat_pass_cleanup()
|
||||
nat_pass_out_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
@@ -874,7 +908,8 @@ atf_init_test_cases()
|
||||
atf_add_test_case "no_addrs_random"
|
||||
atf_add_test_case "map_e_compat"
|
||||
atf_add_test_case "map_e_pass"
|
||||
atf_add_test_case "nat_pass"
|
||||
atf_add_test_case "nat_pass_in"
|
||||
atf_add_test_case "nat_pass_out"
|
||||
atf_add_test_case "nat_match"
|
||||
atf_add_test_case "binat_compat"
|
||||
atf_add_test_case "binat_match"
|
||||
|
||||
Reference in New Issue
Block a user