FW3_OPT("output", target, zone, policy_output),
FW3_OPT("masq", bool, zone, masq),
+ FW3_OPT("masq_allow_invalid", bool, zone, masq_allow_invalid),
FW3_LIST("masq_src", network, zone, masq_src),
FW3_LIST("masq_dest", network, zone, masq_dest),
FW3_OPT("extra_src", string, zone, extra_src),
FW3_OPT("extra_dest", string, zone, extra_dest),
- FW3_OPT("conntrack", bool, zone, conntrack),
FW3_OPT("mtu_fix", bool, zone, mtu_fix),
FW3_OPT("custom_chains", bool, zone, custom_chains),
}
}
+static bool
+check_masq_addrs(struct list_head *head)
+{
+ struct fw3_address *addr;
+ int n_addr = 0, n_failed = 0;
+
+ list_for_each_entry(addr, head, list)
+ {
+ if (addr->invert)
+ continue;
+
+ n_addr++;
+
+ if (!addr->set && addr->resolved)
+ n_failed++;
+ }
+
+ return (n_addr == 0 || n_failed < n_addr);
+}
+
static void
resolve_networks(struct uci_element *e, struct fw3_zone *zone)
{
if (!zone)
continue;
- fw3_parse_options(zone, fw3_zone_opts, s);
+ if (!fw3_parse_options(zone, fw3_zone_opts, s))
+ warn_elem(e, "has invalid options");
if (!zone->enabled)
{
warn_elem(e, "has no device, network, subnet or extra options");
}
+ if (!check_masq_addrs(&zone->masq_src))
+ {
+ warn_elem(e, "has unresolved masq_src, disabling masq");
+ zone->masq = false;
+ }
+
+ if (!check_masq_addrs(&zone->masq_dest))
+ {
+ warn_elem(e, "has unresolved masq_dest, disabling masq");
+ zone->masq = false;
+ }
+
check_policy(e, &zone->policy_input, defs->policy_input, "input");
check_policy(e, &zone->policy_output, defs->policy_output, "output");
check_policy(e, &zone->policy_forward, defs->policy_forward, "forward");
if (zone->masq)
{
fw3_setbit(zone->flags[0], FW3_FLAG_SNAT);
- zone->conntrack = true;
}
if (zone->custom_chains)
if (zone->custom_chains)
set(zone->flags, handle->family, FW3_FLAG_CUSTOM_CHAINS);
- if (!zone->conntrack && !state->defaults.drop_invalid)
- set(zone->flags, handle->family, FW3_FLAG_NOTRACK);
-
for (c = zone_chains; c->format; c++)
{
/* don't touch user chains on selective stop */
if (has(zone->flags, handle->family, t))
{
+ if (t == FW3_FLAG_ACCEPT &&
+ zone->masq && !zone->masq_allow_invalid)
+ {
+ r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
+ fw3_ipt_rule_extra(r, "-m conntrack --ctstate INVALID");
+ fw3_ipt_rule_comment(r, "Prevent NAT leakage");
+ fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_DROP]);
+ fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name,
+ fw3_flag_names[t]);
+ }
+
r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
fw3_ipt_rule_target(r, jump_target(t));
fw3_ipt_rule_extra(r, zone->extra_dest);
-
- if (t == FW3_FLAG_ACCEPT && !state->defaults.drop_invalid)
- fw3_ipt_rule_extra(r,
- "-m conntrack --ctstate NEW,UNTRACKED");
-
fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name,
fw3_flag_names[t]);
}
{
rv = list_entry(p, struct fw3_address, list);
- if (fw3_is_family(rv, family) && rv->invert == invert)
+ if (fw3_is_family(rv, family) && rv->set && rv->invert == invert)
return rv;
}
print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
bool reload, struct fw3_zone *zone)
{
- bool disable_notrack = state->defaults.drop_invalid;
bool first_src, first_dest;
struct fw3_address *msrc;
struct fw3_address *mdest;
break;
case FW3_TABLE_RAW:
- if (!zone->conntrack && !disable_notrack)
- {
- r = fw3_ipt_rule_new(handle);
- fw3_ipt_rule_target(r, "CT");
- fw3_ipt_rule_addarg(r, false, "--notrack", NULL);
- fw3_ipt_rule_append(r, "zone_%s_notrack", zone->name);
- }
- break;
-
case FW3_TABLE_MANGLE:
break;
}