From 2c51165f99d57f89b036b15d8b5527b9283c159d Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Mon, 7 Jan 2019 20:51:17 -0800 Subject: [PATCH] firewalld: Flush iptables rules before restarting firewall This is a workaround for the problem that when restarting firewalld with iptables backend, flushing fails and starting with nftables also fails requiring a restart to recover the problem. Fixes #1440. Reviewed-by: Joseph Nuthalapati --- actions/firewall | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/actions/firewall b/actions/firewall index 18eec15fe..60635fcac 100755 --- a/actions/firewall +++ b/actions/firewall @@ -72,6 +72,36 @@ def parse_arguments(): return parser.parse_args() +def _flush_iptables_rules(): + """Flush firewalld iptables rules before restarting it. + + This is workaround for + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914694 + + This workaround can be removed if the bug is fixed or if firewalld starts + defaulting to nftables again. + + The bug leads to firewalld failing to flush rules when there are custom + chains in the rules. This only happens on firewalld iptables backend when + nftables is running with iptables compatibility. + + Flushing the tables before a restart will make the restart succeed and + after the restart nftables backend is used avoiding the problem. + + """ + rule_template = '*{table}\n-F\n-X\n-Z\nCOMMIT\n' + iptables_rules = '' + ip6tables_rules = '' + for table in ['security', 'raw', 'mangle', 'nat', 'filter']: + iptables_rules += rule_template.format(table=table) + ip6tables_rules += rule_template.format(table=table) + + subprocess.run(['iptables-restore'], input=iptables_rules.encode(), + check=True) + subprocess.run(['ip6tables-restore'], input=iptables_rules.encode(), + check=True) + + def set_firewall_backend(backend): """Set FirewallBackend attribute to the specified string.""" conf_file = '/etc/firewalld/firewalld.conf' @@ -83,16 +113,21 @@ def set_firewall_backend(backend): aug.set('/augeas/load/Shellvars/incl[last() + 1]', conf_file) aug.load() + old_backend = aug.get('/files/{}/FirewallBackend'.format(conf_file)) aug.set('/files/{}/FirewallBackend'.format(conf_file), '{}'.format(backend)) aug.save() - action_utils.service_enable('firewalld') - action_utils.service_restart('firewalld') + if old_backend == 'iptables': + _flush_iptables_rules() + + if backend != old_backend: + action_utils.service_restart('firewalld') def subcommand_setup(_): """Perform basic firewalld setup.""" + action_utils.service_enable('firewalld') subprocess.call(['firewall-cmd', '--set-default-zone=external']) set_firewall_backend('nftables')