Blame SOURCES/firewalld-0.7-0003-RFC3964_IPv4-Use-filter-table-instead-of-raw.patch

21c891
From ca0695dd53ad321d89906d190b93a5898cb40220 Mon Sep 17 00:00:00 2001
21c891
From: Eric Garver <eric@garver.life>
21c891
Date: Thu, 10 Jan 2019 10:10:12 -0500
21c891
Subject: [PATCH 3/3] RFC3964_IPv4: Use filter table instead of raw
21c891
21c891
This allows us to use the reject statement, which is more useful to
21c891
provide feedback to senders.
21c891
21c891
Fixes: 5afa02271418 ("nftables: support RFC3964_IPv4 filtering")
21c891
Fixes: b86206ed1590 ("ipXtables: support RFC3964_IPv4 filtering")
21c891
(cherry picked from commit 44200d0f508a990c5dfff9f480a6206ec507e229)
21c891
---
21c891
 src/firewall/core/fw.py            |  12 ++-
21c891
 src/firewall/core/ipXtables.py     |  24 +++--
21c891
 src/firewall/core/nftables.py      |  20 ++--
21c891
 src/tests/features/rfc3964_ipv4.at | 159 +++++++++++++++--------------
21c891
 4 files changed, 122 insertions(+), 93 deletions(-)
21c891
21c891
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
21c891
index a3089ce70eb8..66f4d9508afa 100644
21c891
--- a/src/firewall/core/fw.py
21c891
+++ b/src/firewall/core/fw.py
21c891
@@ -822,9 +822,15 @@ class Firewall(object):
21c891
                 rules = ipv6_backend.build_rpfilter_rules(self._log_denied)
21c891
                 transaction.add_rules(ipv6_backend, rules)
21c891
 
21c891
-            if self._rfc3964_ipv4:
21c891
-                rules = ipv6_backend.build_rfc3964_ipv4_rules()
21c891
-                transaction.add_rules(ipv6_backend, rules)
21c891
+        if self._rfc3964_ipv4:
21c891
+            # Flush due to iptables-restore (nftables) bug tiggered when
21c891
+            # specifying same index multiple times in same batch
21c891
+            # rhbz 1647925
21c891
+            transaction.execute(True)
21c891
+            transaction.clear()
21c891
+
21c891
+            rules = ipv6_backend.build_rfc3964_ipv4_rules()
21c891
+            transaction.add_rules(ipv6_backend, rules)
21c891
 
21c891
         else:
21c891
             if use_transaction is None:
21c891
diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
21c891
index c5b17aa3a846..1355a473f792 100644
21c891
--- a/src/firewall/core/ipXtables.py
21c891
+++ b/src/firewall/core/ipXtables.py
21c891
@@ -1320,13 +1320,23 @@ class ip6tables(ip4tables):
21c891
                      "2002:e000::/19", # 224.0.0.0/4 (multicast), 240.0.0.0/4 (reserved and broadcast)
21c891
                      ]
21c891
 
21c891
+        chain_name = "RFC3964_IPv4"
21c891
+        self.our_chains["filter"].add(chain_name)
21c891
+
21c891
         rules = []
21c891
+        rules.append(["-t", "filter", "-N", chain_name])
21c891
         for daddr in daddr_list:
21c891
-            for chain in ["PREROUTING", "OUTPUT"]:
21c891
-                rules.append(["-t", "raw", "-I", chain,
21c891
-                              "-d", daddr, "-j", "DROP"])
21c891
-                if self._fw._log_denied in ["unicast", "all"]:
21c891
-                    rules.append(["-t", "raw", "-I", chain,
21c891
-                                  "-d", daddr, "-j", "LOG",
21c891
-                                  "--log-prefix", "\"RFC3964_IPv4_DROP: \""])
21c891
+            rules.append(["-t", "filter", "-I", chain_name,
21c891
+                          "-d", daddr, "-j", "REJECT", "--reject-with",
21c891
+                          "addr-unreach"])
21c891
+            if self._fw._log_denied in ["unicast", "all"]:
21c891
+                rules.append(["-t", "filter", "-I", chain_name,
21c891
+                              "-d", daddr, "-j", "LOG",
21c891
+                              "--log-prefix", "\"RFC3964_IPv4_REJECT: \""])
21c891
+
21c891
+        # Inject into FORWARD and OUTPUT chains
21c891
+        rules.append(["-t", "filter", "-I", "OUTPUT", "3",
21c891
+                      "-j", chain_name])
21c891
+        rules.append(["-t", "filter", "-I", "FORWARD", "4",
21c891
+                      "-j", chain_name])
21c891
         return rules
21c891
diff --git a/src/firewall/core/nftables.py b/src/firewall/core/nftables.py
21c891
index 1eb9c3fb94c2..94d8c2b155dc 100644
21c891
--- a/src/firewall/core/nftables.py
21c891
+++ b/src/firewall/core/nftables.py
21c891
@@ -54,7 +54,7 @@ IPTABLES_TO_NFT_HOOK = {
21c891
     #},
21c891
     "raw": {
21c891
         "PREROUTING": ("prerouting", -300 + NFT_HOOK_OFFSET),
21c891
-        "OUTPUT": ("output", -300 + NFT_HOOK_OFFSET),
21c891
+    #   "OUTPUT": ("output", -300 + NFT_HOOK_OFFSET),
21c891
     },
21c891
     "mangle": {
21c891
         "PREROUTING": ("prerouting", -150 + NFT_HOOK_OFFSET),
21c891
@@ -72,7 +72,7 @@ IPTABLES_TO_NFT_HOOK = {
21c891
     "filter": {
21c891
         "INPUT": ("input", 0 + NFT_HOOK_OFFSET),
21c891
         "FORWARD": ("forward", 0 + NFT_HOOK_OFFSET),
21c891
-    #   "OUTPUT": ("output", 0 + NFT_HOOK_OFFSET),
21c891
+        "OUTPUT": ("output", 0 + NFT_HOOK_OFFSET),
21c891
     },
21c891
 }
21c891
 
21c891
@@ -485,6 +485,9 @@ class nftables(object):
21c891
             default_rules.append("add rule inet %s filter_%s %%%%LOGTYPE%%%% log prefix '\"FINAL_REJECT: \"'" % (TABLE_NAME, "FORWARD"))
21c891
         default_rules.append("add rule inet %s filter_%s reject with icmpx type admin-prohibited" % (TABLE_NAME, "FORWARD"))
21c891
 
21c891
+        # filter, OUTPUT
21c891
+        default_rules.append("add rule inet %s filter_%s oifname lo accept" % (TABLE_NAME, "OUTPUT"))
21c891
+
21c891
         self.our_chains["inet"]["filter"] = set(["INPUT_ZONES_SOURCE",
21c891
                                                  "INPUT_ZONES",
21c891
                                                  "FORWARD_IN_ZONES_SOURCE",
21c891
@@ -1260,13 +1263,16 @@ class nftables(object):
21c891
 
21c891
         rule_fragment = ["ip6", "daddr"] + daddr_set
21c891
         if self._fw._log_denied in ["unicast", "all"]:
21c891
-            rule_fragment += ["log", "prefix", "\"RFC3964_IPv4_DROP: \""]
21c891
-        rule_fragment += ["drop"]
21c891
+            rule_fragment += ["log", "prefix", "\"RFC3964_IPv4_REJECT: \""]
21c891
+        rule_fragment += ["reject"]
21c891
+        rule_fragment += self._reject_types_fragment("addr-unreach")
21c891
 
21c891
         rules = []
21c891
-        for chain in ["PREROUTING", "OUTPUT"]:
21c891
-            rules.append(["insert", "rule", "inet", "%s" % TABLE_NAME,
21c891
-                          "raw_%s" % chain] + rule_fragment)
21c891
+        # WARN: index must be kept in sync with build_default_rules()
21c891
+        rules.append(["add", "rule", "inet", "%s" % TABLE_NAME,
21c891
+                      "filter_OUTPUT", "index", "0"] + rule_fragment)
21c891
+        rules.append(["add", "rule", "inet", "%s" % TABLE_NAME,
21c891
+                      "filter_FORWARD", "index", "1"] + rule_fragment)
21c891
         return rules
21c891
 
21c891
     def build_zone_rich_source_destination_rules(self, enable, zone, rich_rule):
21c891
diff --git a/src/tests/features/rfc3964_ipv4.at b/src/tests/features/rfc3964_ipv4.at
21c891
index ea8dd40bb5c3..a93aba192c2c 100644
21c891
--- a/src/tests/features/rfc3964_ipv4.at
21c891
+++ b/src/tests/features/rfc3964_ipv4.at
21c891
@@ -5,74 +5,70 @@ AT_CHECK([sed -i 's/^RFC3964_IPv4.*/RFC3964_IPv4=yes/' ./firewalld.conf])
21c891
 FWD_RELOAD
21c891
 
21c891
 m4_if(nftables, FIREWALL_BACKEND, [
21c891
-    NFT_LIST_RULES([inet], [raw_PREROUTING], 0, [dnl
21c891
+    NFT_LIST_RULES([inet], [filter_FORWARD], 0, [dnl
21c891
         table inet firewalld {
21c891
-        chain raw_PREROUTING {
21c891
-        ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } log prefix "RFC3964_IPv4_DROP: " drop
21c891
-        m4_if(yes, HOST_SUPPORTS_NFT_FIB, [dnl
21c891
-            icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept
21c891
-            meta nfproto ipv6 fib saddr . iif oif missing log prefix "rpfilter_DROP: " drop
21c891
-        ])dnl
21c891
-        jump raw_PREROUTING_ZONES_SOURCE
21c891
-        jump raw_PREROUTING_ZONES
21c891
+        chain filter_FORWARD {
21c891
+        ct state established,related accept
21c891
+        iifname "lo" accept
21c891
+        ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } log prefix "RFC3964_IPv4_REJECT: " reject with icmpv6 type addr-unreachable
21c891
+        jump filter_FORWARD_IN_ZONES_SOURCE
21c891
+        jump filter_FORWARD_IN_ZONES
21c891
+        jump filter_FORWARD_OUT_ZONES_SOURCE
21c891
+        jump filter_FORWARD_OUT_ZONES
21c891
+        ct state invalid log prefix "STATE_INVALID_DROP: "
21c891
+        ct state invalid drop
21c891
+        log prefix "FINAL_REJECT: "
21c891
+        reject with icmpx type admin-prohibited
21c891
         }
21c891
         }
21c891
     ])
21c891
-    NFT_LIST_RULES([inet], [raw_OUTPUT], 0, [dnl
21c891
+    NFT_LIST_RULES([inet], [filter_OUTPUT], 0, [dnl
21c891
         table inet firewalld {
21c891
-        chain raw_OUTPUT {
21c891
-        ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } log prefix "RFC3964_IPv4_DROP: " drop
21c891
+        chain filter_OUTPUT {
21c891
+        oifname "lo" accept
21c891
+        ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } log prefix "RFC3964_IPv4_REJECT: " reject with icmpv6 type addr-unreachable
21c891
         }
21c891
         }
21c891
     ])
21c891
 ], [
21c891
-    IP6TABLES_LIST_RULES([raw], [PREROUTING], 0, [dnl
21c891
-        LOG all ::/0 2002:e000::/19 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:e000::/19
21c891
-        LOG all ::/0 2002:a9fe::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:a9fe::/32
21c891
-        LOG all ::/0 2002:c0a8::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:c0a8::/32
21c891
-        LOG all ::/0 2002:ac10::/28 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:ac10::/28
21c891
-        LOG all ::/0 2002:7f00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:7f00::/24
21c891
-        LOG all ::/0 2002:a00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:a00::/24
21c891
-        LOG all ::/0 2002::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002::/24
21c891
-        LOG all ::/0 ::ffff:0.0.0.0/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 ::ffff:0.0.0.0/96
21c891
-        LOG all ::/0 ::/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 ::/96
21c891
-        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 134
21c891
-        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 135
21c891
-        LOG all ::/0 ::/0 rpfilter invert LOG flags 0 level 4 prefix "rpfilter_DROP: "
21c891
-        DROP all ::/0 ::/0 rpfilter invert
21c891
-        PREROUTING_direct all ::/0 ::/0
21c891
-        PREROUTING_ZONES_SOURCE all ::/0 ::/0
21c891
-        PREROUTING_ZONES all ::/0 ::/0
21c891
+    IP6TABLES_LIST_RULES([filter], [RFC3964_IPv4], 0, [dnl
21c891
+        LOG all ::/0 2002:e000::/19 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:e000::/19 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002:a9fe::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:a9fe::/32 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002:c0a8::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:c0a8::/32 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002:ac10::/28 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:ac10::/28 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002:7f00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:7f00::/24 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002:a00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002:a00::/24 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 2002::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 2002::/24 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 ::ffff:0.0.0.0/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 ::ffff:0.0.0.0/96 reject-with icmp6-addr-unreachable
21c891
+        LOG all ::/0 ::/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_REJECT: "
21c891
+        REJECT all ::/0 ::/96 reject-with icmp6-addr-unreachable
21c891
     ])
21c891
-    IP6TABLES_LIST_RULES([raw], [OUTPUT], 0, [dnl
21c891
-        LOG all ::/0 2002:e000::/19 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:e000::/19
21c891
-        LOG all ::/0 2002:a9fe::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:a9fe::/32
21c891
-        LOG all ::/0 2002:c0a8::/32 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:c0a8::/32
21c891
-        LOG all ::/0 2002:ac10::/28 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:ac10::/28
21c891
-        LOG all ::/0 2002:7f00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:7f00::/24
21c891
-        LOG all ::/0 2002:a00::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002:a00::/24
21c891
-        LOG all ::/0 2002::/24 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 2002::/24
21c891
-        LOG all ::/0 ::ffff:0.0.0.0/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 ::ffff:0.0.0.0/96
21c891
-        LOG all ::/0 ::/96 LOG flags 0 level 4 prefix "RFC3964_IPv4_DROP: "
21c891
-        DROP all ::/0 ::/96
21c891
+    IP6TABLES_LIST_RULES([filter], [FORWARD], 0, [dnl
21c891
+        ACCEPT all ::/0 ::/0 ctstate RELATED,ESTABLISHED
21c891
+        ACCEPT all ::/0 ::/0
21c891
+        FORWARD_direct all ::/0 ::/0
21c891
+        RFC3964_IPv4 all ::/0 ::/0
21c891
+        FORWARD_IN_ZONES_SOURCE all ::/0 ::/0
21c891
+        FORWARD_IN_ZONES all ::/0 ::/0
21c891
+        FORWARD_OUT_ZONES_SOURCE all ::/0 ::/0
21c891
+        FORWARD_OUT_ZONES all ::/0 ::/0
21c891
+        LOG all ::/0 ::/0 ctstate INVALID LOG flags 0 level 4 prefix "STATE_INVALID_DROP: "
21c891
+        DROP all ::/0 ::/0 ctstate INVALID
21c891
+        LOG all ::/0 ::/0 LOG flags 0 level 4 prefix "FINAL_REJECT: "
21c891
+        REJECT all ::/0 ::/0 reject-with icmp6-adm-prohibited
21c891
+    ])
21c891
+    IP6TABLES_LIST_RULES([filter], [OUTPUT], 0, [dnl
21c891
+        ACCEPT all ::/0 ::/0
21c891
         OUTPUT_direct all ::/0 ::/0
21c891
+        RFC3964_IPv4 all ::/0 ::/0
21c891
     ])
21c891
 ])
21c891
 
21c891
@@ -80,35 +76,46 @@ AT_CHECK([sed -i 's/^RFC3964_IPv4.*/RFC3964_IPv4=no/' ./firewalld.conf])
21c891
 FWD_RELOAD
21c891
 
21c891
 m4_if(nftables, FIREWALL_BACKEND, [
21c891
-    NFT_LIST_RULES([inet], [raw_PREROUTING], 0, [dnl
21c891
+    NFT_LIST_RULES([inet], [filter_FORWARD], 0, [dnl
21c891
         table inet firewalld {
21c891
-        chain raw_PREROUTING {
21c891
-        m4_if(yes, HOST_SUPPORTS_NFT_FIB, [dnl
21c891
-            icmpv6 type { nd-router-advert, nd-neighbor-solicit } accept
21c891
-            meta nfproto ipv6 fib saddr . iif oif missing log prefix "rpfilter_DROP: " drop
21c891
-        ])dnl
21c891
-        jump raw_PREROUTING_ZONES_SOURCE
21c891
-        jump raw_PREROUTING_ZONES
21c891
+        chain filter_FORWARD {
21c891
+        ct state established,related accept
21c891
+        iifname "lo" accept
21c891
+        jump filter_FORWARD_IN_ZONES_SOURCE
21c891
+        jump filter_FORWARD_IN_ZONES
21c891
+        jump filter_FORWARD_OUT_ZONES_SOURCE
21c891
+        jump filter_FORWARD_OUT_ZONES
21c891
+        ct state invalid log prefix "STATE_INVALID_DROP: "
21c891
+        ct state invalid drop
21c891
+        log prefix "FINAL_REJECT: "
21c891
+        reject with icmpx type admin-prohibited
21c891
         }
21c891
         }
21c891
     ])
21c891
-    NFT_LIST_RULES([inet], [raw_OUTPUT], 0, [dnl
21c891
+    NFT_LIST_RULES([inet], [filter_OUTPUT], 0, [dnl
21c891
         table inet firewalld {
21c891
-        chain raw_OUTPUT {
21c891
+        chain filter_OUTPUT {
21c891
+        oifname "lo" accept
21c891
         }
21c891
         }
21c891
     ])
21c891
 ], [
21c891
-    IP6TABLES_LIST_RULES([raw], [PREROUTING], 0, [dnl
21c891
-        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 134
21c891
-        ACCEPT icmpv6 ::/0 ::/0 ipv6-icmptype 135
21c891
-        LOG all ::/0 ::/0 rpfilter invert LOG flags 0 level 4 prefix "rpfilter_DROP: "
21c891
-        DROP all ::/0 ::/0 rpfilter invert
21c891
-        PREROUTING_direct all ::/0 ::/0
21c891
-        PREROUTING_ZONES_SOURCE all ::/0 ::/0
21c891
-        PREROUTING_ZONES all ::/0 ::/0
21c891
+    NS_CHECK([ip6tables -w -n -t filter -L RFC3964_IPv4], 1, [ignore], [ignore])
21c891
+    IP6TABLES_LIST_RULES([filter], [FORWARD], 0, [dnl
21c891
+        ACCEPT all ::/0 ::/0 ctstate RELATED,ESTABLISHED
21c891
+        ACCEPT all ::/0 ::/0
21c891
+        FORWARD_direct all ::/0 ::/0
21c891
+        FORWARD_IN_ZONES_SOURCE all ::/0 ::/0
21c891
+        FORWARD_IN_ZONES all ::/0 ::/0
21c891
+        FORWARD_OUT_ZONES_SOURCE all ::/0 ::/0
21c891
+        FORWARD_OUT_ZONES all ::/0 ::/0
21c891
+        LOG all ::/0 ::/0 ctstate INVALID LOG flags 0 level 4 prefix "STATE_INVALID_DROP: "
21c891
+        DROP all ::/0 ::/0 ctstate INVALID
21c891
+        LOG all ::/0 ::/0 LOG flags 0 level 4 prefix "FINAL_REJECT: "
21c891
+        REJECT all ::/0 ::/0 reject-with icmp6-adm-prohibited
21c891
     ])
21c891
-    IP6TABLES_LIST_RULES([raw], [OUTPUT], 0, [dnl
21c891
+    IP6TABLES_LIST_RULES([filter], [OUTPUT], 0, [dnl
21c891
+        ACCEPT all ::/0 ::/0
21c891
         OUTPUT_direct all ::/0 ::/0
21c891
     ])
21c891
 ])
21c891
-- 
21c891
2.18.0
21c891