[OpenWrt-Devel] Add support to define multiple zones for dnat redirection reflection rules

Message ID 1536946275-21465-1-git-send-email-engelhardt.anton@gmail.com
State New
Delegated to: Jo-Philipp Wich
Headers show
Series
  • [OpenWrt-Devel] Add support to define multiple zones for dnat redirection reflection rules
Related show

Commit Message

Anton Engelhardt Sept. 14, 2018, 5:31 p.m.
Added new config option for redirect, which accespts 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
        option reflection_zones 'lan devices servers'
reflection rules will get added for all and only the given zones.

Reflection is therefore also possible like this
       option reflection_zones 'lan devices'
Which enables to create a redirection to zone servers, without a reflection rule for that zone.

Not setting that option results in the old behaviour.

Tested on x86 master and 18.06.

Signed-off-by: Anton Engelhardt <engelhardt.anton@gmail.com>
---
 options.h   |  2 ++
 redirects.c | 58 ++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 42 insertions(+), 18 deletions(-)

Patch

diff --git a/options.h b/options.h
index a75cfa3..2804f98 100644
--- a/options.h
+++ b/options.h
@@ -441,6 +441,8 @@  struct fw3_redirect
 	bool local;
 	bool reflection;
 	enum fw3_reflection_source reflection_src;
+	struct list_head reflection_zones;
+	struct list_head *_reflection_zones;
 };
 
 struct fw3_snat
diff --git a/redirects.c b/redirects.c
index 6cd09f1..2f899a3 100644
--- a/redirects.c
+++ b/redirects.c
@@ -61,6 +61,7 @@  const struct fw3_option fw3_redirect_opts[] = {
 	FW3_OPT("reflection",          bool,      redirect,     reflection),
 	FW3_OPT("reflection_src",      reflection_source,
 	                                          redirect,     reflection_src),
+	FW3_LIST("reflection_zones",   device,    redirect,     reflection_zones),
 
 	FW3_OPT("target",              target,    redirect,     target),
 
@@ -367,6 +368,7 @@  fw3_alloc_redirect(struct fw3_state *state)
 
 	INIT_LIST_HEAD(&redir->proto);
 	INIT_LIST_HEAD(&redir->mac_src);
+	INIT_LIST_HEAD(&redir->reflection_zones);
 
 	redir->enabled = true;
 	redir->reflection = true;
@@ -612,7 +614,7 @@  static void
 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;
 
@@ -625,7 +627,7 @@  print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
 		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);
@@ -633,7 +635,7 @@  print_reflection(struct fw3_ipt_handle *h, struct fw3_state *state,
 		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);
 		break;
 
 	default:
@@ -649,6 +651,7 @@  expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
 	struct fw3_address *ext_addr, *int_addr, ref_addr;
 	struct fw3_protocol *proto;
 	struct fw3_mac *mac;
+	struct fw3_device *reflection_zone;
 
 	if (redir->name)
 		info("   * Redirect '%s'", redir->name);
@@ -698,6 +701,18 @@  expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
 		print_redirect(handle, state, redir, num, proto, mac);
 
 	/* reflection rules */
+	// use reflection_zones if set, else the redirection dest zone for reflection
+	struct fw3_device *dest;
+	if(list_empty(&redir->reflection_zones)) {
+		redir->_reflection_zones = calloc(1, sizeof(struct list_head));
+		INIT_LIST_HEAD(redir->_reflection_zones);
+		dest = calloc(1, sizeof(struct fw3_device));
+		memcpy((void *)dest, (void *)&redir->dest, sizeof(struct fw3_device));
+		list_add(&(dest->list), redir->_reflection_zones);
+	} else {
+		redir->_reflection_zones = &redir->reflection_zones;
+	}
+
 	if (redir->target != FW3_FLAG_DNAT || !redir->reflection || redir->local)
 		return;
 
@@ -705,9 +720,8 @@  expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
 		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)
+	if (!ext_addrs)
 		goto out;
 
 	list_for_each_entry(ext_addr, ext_addrs, list)
@@ -715,26 +729,34 @@  expand_redirect(struct fw3_ipt_handle *handle, struct fw3_state *state,
 		if (!fw3_is_family(ext_addr, handle->family))
 			continue;
 
-		list_for_each_entry(int_addr, int_addrs, list)
+		list_for_each_entry(reflection_zone, redir->_reflection_zones, list)
 		{
-			if (!fw3_is_family(int_addr, handle->family))
+			struct fw3_zone *zone = fw3_lookup_zone(state, reflection_zone->name);
+			if (!zone)
 				continue;
-
-			fw3_foreach(proto, &redir->proto)
+			
+			int_addrs = fw3_resolve_zone_addresses(zone, NULL);
+			list_for_each_entry(int_addr, int_addrs, list)
 			{
-				if (!proto)
+				if (!fw3_is_family(int_addr, handle->family))
 					continue;
 
-				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);
+				}
 			}
 		}
 	}