From 17c70eba7ddfd8a8687b16102cf5ee988e33993f Mon Sep 17 00:00:00 2001 From: Eric Garver Date: Mon, 30 Jan 2023 16:42:50 -0500 Subject: [PATCH 29/30] v2.0.0: feat(direct): avoid iptables flush if using nftables backend If FirewallBackend=nftables and there are no direct rules; then we can avoid flushing iptables at startup and shutdown. This means other applications can control iptables while firewalld only touches nftables. Fixes: #863 (cherry picked from commit b7faa74db15e2d1ebd9fdfcdc7579874d3a2fa87) --- src/firewall/core/fw.py | 31 +++++++++++++++++++++++++++---- src/firewall/core/fw_direct.py | 9 +++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py index 5cef18b5f889..a2ad39bd9f5f 100644 --- a/src/firewall/core/fw.py +++ b/src/firewall/core/fw.py @@ -425,7 +425,8 @@ class Firewall(object): transaction = FirewallTransaction(self) # flush rules - self.flush(use_transaction=transaction) + if not reload: + self.flush(use_transaction=transaction) # If modules need to be unloaded in complete reload or if there are # ipsets to get applied, limit the transaction to flush. @@ -836,7 +837,26 @@ class Firewall(object): if use_transaction is None: transaction.execute(True) - # flush and policy + def may_skip_flush_direct_backends(self): + if self.nftables_enabled and not self.direct.has_runtime_configuration(): + return True + + return False + + def flush_direct_backends(self, use_transaction=None): + if use_transaction is None: + transaction = FirewallTransaction(self) + else: + transaction = use_transaction + + for backend in self.all_backends(): + if backend in self.enabled_backends(): + continue + rules = backend.build_flush_rules() + transaction.add_rules(backend, rules) + + if use_transaction is None: + transaction.execute(True) def flush(self, use_transaction=None): if use_transaction is None: @@ -846,7 +866,10 @@ class Firewall(object): log.debug1("Flushing rule set") - for backend in self.all_backends(): + if not self.may_skip_flush_direct_backends(): + self.flush_direct_backends(use_transaction=transaction) + + for backend in self.enabled_backends(): rules = backend.build_flush_rules() transaction.add_rules(backend, rules) @@ -1002,7 +1025,7 @@ class Firewall(object): if not _panic: self.set_policy("DROP") - # stop + self.flush() self.cleanup() start_exception = None diff --git a/src/firewall/core/fw_direct.py b/src/firewall/core/fw_direct.py index a35ebce1f276..5d4cc6a6918e 100644 --- a/src/firewall/core/fw_direct.py +++ b/src/firewall/core/fw_direct.py @@ -219,6 +219,9 @@ class FirewallDirect(object): else: transaction = use_transaction + if self._fw.may_skip_flush_direct_backends(): + transaction.add_pre(self._fw.flush_direct_backends) + #TODO: policy="ACCEPT" self._chain(True, ipv, table, chain, transaction) @@ -265,6 +268,9 @@ class FirewallDirect(object): else: transaction = use_transaction + if self._fw.may_skip_flush_direct_backends(): + transaction.add_pre(self._fw.flush_direct_backends) + self._rule(True, ipv, table, chain, priority, args, transaction) if use_transaction is None: @@ -347,6 +353,9 @@ class FirewallDirect(object): else: transaction = use_transaction + if self._fw.may_skip_flush_direct_backends(): + transaction.add_pre(self._fw.flush_direct_backends) + self._passthrough(True, ipv, list(args), transaction) if use_transaction is None: -- 2.43.0