fw4: fix emitting family specific redirect rules without any addrs
authorJo-Philipp Wich <jo@mein.io>
Sat, 2 Apr 2022 18:27:25 +0000 (20:27 +0200)
committerJo-Philipp Wich <jo@mein.io>
Sat, 2 Apr 2022 18:27:25 +0000 (20:27 +0200)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
root/usr/share/ucode/fw4.uc
tests/03_rules/07_redirect

index 8e38a5cc15fe26ca35ba24d93010eaaa22958c39..0659af6ce562deb8a84d118708a3f4e64ff14dc2 100644 (file)
@@ -2830,8 +2830,12 @@ return {
                        if (length(rip[0]) > 1 || length(rip[1]) > 1)
                                this.warn_section(data, "specifies multiple rewrite addresses, using only first one");
 
+                       let has_ip4_addr = length(sip[0]) || length(dip[0]) || length(rip[0]),
+                           has_ip6_addr = length(sip[1]) || length(dip[1]) || length(rip[1]),
+                           has_any_addr = has_ip4_addr || has_ip6_addr;
+
                        /* check if there's no AF specific bits, in this case we can do an AF agnostic rule */
-                       if (!family && !length(sip[0]) && !length(sip[1]) && !length(dip[0]) && !length(dip[1]) && !length(rip[0]) && !length(rip[1])) {
+                       if (!family && !has_any_addr) {
                                /* for backwards compatibility, treat unspecified family as IPv4 unless user explicitly requested any (0) */
                                if (family == null)
                                        family = 4;
@@ -2841,13 +2845,13 @@ return {
 
                        /* we need to emit one or two AF specific rules */
                        else {
-                               if ((!family || family == 4) && (length(sip[0]) || length(dip[0]) || length(rip[0]))) {
+                               if ((!family || family == 4) && (!has_any_addr || has_ip4_addr)) {
                                        for (let saddrs in subnets_group_by_masking(sip[0]))
                                                for (let daddrs in subnets_group_by_masking(dip[0]))
                                                        add_rule(4, proto, saddrs, daddrs, rip[0], sport, dport, rport, ipset, redir);
                                }
 
-                               if ((!family || family == 6) && (length(sip[1]) || length(dip[1]) || length(rip[1]))) {
+                               if ((!family || family == 6) && (!has_any_addr || has_ip6_addr)) {
                                        for (let saddrs in subnets_group_by_masking(sip[1]))
                                                for (let daddrs in subnets_group_by_masking(dip[1]))
                                                        add_rule(6, proto, saddrs, daddrs, rip[1], sport, dport, rport, ipset, redir);
index f9292ea154bdcc648ec3f2dced0575e2e0c72e10..90b845bd2056839076ace34ec22587358c4e70ef 100644 (file)
@@ -97,6 +97,28 @@ Test various address selection rules in redirect rules.
                        "dest_ip": "2001:db8:1000:1::1234",
                        "dest_port": "25",
                        "target": "dnat"
+               },
+               {
+                       ".description": "Ensure that family restricted redirect rules work properly",
+                       "name": "Redirect test #7",
+                       "family": "ipv4",
+                       "src": "wan",
+                       "dest": "lan",
+                       "proto": "tcp",
+                       "src_dport": "26",
+                       "dest_port": "26",
+                       "target": "dnat"
+               },
+               {
+                       ".description": "Ensure that family restricted redirect rules work properly",
+                       "name": "Redirect test #8",
+                       "family": "ipv6",
+                       "src": "wan",
+                       "dest": "lan",
+                       "proto": "tcp",
+                       "src_dport": "27",
+                       "dest_port": "27",
+                       "target": "dnat"
                }
        ]
 }
@@ -268,6 +290,8 @@ table inet fw4 {
                meta nfproto ipv4 tcp dport 22 counter dnat 192.168.26.100:22 comment "!fw4: Redirect test #3"
                meta nfproto ipv4 tcp dport 23 counter dnat 192.168.26.100:23 comment "!fw4: Redirect test #4"
                meta nfproto ipv6 tcp dport 25 counter dnat [2001:db8:1000:1::1234]:25 comment "!fw4: Redirect test #6"
+               meta nfproto ipv4 tcp dport 26 counter redirect to 26 comment "!fw4: Redirect test #7"
+               meta nfproto ipv6 tcp dport 27 counter redirect to 27 comment "!fw4: Redirect test #8"
        }
 
        chain srcnat_wan {