Message ID | ED9CFA6F-B8C3-4264-A22E-DEAF62DB3320@timothyace.com |
---|---|
State | Changes Requested |
Headers | show |
I've created a fork of the firewall3 git repo at git://nbd.name/firewall3.git on github repo, that contains this patch, for easier pulling: Please see: https://github.com/ecammit/firewall3 > On Aug 13, 2015, at 1:58 PM, Timothy Ace <openwrt.org-1@timothyace.com> wrote: > > From: Timothy Ace <openwrt.org-1@timothyace.com> > > Adds support for IPv6 DNAT, SNAT, and REDIRECT. > > Signed-off-by: Timothy Ace <openwrt.org-1@timothyace.com> > --- > This is a git patch for the firewall3 git repo at git://nbd.name/firewall3.git > > Note1: Luci updates still need to be made in a separate patch to support IPv6 address entry on the port forwards page, but this works using manual entries in /etc/config/firewall for now. > > Note2: I changed the section in compare_addr() from this: > > - return ((a->address.v4.s_addr & a->mask.v4.s_addr) == > - (b->address.v4.s_addr & a->mask.v4.s_addr)); > > to this: > > + return ((a->address.v4.s_addr & a->mask.v4.s_addr) == > + (b->address.v4.s_addr & b->mask.v4.s_addr)); > > ... because using "a->mask" instead of "b->mask" on the second line looked wrong to me. Please let me know if that was intentional and I'll re-submit a patch that accounts for that change for the v4 and new v6 sections. > > > From 83cdcf604b8c81c75065a91f50459721e87740b0 Mon Sep 17 00:00:00 2001 > From: Timothy Ace <openwrt.org-1@timothyace.com> > Date: Thu, 13 Aug 2015 00:28:02 -0400 > Subject: [PATCH] Adds support for IPv6 DNAT, SNAT, and REDIRECT > > --- > defaults.c | 8 ++++---- > redirects.c | 42 ++++++++++++++++++++++++++++++++++-------- > snats.c | 1 + > ubus.c | 24 ++++++++++++++++++++---- > utils.c | 10 ++++++++-- > zones.c | 13 ++++++++----- > 6 files changed, 75 insertions(+), 23 deletions(-) > > diff --git a/defaults.c b/defaults.c > index 396cbf7..45d6de6 100644 > --- a/defaults.c > +++ b/defaults.c > @@ -32,10 +32,10 @@ static const struct fw3_chain_spec default_chains[] = { > C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"), > C(ANY, FILTER, SYN_FLOOD, "syn_flood"), > > - C(V4, NAT, UNSPEC, "delegate_prerouting"), > - C(V4, NAT, UNSPEC, "delegate_postrouting"), > - C(V4, NAT, CUSTOM_CHAINS, "prerouting_rule"), > - C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"), > + C(ANY, NAT, UNSPEC, "delegate_prerouting"), > + C(ANY, NAT, UNSPEC, "delegate_postrouting"), > + C(ANY, NAT, CUSTOM_CHAINS, "prerouting_rule"), > + C(ANY, NAT, CUSTOM_CHAINS, "postrouting_rule"), > > C(ANY, MANGLE, UNSPEC, "mssfix"), > C(ANY, MANGLE, UNSPEC, "fwmark"), > diff --git a/redirects.c b/redirects.c > index 5b8d7a9..0751e93 100644 > --- a/redirects.c > +++ b/redirects.c > @@ -116,11 +116,26 @@ check_families(struct uci_element *e, struct fw3_redirect *r) > static bool > compare_addr(struct fw3_address *a, struct fw3_address *b) > { > - if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4) > + if (a->family != b->family) > return false; > > - return ((a->address.v4.s_addr & a->mask.v4.s_addr) == > - (b->address.v4.s_addr & a->mask.v4.s_addr)); > + if (a->family == FW3_FAMILY_V4) > + { > + return ((a->address.v4.s_addr & a->mask.v4.s_addr) == > + (b->address.v4.s_addr & b->mask.v4.s_addr)); > + } > + else if (a->family == FW3_FAMILY_V6) > + { > + int i; > + for (i = 0; i < 16; i++) > + { > + if ((a->address.v6.s6_addr[i] & a->mask.v6.s6_addr[i]) != > + (b->address.v6.s6_addr[i] & b->mask.v6.s6_addr[i])) > + return false; > + } > + return true; > + } > + return false; > } > > static bool > @@ -278,6 +293,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) > else > { > set(redir->_src->flags, FW3_FAMILY_V4, redir->target); > + set(redir->_src->flags, FW3_FAMILY_V6, redir->target); > redir->_src->conntrack = true; > valid = true; > > @@ -293,6 +309,9 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) > set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_ACCEPT); > set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_DNAT); > set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT); > + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_ACCEPT); > + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_DNAT); > + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT); > } > } > } > @@ -309,6 +328,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) > else > { > set(redir->_dest->flags, FW3_FAMILY_V4, redir->target); > + set(redir->_dest->flags, FW3_FAMILY_V6, redir->target); > redir->_dest->conntrack = true; > valid = true; > } > @@ -364,13 +384,22 @@ static void > set_snat_dnat(struct fw3_ipt_rule *r, enum fw3_flag target, > struct fw3_address *addr, struct fw3_port *port) > { > - char buf[sizeof("255.255.255.255:65535-65535\0")]; > + char buf[INET6_ADDRSTRLEN + sizeof("[]:65535-65535\0")]; > > buf[0] = '\0'; > > if (addr && addr->set) > { > - inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); > + if (addr->family == FW3_FAMILY_V4) > + { > + inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); > + } > + else if (addr->family == FW3_FAMILY_V6) > + { > + buf[0] = '['; > + inet_ntop(AF_INET6, &addr->address.v6, buf + 1, sizeof(buf) - 2); > + sprintf(buf + strlen(buf), "]"); > + } > } > > if (port && port->set) > @@ -607,9 +636,6 @@ fw3_print_redirects(struct fw3_ipt_handle *handle, struct fw3_state *state) > int num = 0; > struct fw3_redirect *redir; > > - if (handle->family == FW3_FAMILY_V6) > - return; > - > if (handle->table != FW3_TABLE_FILTER && handle->table != FW3_TABLE_NAT) > return; > > diff --git a/snats.c b/snats.c > index 0f7d851..1d22e33 100644 > --- a/snats.c > +++ b/snats.c > @@ -254,6 +254,7 @@ fw3_load_snats(struct fw3_state *state, struct uci_package *p, struct blob_attr > if (snat->_src) > { > set(snat->_src->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT); > + set(snat->_src->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT); > snat->_src->conntrack = true; > } > } > diff --git a/ubus.c b/ubus.c > index 9e034c8..4ae5c8b 100644 > --- a/ubus.c > +++ b/ubus.c > @@ -93,11 +93,27 @@ parse_subnet(enum fw3_family family, struct blob_attr *dict, int rem) > __blob_for_each_attr(cur, dict, rem) > { > if (!strcmp(blobmsg_name(cur), "address")) > - inet_pton(family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, > - blobmsg_get_string(cur), &addr->address.v6); > - > + { > + if (family == FW3_FAMILY_V4) > + { > + inet_pton(AF_INET, blobmsg_get_string(cur), &addr->address.v4); > + } > + else > + { > + inet_pton(AF_INET6, blobmsg_get_string(cur), &addr->address.v6); > + } > + } > else if (!strcmp(blobmsg_name(cur), "mask")) > - fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6); > + { > + if (family == FW3_FAMILY_V4) > + { > + fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v4); > + } > + else > + { > + fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6); > + } > + } > } > > return addr; > diff --git a/utils.c b/utils.c > index b2fbe02..4b8d44e 100644 > --- a/utils.c > +++ b/utils.c > @@ -882,8 +882,14 @@ fw3_flush_conntrack(void *state) > > if (!found) > { > - inet_ntop(addr->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, > - &addr->address.v4, buf, sizeof(buf)); > + if (addr->family == FW3_FAMILY_V4) > + { > + inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); > + } > + else > + { > + inet_ntop(AF_INET6, &addr->address.v6, buf, sizeof(buf)); > + } > > info(" * Flushing conntrack: %s", buf); > fprintf(ct, "%s\n", buf); > diff --git a/zones.c b/zones.c > index 2ddd7b4..ff2403f 100644 > --- a/zones.c > +++ b/zones.c > @@ -36,8 +36,8 @@ static const struct fw3_chain_spec zone_chains[] = { > C(ANY, FILTER, REJECT, "zone_%s_dest_REJECT"), > C(ANY, FILTER, DROP, "zone_%s_dest_DROP"), > > - C(V4, NAT, SNAT, "zone_%s_postrouting"), > - C(V4, NAT, DNAT, "zone_%s_prerouting"), > + C(ANY, NAT, SNAT, "zone_%s_postrouting"), > + C(ANY, NAT, DNAT, "zone_%s_prerouting"), > > C(ANY, RAW, NOTRACK, "zone_%s_notrack"), > > @@ -45,8 +45,8 @@ static const struct fw3_chain_spec zone_chains[] = { > C(ANY, FILTER, CUSTOM_CHAINS, "output_%s_rule"), > C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_%s_rule"), > > - C(V4, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"), > - C(V4, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"), > + C(ANY, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"), > + C(ANY, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"), > > { } > }; > @@ -217,13 +217,16 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) > if (zone->masq) > { > setbit(zone->flags[0], FW3_FLAG_SNAT); > + setbit(zone->flags[1], FW3_FLAG_SNAT); > zone->conntrack = true; > } > > if (zone->custom_chains) > { > setbit(zone->flags[0], FW3_FLAG_SNAT); > + setbit(zone->flags[1], FW3_FLAG_SNAT); > setbit(zone->flags[0], FW3_FLAG_DNAT); > + setbit(zone->flags[1], FW3_FLAG_DNAT); > } > > setbit(zone->flags[0], fw3_to_src_target(zone->policy_input)); > @@ -540,7 +543,7 @@ print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, > break; > > case FW3_TABLE_NAT: > - if (zone->masq && handle->family == FW3_FAMILY_V4) > + if (zone->masq) > { > fw3_foreach(msrc, &zone->masq_src) > fw3_foreach(mdest, &zone->masq_dest) > -- > 2.3.2 (Apple Git-55)
diff --git a/defaults.c b/defaults.c index 396cbf7..45d6de6 100644 --- a/defaults.c +++ b/defaults.c @@ -32,10 +32,10 @@ static const struct fw3_chain_spec default_chains[] = { C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"), C(ANY, FILTER, SYN_FLOOD, "syn_flood"), - C(V4, NAT, UNSPEC, "delegate_prerouting"), - C(V4, NAT, UNSPEC, "delegate_postrouting"), - C(V4, NAT, CUSTOM_CHAINS, "prerouting_rule"), - C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"), + C(ANY, NAT, UNSPEC, "delegate_prerouting"), + C(ANY, NAT, UNSPEC, "delegate_postrouting"), + C(ANY, NAT, CUSTOM_CHAINS, "prerouting_rule"), + C(ANY, NAT, CUSTOM_CHAINS, "postrouting_rule"), C(ANY, MANGLE, UNSPEC, "mssfix"), C(ANY, MANGLE, UNSPEC, "fwmark"), diff --git a/redirects.c b/redirects.c index 5b8d7a9..0751e93 100644 --- a/redirects.c +++ b/redirects.c @@ -116,11 +116,26 @@ check_families(struct uci_element *e, struct fw3_redirect *r) static bool compare_addr(struct fw3_address *a, struct fw3_address *b) { - if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4) + if (a->family != b->family) return false; - return ((a->address.v4.s_addr & a->mask.v4.s_addr) == - (b->address.v4.s_addr & a->mask.v4.s_addr)); + if (a->family == FW3_FAMILY_V4) + { + return ((a->address.v4.s_addr & a->mask.v4.s_addr) == + (b->address.v4.s_addr & b->mask.v4.s_addr)); + } + else if (a->family == FW3_FAMILY_V6) + { + int i; + for (i = 0; i < 16; i++) + { + if ((a->address.v6.s6_addr[i] & a->mask.v6.s6_addr[i]) != + (b->address.v6.s6_addr[i] & b->mask.v6.s6_addr[i])) + return false; + } + return true; + } + return false; } static bool @@ -278,6 +293,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) else { set(redir->_src->flags, FW3_FAMILY_V4, redir->target); + set(redir->_src->flags, FW3_FAMILY_V6, redir->target); redir->_src->conntrack = true; valid = true; @@ -293,6 +309,9 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_ACCEPT); set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_DNAT); set(redir->_dest->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT); + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_ACCEPT); + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_DNAT); + set(redir->_dest->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT); } } } @@ -309,6 +328,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) else { set(redir->_dest->flags, FW3_FAMILY_V4, redir->target); + set(redir->_dest->flags, FW3_FAMILY_V6, redir->target); redir->_dest->conntrack = true; valid = true; } @@ -364,13 +384,22 @@ static void set_snat_dnat(struct fw3_ipt_rule *r, enum fw3_flag target, struct fw3_address *addr, struct fw3_port *port) { - char buf[sizeof("255.255.255.255:65535-65535\0")]; + char buf[INET6_ADDRSTRLEN + sizeof("[]:65535-65535\0")]; buf[0] = '\0'; if (addr && addr->set) { - inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); + if (addr->family == FW3_FAMILY_V4) + { + inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); + } + else if (addr->family == FW3_FAMILY_V6) + { + buf[0] = '['; + inet_ntop(AF_INET6, &addr->address.v6, buf + 1, sizeof(buf) - 2); + sprintf(buf + strlen(buf), "]"); + } } if (port && port->set) @@ -607,9 +636,6 @@ fw3_print_redirects(struct fw3_ipt_handle *handle, struct fw3_state *state) int num = 0; struct fw3_redirect *redir; - if (handle->family == FW3_FAMILY_V6) - return; - if (handle->table != FW3_TABLE_FILTER && handle->table != FW3_TABLE_NAT) return; diff --git a/snats.c b/snats.c index 0f7d851..1d22e33 100644 --- a/snats.c +++ b/snats.c @@ -254,6 +254,7 @@ fw3_load_snats(struct fw3_state *state, struct uci_package *p, struct blob_attr if (snat->_src) { set(snat->_src->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT); + set(snat->_src->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT); snat->_src->conntrack = true; } } diff --git a/ubus.c b/ubus.c index 9e034c8..4ae5c8b 100644 --- a/ubus.c +++ b/ubus.c @@ -93,11 +93,27 @@ parse_subnet(enum fw3_family family, struct blob_attr *dict, int rem) __blob_for_each_attr(cur, dict, rem) { if (!strcmp(blobmsg_name(cur), "address")) - inet_pton(family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - blobmsg_get_string(cur), &addr->address.v6); - + { + if (family == FW3_FAMILY_V4) + { + inet_pton(AF_INET, blobmsg_get_string(cur), &addr->address.v4); + } + else + { + inet_pton(AF_INET6, blobmsg_get_string(cur), &addr->address.v6); + } + } else if (!strcmp(blobmsg_name(cur), "mask")) - fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6); + { + if (family == FW3_FAMILY_V4) + { + fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v4); + } + else + { + fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6); + } + } } return addr; diff --git a/utils.c b/utils.c index b2fbe02..4b8d44e 100644 --- a/utils.c +++ b/utils.c @@ -882,8 +882,14 @@ fw3_flush_conntrack(void *state) if (!found) { - inet_ntop(addr->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &addr->address.v4, buf, sizeof(buf)); + if (addr->family == FW3_FAMILY_V4) + { + inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf)); + } + else + { + inet_ntop(AF_INET6, &addr->address.v6, buf, sizeof(buf)); + } info(" * Flushing conntrack: %s", buf); fprintf(ct, "%s\n", buf); diff --git a/zones.c b/zones.c index 2ddd7b4..ff2403f 100644 --- a/zones.c +++ b/zones.c @@ -36,8 +36,8 @@ static const struct fw3_chain_spec zone_chains[] = { C(ANY, FILTER, REJECT, "zone_%s_dest_REJECT"), C(ANY, FILTER, DROP, "zone_%s_dest_DROP"), - C(V4, NAT, SNAT, "zone_%s_postrouting"), - C(V4, NAT, DNAT, "zone_%s_prerouting"), + C(ANY, NAT, SNAT, "zone_%s_postrouting"), + C(ANY, NAT, DNAT, "zone_%s_prerouting"), C(ANY, RAW, NOTRACK, "zone_%s_notrack"), @@ -45,8 +45,8 @@ static const struct fw3_chain_spec zone_chains[] = { C(ANY, FILTER, CUSTOM_CHAINS, "output_%s_rule"), C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_%s_rule"), - C(V4, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"), - C(V4, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"), + C(ANY, NAT, CUSTOM_CHAINS, "prerouting_%s_rule"), + C(ANY, NAT, CUSTOM_CHAINS, "postrouting_%s_rule"), { } }; @@ -217,13 +217,16 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p) if (zone->masq) { setbit(zone->flags[0], FW3_FLAG_SNAT); + setbit(zone->flags[1], FW3_FLAG_SNAT); zone->conntrack = true; } if (zone->custom_chains) { setbit(zone->flags[0], FW3_FLAG_SNAT); + setbit(zone->flags[1], FW3_FLAG_SNAT); setbit(zone->flags[0], FW3_FLAG_DNAT); + setbit(zone->flags[1], FW3_FLAG_DNAT); } setbit(zone->flags[0], fw3_to_src_target(zone->policy_input)); @@ -540,7 +543,7 @@ print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, break; case FW3_TABLE_NAT: - if (zone->masq && handle->family == FW3_FAMILY_V4) + if (zone->masq) { fw3_foreach(msrc, &zone->masq_src) fw3_foreach(mdest, &zone->masq_dest)