From 1ceae64feaf4b6179d8afe97189d7078cff7409e Mon Sep 17 00:00:00 2001 From: badrogger Date: Wed, 18 Dec 2024 19:18:57 +0000 Subject: [PATCH] Fix migration --- node_cli/core/nftables.py | 29 ++++++++++++---- node_cli/core/node.py | 1 + node_cli/migrations/focal_to_jammy.py | 50 ++++++++++++++++----------- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/node_cli/core/nftables.py b/node_cli/core/nftables.py index fe5b975a..a752a847 100644 --- a/node_cli/core/nftables.py +++ b/node_cli/core/nftables.py @@ -307,12 +307,7 @@ def setup_firewall(self, enable_monitoring: bool = False) -> None: try: self.create_table_if_not_exists() - base_chains_config = { - 'input': {'hook': 'input', 'policy': 'accept'}, - 'forward': {'hook': 'forward', 'policy': 'drop'}, - 'output': {'hook': 'output', 'policy': 'accept'}, - 'skale': {'hook': 'input', 'policy': 'accept'}, - } + base_chains_config = {'skale': {'hook': 'input', 'policy': 'accept'}} for chain, config in base_chains_config.items(): self.create_chain_if_not_exists( @@ -348,6 +343,28 @@ def setup_firewall(self, enable_monitoring: bool = False) -> None: raise NFTablesError(e) logger.info('Firewall rules are configured') + def flush_chain(self, chain: str) -> None: + """Remove all rules from a specific chain""" + json_cmd = { + 'nftables': [{ + 'flush': { + 'chain': { + 'family': self.family, + 'table': self.table, + 'name': chain + } + } + }] + } + + try: + rc, output, error = self.nft.json_cmd(json_cmd) + if rc != 0: + raise NFTablesError(f'Failed to flush chain: {error}') + except Exception as e: + logger.error(f'Failed to flush chain: {str(e)}') + raise NFTablesError('Flushing chain errored') + def prepare_directories() -> None: logger.info('Prepare directories for nftables') diff --git a/node_cli/core/node.py b/node_cli/core/node.py index 24f4ea00..147a0a30 100644 --- a/node_cli/core/node.py +++ b/node_cli/core/node.py @@ -260,6 +260,7 @@ def update(env_filepath: str, pull_config_for_schain: str, unsafe_ok: bool = Fal error_exit(error_msg, exit_code=CLIExitCodes.UNSAFE_UPDATE) prev_version = get_meta_info().version + logger.info('HERE %s %s', __version__, prev_version) if (__version__ == 'test' or __version__.startswith('2.6')) and prev_version == '2.5.0': migrate_2_6() logger.info('Node update started') diff --git a/node_cli/migrations/focal_to_jammy.py b/node_cli/migrations/focal_to_jammy.py index 0f7be46c..7c0f0625 100644 --- a/node_cli/migrations/focal_to_jammy.py +++ b/node_cli/migrations/focal_to_jammy.py @@ -1,5 +1,6 @@ import logging +from node_cli.core.nftables import NFTablesManager from node_cli.utils.helper import get_ssh_port, run_cmd logger = logging.getLogger(__name__) @@ -19,67 +20,73 @@ '53' # dns ] +IPTABLES_CHAIN = 'INPUT' + + +class NFTablesCmdFailedError(Exception): + pass + def remove_tcp_rules(ssh_port: int) -> None: - tcp_rule_template = 'iptables -{} INPUT -p tcp -m tcp --dport {} -j ACCEPT' + tcp_rule_template = 'iptables -{} {} -p tcp -m tcp --dport {} -j ACCEPT' for tcp_port in [*ALLOWED_INCOMING_TCP_PORTS, ssh_port]: - check_cmd = tcp_rule_template.format('C', tcp_port).split(' ') - remove_cmd = tcp_rule_template.format('D', tcp_port).split(' ') + check_cmd = tcp_rule_template.format('C', IPTABLES_CHAIN, tcp_port).split(' ') + remove_cmd = tcp_rule_template.format('D', IPTABLES_CHAIN, tcp_port).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) def remove_udp_rules() -> None: - udp_rule_template = 'iptables -{} INPUT -p udp -m udp --dport {} -j ACCEPT' + udp_rule_template = 'iptables -{} {} -p udp -m udp --dport {} -j ACCEPT' for udp_port in [*ALLOWED_INCOMING_UDP_PORTS]: - check_cmd = udp_rule_template.format('C', udp_port).split(' ') - remove_cmd = udp_rule_template.format('D', udp_port).split(' ') + check_cmd = udp_rule_template.format('C', IPTABLES_CHAIN, udp_port).split(' ') + remove_cmd = udp_rule_template.format('D', IPTABLES_CHAIN, udp_port).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) def remove_loopback_rules() -> None: - loopback_rule_template = 'iptables -{} INPUT -i lo -j ACCEPT' - check_cmd = loopback_rule_template.format('C').split(' ') - remove_cmd = loopback_rule_template.format('D').split(' ') + loopback_rule_template = 'iptables -{} {} -i lo -j ACCEPT' + check_cmd = loopback_rule_template.format('C', IPTABLES_CHAIN).split(' ') + remove_cmd = loopback_rule_template.format('D', IPTABLES_CHAIN).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) def remove_icmp_rules() -> None: - icmp_rule_template = 'iptables -{} INPUT -p icmp -m icmp --icmp-type {} -j ACCEPT' + icmp_rule_template = 'iptables -{} {} -p icmp -m icmp --icmp-type {} -j ACCEPT' for icmp_type in [3, 4, 11]: - check_cmd = icmp_rule_template.format('C', icmp_type).split(' ') - remove_cmd = icmp_rule_template.format('D', icmp_type).split(' ') + check_cmd = icmp_rule_template.format('C', IPTABLES_CHAIN, icmp_type).split(' ') + remove_cmd = icmp_rule_template.format('D', IPTABLES_CHAIN, icmp_type).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) def remove_conntrack_rules() -> None: - track_rule_template = 'iptables -{} INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT' - check_cmd = track_rule_template.format('C').split(' ') - remove_cmd = track_rule_template.format('D').split(' ') + track_rule_template = 'iptables -{} {} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT' + check_cmd = track_rule_template.format('C', IPTABLES_CHAIN).split(' ') + remove_cmd = track_rule_template.format('D', IPTABLES_CHAIN).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) def remove_drop_rules() -> None: - drop_rule_template = 'iptables -{} INPUT -p {} -j DROP' + drop_rule_template = 'iptables -{} {} -p {} -j DROP' protocols = ['tcp', 'udp'] for proto in protocols: - check_cmd = drop_rule_template.format('C', proto).split(' ') - remove_cmd = drop_rule_template.format('D', proto).split(' ') + check_cmd = drop_rule_template.format('C', IPTABLES_CHAIN, proto).split(' ') + remove_cmd = drop_rule_template.format('D', IPTABLES_CHAIN, proto).split(' ') result = run_cmd(check_cmd, check_code=False) if result.returncode == 0: result = run_cmd(remove_cmd) -def remove_old_firewall_rules(ssh_port: int) -> None: +def remove_old_iptables_rules(ssh_port: int) -> None: remove_drop_rules() remove_conntrack_rules() remove_loopback_rules() @@ -91,5 +98,8 @@ def remove_old_firewall_rules(ssh_port: int) -> None: def migrate() -> None: ssh_port = get_ssh_port() logger.info('Running migration from focal to jammy') - remove_old_firewall_rules(ssh_port) + remove_old_iptables_rules(ssh_port) + logger.info('Flushing nftables rules generated by release upgrade') + nft = NFTablesManager(family='ip', table='filter') + nft.flush_chain(IPTABLES_CHAIN) logger.info('Migration from focal to jammy completed')