X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=zones.c;h=26f6215b22b77a793aa73061b29f2abbbaf17cc9;hb=e06e5376e1a2d70de256fe9da0ea78d2a7695a98;hp=2ddd7b44443f3b2714e19ffb2f8b8b29320700d2;hpb=b59934331c4b9271ceb5e30b793a552618299d39;p=project%2Ffirewall3.git diff --git a/zones.c b/zones.c index 2ddd7b4..26f6215 100644 --- a/zones.c +++ b/zones.c @@ -1,7 +1,7 @@ /* * firewall3 - 3rd OpenWrt UCI firewall implementation * - * Copyright (C) 2013 Jo-Philipp Wich + * Copyright (C) 2013 Jo-Philipp Wich * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -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), @@ -216,23 +216,22 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) if (zone->masq) { - setbit(zone->flags[0], FW3_FLAG_SNAT); - zone->conntrack = true; + fw3_setbit(zone->flags[0], FW3_FLAG_SNAT); } if (zone->custom_chains) { - setbit(zone->flags[0], FW3_FLAG_SNAT); - setbit(zone->flags[0], FW3_FLAG_DNAT); + fw3_setbit(zone->flags[0], FW3_FLAG_SNAT); + fw3_setbit(zone->flags[0], FW3_FLAG_DNAT); } - setbit(zone->flags[0], fw3_to_src_target(zone->policy_input)); - setbit(zone->flags[0], zone->policy_forward); - setbit(zone->flags[0], zone->policy_output); + fw3_setbit(zone->flags[0], fw3_to_src_target(zone->policy_input)); + fw3_setbit(zone->flags[0], zone->policy_forward); + fw3_setbit(zone->flags[0], zone->policy_output); - setbit(zone->flags[1], fw3_to_src_target(zone->policy_input)); - setbit(zone->flags[1], zone->policy_forward); - setbit(zone->flags[1], zone->policy_output); + fw3_setbit(zone->flags[1], fw3_to_src_target(zone->policy_input)); + fw3_setbit(zone->flags[1], zone->policy_forward); + fw3_setbit(zone->flags[1], zone->policy_output); list_add_tail(&zone->list, &state->zones); } @@ -268,9 +267,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 */ @@ -284,7 +280,7 @@ print_zone_chain(struct fw3_ipt_handle *handle, struct fw3_state *state, continue; if (c->flag && - !hasbit(zone->flags[handle->family == FW3_FAMILY_V6], c->flag)) + !fw3_hasbit(zone->flags[handle->family == FW3_FAMILY_V6], c->flag)) continue; fw3_ipt_create_chain(handle, c->format, zone->name); @@ -331,9 +327,9 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, int i; const char *chains[] = { - "input", - "output", - "forward", + "input", "INPUT", + "output", "OUTPUT", + "forward", "FORWARD", }; #define jump_target(t) \ @@ -348,12 +344,28 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); fw3_ipt_rule_target(r, jump_target(t)); fw3_ipt_rule_extra(r, zone->extra_src); + + 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_src_%s", zone->name, fw3_flag_names[t]); } 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); @@ -362,7 +374,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, } } - for (i = 0; i < sizeof(chains)/sizeof(chains[0]); i++) + for (i = 0; i < sizeof(chains)/sizeof(chains[0]); i += 2) { if (*chains[i] == 'o') r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); @@ -376,7 +388,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, else fw3_ipt_rule_extra(r, zone->extra_src); - fw3_ipt_rule_replace(r, "delegate_%s", chains[i]); + fw3_ipt_rule_replace(r, chains[i + 1]); } } else if (handle->table == FW3_TABLE_NAT) @@ -386,7 +398,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); fw3_ipt_rule_target(r, "zone_%s_prerouting", zone->name); fw3_ipt_rule_extra(r, zone->extra_src); - fw3_ipt_rule_replace(r, "delegate_prerouting"); + fw3_ipt_rule_replace(r, "PREROUTING"); } if (has(zone->flags, handle->family, FW3_FLAG_SNAT)) @@ -394,7 +406,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); fw3_ipt_rule_target(r, "zone_%s_postrouting", zone->name); fw3_ipt_rule_extra(r, zone->extra_dest); - fw3_ipt_rule_replace(r, "delegate_postrouting"); + fw3_ipt_rule_replace(r, "POSTROUTING"); } } else if (handle->table == FW3_TABLE_MANGLE) @@ -412,7 +424,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, fw3_ipt_rule_comment(r, "%s (mtu_fix logging)", zone->name); fw3_ipt_rule_target(r, "LOG"); fw3_ipt_rule_addarg(r, false, "--log-prefix", buf); - fw3_ipt_rule_replace(r, "mssfix"); + fw3_ipt_rule_replace(r, "FORWARD"); } r = fw3_ipt_rule_create(handle, &tcp, NULL, dev, NULL, sub); @@ -421,7 +433,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, fw3_ipt_rule_comment(r, "%s (mtu_fix)", zone->name); fw3_ipt_rule_target(r, "TCPMSS"); fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL); - fw3_ipt_rule_replace(r, "mssfix"); + fw3_ipt_rule_replace(r, "FORWARD"); } } else if (handle->table == FW3_TABLE_RAW) @@ -431,7 +443,7 @@ print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); fw3_ipt_rule_target(r, "zone_%s_notrack", zone->name); fw3_ipt_rule_extra(r, zone->extra_src); - fw3_ipt_rule_replace(r, "delegate_notrack"); + fw3_ipt_rule_replace(r, "PREROUTING"); } } } @@ -456,11 +468,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; @@ -542,31 +572,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; } @@ -645,15 +699,15 @@ fw3_hotplug_zones(struct fw3_state *state, bool add) list_for_each_entry(z, &state->zones, list) { - if (add != hasbit(z->flags[0], FW3_FLAG_HOTPLUG)) + if (add != fw3_hasbit(z->flags[0], FW3_FLAG_HOTPLUG)) { list_for_each_entry(d, &z->devices, list) fw3_hotplug(add, z, d); if (add) - setbit(z->flags[0], FW3_FLAG_HOTPLUG); + fw3_setbit(z->flags[0], FW3_FLAG_HOTPLUG); else - delbit(z->flags[0], FW3_FLAG_HOTPLUG); + fw3_delbit(z->flags[0], FW3_FLAG_HOTPLUG); } } }