summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Engelhardt <engelhardt.anton@gmail.com>2018-09-14 19:31:15 +0200
committerJo-Philipp Wich <jo@mein.io>2020-03-16 08:53:34 +0100
commit9d7f49df47ad40a95ea0a37b9dcf423ee07819a7 (patch)
treeedfe4088b4740af808d8d392c38c8f6b0cd68b0a
parentf87d0b0f607420424cfcb4ff5a376d7659fa5b6b (diff)
downloadfirewall3-9d7f49df47ad40a95ea0a37b9dcf423ee07819a7.tar.gz
redurects: add support to define multiple zones for dnat reflection rules
Added new config option for redirect, which accepts a list of zones from which reflection rules shall be created. Example: zones: wan lan devices servers config redirect ... option target 'DNAT' option src 'wan' option dest 'servers' option proto 'tcp' option src_dport '443' option dest_port '443' option name 'HTTPS' option reflection_src 'extern' ... Old behaviour would only add a reflection rule from the servers zone. By adding a config `option reflection_zones 'lan devices servers'`, reflection rules will get added for all and only the given zones. Not setting that option results in the old behaviour of using the DNAT destination zone for reflection rules. Tested on x86 master and 18.06. Signed-off-by: Anton Engelhardt <engelhardt.anton@gmail.com> [reword commit message, align code style, avoid temporary list, singular option name] Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--options.h1
-rw-r--r--redirects.c54
2 files changed, 38 insertions, 17 deletions
diff --git a/options.h b/options.h
index cffc01c..e20c89b 100644
--- a/options.h
+++ b/options.h
@@ -441,6 +441,7 @@ struct fw3_redirect
bool local;
bool reflection;
enum fw3_reflection_source reflection_src;
+ struct list_head reflection_zones;
};
struct fw3_snat
diff --git a/redirects.c b/redirects.c
index d376555..b928287 100644
--- a/redirects.c
+++ b/redirects.c
@@ -61,6 +61,7 @@ const struct fw3_option fw3_redirect_opts[] = {
FW3_OPT("reflection", bool, redirect, reflection),
FW3_OPT("reflection_src", reflection_source,
redirect, reflection_src),
+ FW3_LIST("reflection_zone", device, redirect, reflection_zones),
FW3_OPT("target", target, redirect, target),
@@ -366,6 +367,7 @@ fw3_alloc_redirect(struct fw3_state *state)
INIT_LIST_HEAD(&redir->proto);
INIT_LIST_HEAD(&redir->mac_src);
+ INIT_LIST_HEAD(&redir->reflection_zones);
redir->enabled = true;
redir->reflection = true;
@@ -611,7 +613,7 @@ static void
print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
struct fw3_redirect *redir, int num,
struct fw3_protocol *proto, struct fw3_address *ra,
- struct fw3_address *ia, struct fw3_address *ea)
+ struct fw3_address *ia, struct fw3_address *ea, struct fw3_device *rz)
{
struct fw3_ipt_rule *r;
@@ -624,7 +626,7 @@ print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, "reflection");
set_snat_dnat(r, FW3_FLAG_DNAT, &redir->ip_redir, &redir->port_redir);
- fw3_ipt_rule_replace(r, "zone_%s_prerouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_prerouting", rz->name);
r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, &redir->ip_redir);
fw3_ipt_rule_sport_dport(r, NULL, &redir->port_redir);
@@ -632,7 +634,7 @@ print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
fw3_ipt_rule_time(r, &redir->time);
set_comment(r, redir->name, num, "reflection");
set_snat_dnat(r, FW3_FLAG_SNAT, ra, NULL);
- fw3_ipt_rule_replace(r, "zone_%s_postrouting", redir->dest.name);
+ fw3_ipt_rule_replace(r, "zone_%s_postrouting", rz->name);
break;
default:
@@ -648,6 +650,8 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_address *ext_addr, *int_addr, ref_addr;
struct fw3_protocol *proto;
struct fw3_mac *mac;
+ struct fw3_device *reflection_zone;
+ struct fw3_zone *zone;
if (redir->name)
info(" * Redirect '%s'", redir->name);
@@ -704,9 +708,8 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
return;
ext_addrs = fw3_resolve_zone_addresses(redir->_src, &redir->ip_dest);
- int_addrs = fw3_resolve_zone_addresses(redir->_dest, NULL);
- if (!ext_addrs || !int_addrs)
+ if (!ext_addrs)
goto out;
list_for_each_entry(ext_addr, ext_addrs, list)
@@ -714,26 +717,43 @@ expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
if (!fw3_is_family(ext_addr, handle->family))
continue;
- list_for_each_entry(int_addr, int_addrs, list)
+ for (reflection_zone = list_empty(&redir->reflection_zones)
+ ? &redir->dest
+ : list_first_entry(&redir->reflection_zones, struct fw3_device, list);
+ list_empty(&redir->reflection_zones)
+ ? (reflection_zone == &redir->dest)
+ : (&reflection_zone->list != &redir->reflection_zones);
+ reflection_zone = list_empty(&redir->reflection_zones)
+ ? NULL
+ : list_entry(reflection_zone->list.next, struct fw3_device, list))
{
- if (!fw3_is_family(int_addr, handle->family))
+ zone = fw3_lookup_zone(state, reflection_zone->name);
+
+ if (!zone)
continue;
- fw3_foreach(proto, &redir->proto)
+ int_addrs = fw3_resolve_zone_addresses(zone, NULL);
+ list_for_each_entry(int_addr, int_addrs, list)
{
- if (!proto)
+ if (!fw3_is_family(int_addr, handle->family))
continue;
- if (redir->reflection_src == FW3_REFLECTION_INTERNAL)
- ref_addr = *int_addr;
- else
- ref_addr = *ext_addr;
+ fw3_foreach(proto, &redir->proto)
+ {
+ if (!proto)
+ continue;
+
+ if (redir->reflection_src == FW3_REFLECTION_INTERNAL)
+ ref_addr = *int_addr;
+ else
+ ref_addr = *ext_addr;
- ref_addr.mask.v4.s_addr = 0xFFFFFFFF;
- ext_addr->mask.v4.s_addr = 0xFFFFFFFF;
+ ref_addr.mask.v4.s_addr = 0xFFFFFFFF;
+ ext_addr->mask.v4.s_addr = 0xFFFFFFFF;
- print_reflection(handle, state, redir, num, proto,
- &ref_addr, int_addr, ext_addr);
+ print_reflection(handle, state, redir, num, proto,
+ &ref_addr, int_addr, ext_addr, reflection_zone);
+ }
}
}
}