X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=zones.c;h=2aa74738ebcddb23263bfb8f172b975030f3b7e4;hb=f62595480555f4034841cfbdec5858645528ae7d;hp=9ae0c75b98350c577046ecb72654a87f56c3b240;hpb=18f4c6fda6afb912f53ded3112b1f270ddf5ff6c;p=project%2Ffirewall3.git diff --git a/zones.c b/zones.c index 9ae0c75..2aa7473 100644 --- a/zones.c +++ b/zones.c @@ -66,6 +66,7 @@ const struct fw3_option fw3_zone_opts[] = { 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), @@ -73,7 +74,6 @@ const struct fw3_option fw3_zone_opts[] = { 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), @@ -171,7 +171,8 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) 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) { @@ -217,7 +218,6 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) if (zone->masq) { fw3_setbit(zone->flags[0], FW3_FLAG_SNAT); - zone->conntrack = true; } if (zone->custom_chains) @@ -268,9 +268,6 @@ print_zone_chain(struct fw3_ipt_handle *handle, struct fw3_state *state, 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 */ @@ -359,14 +356,20 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, 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]); } @@ -466,11 +469,29 @@ print_interface_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, } } +static struct fw3_address * +next_addr(struct fw3_address *addr, struct list_head *list, + enum fw3_family family, bool invert) +{ + struct list_head *p; + struct fw3_address *rv; + + for (p = addr ? addr->list.next : list->next; p != list; p = p->next) + { + rv = list_entry(p, struct fw3_address, list); + + if (fw3_is_family(rv, family) && rv->invert == invert) + return rv; + } + + return NULL; +} + static void 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; struct fw3_ipt_rule *r; @@ -552,31 +573,55 @@ print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, case FW3_TABLE_NAT: if (zone->masq && handle->family == FW3_FAMILY_V4) { - fw3_foreach(msrc, &zone->masq_src) - fw3_foreach(mdest, &zone->masq_dest) + /* for any negated masq_src ip, emit -s addr -j RETURN rules */ + for (msrc = NULL; + (msrc = next_addr(msrc, &zone->masq_src, + handle->family, true)) != NULL; ) { - if (!fw3_is_family(msrc, handle->family) || - !fw3_is_family(mdest, handle->family)) - continue; + msrc->invert = false; + r = fw3_ipt_rule_new(handle); + fw3_ipt_rule_src_dest(r, msrc, NULL); + fw3_ipt_rule_target(r, "RETURN"); + fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); + msrc->invert = true; + } + /* for any negated masq_dest ip, emit -d addr -j RETURN rules */ + for (mdest = NULL; + (mdest = next_addr(mdest, &zone->masq_dest, + handle->family, true)) != NULL; ) + { + mdest->invert = false; r = fw3_ipt_rule_new(handle); - fw3_ipt_rule_src_dest(r, msrc, mdest); - fw3_ipt_rule_target(r, "MASQUERADE"); + fw3_ipt_rule_src_dest(r, NULL, mdest); + fw3_ipt_rule_target(r, "RETURN"); fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); + mdest->invert = true; } - } - 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); + /* emit masquerading entries for non-negated addresses + and ensure that both src and dest loops run at least once, + even if there are no relevant addresses */ + for (first_src = true, msrc = NULL; + (msrc = next_addr(msrc, &zone->masq_src, + handle->family, false)) || first_src; + first_src = false) + { + for (first_dest = true, mdest = NULL; + (mdest = next_addr(mdest, &zone->masq_dest, + handle->family, false)) || first_dest; + first_dest = false) + { + r = fw3_ipt_rule_new(handle); + fw3_ipt_rule_src_dest(r, msrc, mdest); + fw3_ipt_rule_target(r, "MASQUERADE"); + fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); + } + } } break; + case FW3_TABLE_RAW: case FW3_TABLE_MANGLE: break; }