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>
bool local;
bool reflection;
enum fw3_reflection_source reflection_src;
bool local;
bool reflection;
enum fw3_reflection_source reflection_src;
+ struct list_head reflection_zones;
FW3_OPT("reflection", bool, redirect, reflection),
FW3_OPT("reflection_src", reflection_source,
redirect, reflection_src),
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),
FW3_OPT("target", target, redirect, target),
INIT_LIST_HEAD(&redir->proto);
INIT_LIST_HEAD(&redir->mac_src);
INIT_LIST_HEAD(&redir->proto);
INIT_LIST_HEAD(&redir->mac_src);
+ INIT_LIST_HEAD(&redir->reflection_zones);
redir->enabled = true;
redir->reflection = true;
redir->enabled = true;
redir->reflection = true;
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,
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;
{
struct fw3_ipt_rule *r;
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_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);
r = fw3_ipt_rule_create(h, proto, NULL, NULL, ia, &redir->ip_redir);
fw3_ipt_rule_sport_dport(r, NULL, &redir->port_redir);
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_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);
struct fw3_address *ext_addr, *int_addr, ref_addr;
struct fw3_protocol *proto;
struct fw3_mac *mac;
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);
if (redir->name)
info(" * Redirect '%s'", redir->name);
return;
ext_addrs = fw3_resolve_zone_addresses(redir->_src, &redir->ip_dest);
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)
goto out;
list_for_each_entry(ext_addr, ext_addrs, list)
goto out;
list_for_each_entry(ext_addr, ext_addrs, list)
if (!fw3_is_family(ext_addr, handle->family))
continue;
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)
- fw3_foreach(proto, &redir->proto)
+ int_addrs = fw3_resolve_zone_addresses(zone, NULL);
+ list_for_each_entry(int_addr, int_addrs, list)
+ if (!fw3_is_family(int_addr, handle->family))
- 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);
+ }