Blob Blame History Raw
From 8d480dea4b3fd4ecce20c1569d000cb999dd50f6 Mon Sep 17 00:00:00 2001
From: Eric Garver <eric@garver.life>
Date: Sun, 19 Jan 2020 14:37:31 -0500
Subject: [PATCH 31/37] feat: nftables: support AllowZoneDrifting=yes

(cherry picked from commit 517a061c5886f2ebfb4aa7d73804aa7f3c5a3004)
(cherry picked from commit 92c5926bb9e493545f8d949ba00cbf72e4c7f202)
---
 src/firewall/core/nftables.py | 91 ++++++++++++++++++++---------------
 1 file changed, 52 insertions(+), 39 deletions(-)

diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
index cb8521fb7a5a..c8e893b5dbf6 100644
--- a/src/firewall/core/nftables.py
+++ b/src/firewall/core/nftables.py
@@ -208,8 +208,11 @@ class nftables(object):
 
                 index = zone_source_index_cache[family].index(zone_source)
             else:
-                index = len(zone_source_index_cache[family])
-                
+                if self._fw._allow_zone_drifting:
+                    index = 0
+                else:
+                    index = len(zone_source_index_cache[family])
+
             _verb_snippet = rule[verb]
             del rule[verb]
             if index == 0:
@@ -506,13 +509,14 @@ class nftables(object):
                                                     "prio": IPTABLES_TO_NFT_HOOK["raw"][chain][1]}}})
 
         for chain in ["PREROUTING"]:
-            default_rules.append({"add": {"chain": {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "name": "raw_%s_ZONES" % chain}}})
-            default_rules.append({"add": {"rule":  {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "chain": "raw_%s" % chain,
-                                                    "expr": [{"jump": {"target": "raw_%s_ZONES" % chain}}]}}})
+            for dispatch_suffix in ["ZONES_SOURCE", "ZONES"] if self._fw._allow_zone_drifting else ["ZONES"]:
+                default_rules.append({"add": {"chain": {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "name": "raw_%s_%s" % (chain, dispatch_suffix)}}})
+                default_rules.append({"add": {"rule":  {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "chain": "raw_%s" % chain,
+                                                        "expr": [{"jump": {"target": "raw_%s_%s" % (chain, dispatch_suffix)}}]}}})
 
         for chain in IPTABLES_TO_NFT_HOOK["mangle"].keys():
             default_rules.append({"add": {"chain": {"family": "inet",
@@ -521,13 +525,14 @@ class nftables(object):
                                                     "type": "filter",
                                                     "hook": "%s" % IPTABLES_TO_NFT_HOOK["mangle"][chain][0],
                                                     "prio": IPTABLES_TO_NFT_HOOK["mangle"][chain][1]}}})
-            default_rules.append({"add": {"chain": {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "name": "mangle_%s_ZONES" % chain}}})
-            default_rules.append({"add": {"rule":  {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "chain": "mangle_%s" % chain,
-                                                    "expr": [{"jump": {"target": "mangle_%s_ZONES" % chain}}]}}})
+            for dispatch_suffix in ["ZONES_SOURCE", "ZONES"] if self._fw._allow_zone_drifting else ["ZONES"]:
+                default_rules.append({"add": {"chain": {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "name": "mangle_%s_%s" % (chain, dispatch_suffix)}}})
+                default_rules.append({"add": {"rule":  {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "chain": "mangle_%s" % chain,
+                                                        "expr": [{"jump": {"target": "mangle_%s_%s" % (chain, dispatch_suffix)}}]}}})
 
         for family in ["ip", "ip6"]:
             for chain in IPTABLES_TO_NFT_HOOK["nat"].keys():
@@ -537,13 +542,15 @@ class nftables(object):
                                                         "type": "nat",
                                                         "hook": "%s" % IPTABLES_TO_NFT_HOOK["nat"][chain][0],
                                                         "prio": IPTABLES_TO_NFT_HOOK["nat"][chain][1]}}})
-                default_rules.append({"add": {"chain": {"family": family,
-                                                        "table": TABLE_NAME,
-                                                        "name": "nat_%s_ZONES" % chain}}})
-                default_rules.append({"add": {"rule":  {"family": family,
-                                                        "table": TABLE_NAME,
-                                                        "chain": "nat_%s" % chain,
-                                                        "expr": [{"jump": {"target": "nat_%s_ZONES" % chain}}]}}})
+
+                for dispatch_suffix in ["ZONES_SOURCE", "ZONES"] if self._fw._allow_zone_drifting else ["ZONES"]:
+                    default_rules.append({"add": {"chain": {"family": family,
+                                                            "table": TABLE_NAME,
+                                                            "name": "nat_%s_%s" % (chain, dispatch_suffix)}}})
+                    default_rules.append({"add": {"rule":  {"family": family,
+                                                            "table": TABLE_NAME,
+                                                            "chain": "nat_%s" % chain,
+                                                            "expr": [{"jump": {"target": "nat_%s_%s" % (chain, dispatch_suffix)}}]}}})
 
         for chain in IPTABLES_TO_NFT_HOOK["filter"].keys():
             default_rules.append({"add": {"chain": {"family": "inet",
@@ -554,9 +561,6 @@ class nftables(object):
                                                     "prio": IPTABLES_TO_NFT_HOOK["filter"][chain][1]}}})
 
         # filter, INPUT
-        default_rules.append({"add": {"chain": {"family": "inet",
-                                                "table": TABLE_NAME,
-                                                "name": "filter_%s_ZONES" % "INPUT"}}})
         default_rules.append({"add": {"rule":  {"family": "inet",
                                                 "table": TABLE_NAME,
                                                 "chain": "filter_%s" % "INPUT",
@@ -578,10 +582,14 @@ class nftables(object):
                                                                     "op": "==",
                                                                     "right": "lo"}},
                                                          {"accept": None}]}}})
-        default_rules.append({"add": {"rule":  {"family": "inet",
-                                                "table": TABLE_NAME,
-                                                "chain": "filter_%s" % "INPUT",
-                                                "expr": [{"jump": {"target": "filter_%s_ZONES" % "INPUT"}}]}}})
+        for dispatch_suffix in ["ZONES_SOURCE", "ZONES"] if self._fw._allow_zone_drifting else ["ZONES"]:
+            default_rules.append({"add": {"chain": {"family": "inet",
+                                                    "table": TABLE_NAME,
+                                                    "name": "filter_%s_%s" % ("INPUT", dispatch_suffix)}}})
+            default_rules.append({"add": {"rule":  {"family": "inet",
+                                                    "table": TABLE_NAME,
+                                                    "chain": "filter_%s" % "INPUT",
+                                                    "expr": [{"jump": {"target": "filter_%s_%s" % ("INPUT", dispatch_suffix)}}]}}})
         if log_denied != "off":
             default_rules.append({"add": {"rule":  {"family": "inet",
                                                     "table": TABLE_NAME,
@@ -610,10 +618,6 @@ class nftables(object):
                                                 "expr": [{"reject": {"type": "icmpx", "expr": "admin-prohibited"}}]}}})
 
         # filter, FORWARD
-        for direction in ["IN", "OUT"]:
-            default_rules.append({"add": {"chain": {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "name": "filter_%s_%s_ZONES" % ("FORWARD", direction)}}})
         default_rules.append({"add": {"rule":  {"family": "inet",
                                                 "table": TABLE_NAME,
                                                 "chain": "filter_%s" % "FORWARD",
@@ -636,10 +640,14 @@ class nftables(object):
                                                                     "right": "lo"}},
                                                          {"accept": None}]}}})
         for direction in ["IN", "OUT"]:
-            default_rules.append({"add": {"rule":  {"family": "inet",
-                                                    "table": TABLE_NAME,
-                                                    "chain": "filter_%s" % "FORWARD",
-                                                    "expr": [{"jump": {"target": "filter_%s_%s_ZONES" % ("FORWARD", direction)}}]}}})
+            for dispatch_suffix in ["ZONES_SOURCE", "ZONES"] if self._fw._allow_zone_drifting else ["ZONES"]:
+                default_rules.append({"add": {"chain": {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "name": "filter_%s_%s_%s" % ("FORWARD", direction, dispatch_suffix)}}})
+                default_rules.append({"add": {"rule":  {"family": "inet",
+                                                        "table": TABLE_NAME,
+                                                        "chain": "filter_%s" % "FORWARD",
+                                                        "expr": [{"jump": {"target": "filter_%s_%s_%s" % ("FORWARD", direction, dispatch_suffix)}}]}}})
         if log_denied != "off":
             default_rules.append({"add": {"rule":  {"family": "inet",
                                                     "table": TABLE_NAME,
@@ -778,12 +786,17 @@ class nftables(object):
             "OUTPUT": "daddr",
         }[chain]
 
+        if self._fw._allow_zone_drifting:
+            zone_dispatch_chain = "%s_%s_ZONES_SOURCE" % (table, chain)
+        else:
+            zone_dispatch_chain = "%s_%s_ZONES" % (table, chain)
+
         target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS[chain], zone=zone)
         action = "goto"
 
         rule = {"family": family,
                 "table": TABLE_NAME,
-                "chain": "%s_%s_ZONES" % (table, chain),
+                "chain": zone_dispatch_chain,
                 "expr": [self._rule_addr_fragment(opt, address),
                          {action: {"target": "%s_%s" % (table, target)}}]}
         rule.update(self._zone_source_fragment(zone, address))
-- 
2.23.0