diff options
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-x | src/conf_mode/conntrack_sync.py | 2 | ||||
-rwxr-xr-x | src/conf_mode/firewall-interface.py | 31 | ||||
-rwxr-xr-x | src/conf_mode/firewall.py | 14 | ||||
-rwxr-xr-x | src/conf_mode/high-availability.py (renamed from src/conf_mode/vrrp.py) | 63 | ||||
-rwxr-xr-x | src/conf_mode/zone_policy.py | 6 |
5 files changed, 70 insertions, 46 deletions
diff --git a/src/conf_mode/conntrack_sync.py b/src/conf_mode/conntrack_sync.py index f82a077e6..8f9837c2b 100755 --- a/src/conf_mode/conntrack_sync.py +++ b/src/conf_mode/conntrack_sync.py @@ -36,7 +36,7 @@ airbag.enable() config_file = '/run/conntrackd/conntrackd.conf' def resync_vrrp(): - tmp = run('/usr/libexec/vyos/conf_mode/vrrp.py') + tmp = run('/usr/libexec/vyos/conf_mode/high-availability.py') if tmp > 0: print('ERROR: error restarting VRRP daemon!') diff --git a/src/conf_mode/firewall-interface.py b/src/conf_mode/firewall-interface.py index 516fa6c48..b0df9dff4 100755 --- a/src/conf_mode/firewall-interface.py +++ b/src/conf_mode/firewall-interface.py @@ -32,13 +32,13 @@ from vyos import airbag airbag.enable() NFT_CHAINS = { - 'in': 'VYOS_FW_IN', - 'out': 'VYOS_FW_OUT', + 'in': 'VYOS_FW_FORWARD', + 'out': 'VYOS_FW_FORWARD', 'local': 'VYOS_FW_LOCAL' } NFT6_CHAINS = { - 'in': 'VYOS_FW6_IN', - 'out': 'VYOS_FW6_OUT', + 'in': 'VYOS_FW6_FORWARD', + 'out': 'VYOS_FW6_FORWARD', 'local': 'VYOS_FW6_LOCAL' } @@ -91,11 +91,11 @@ def verify(if_firewall): def generate(if_firewall): return None -def cleanup_rule(table, chain, ifname, new_name=None): +def cleanup_rule(table, chain, prefix, ifname, new_name=None): results = cmd(f'nft -a list chain {table} {chain}').split("\n") retval = None for line in results: - if f'ifname "{ifname}"' in line: + if f'{prefix}ifname "{ifname}"' in line: if new_name and f'jump {new_name}' in line: # new_name is used to clear rules for any previously referenced chains # returns true when rule exists and doesn't need to be created @@ -108,6 +108,7 @@ def cleanup_rule(table, chain, ifname, new_name=None): return retval def state_policy_handle(table, chain): + # Find any state-policy rule to ensure interface rules are only inserted afterwards results = cmd(f'nft -a list chain {table} {chain}').split("\n") for line in results: if 'jump VYOS_STATE_POLICY' in line: @@ -126,11 +127,12 @@ def apply(if_firewall): name = dict_search_args(if_firewall, direction, 'name') if name: - rule_exists = cleanup_rule('ip filter', chain, ifname, name) - rule_action = 'insert' - rule_prefix = '' + rule_exists = cleanup_rule('ip filter', chain, if_prefix, ifname, name) if not rule_exists: + rule_action = 'insert' + rule_prefix = '' + handle = state_policy_handle('ip filter', chain) if handle: rule_action = 'add' @@ -138,15 +140,16 @@ def apply(if_firewall): run(f'nft {rule_action} rule ip filter {chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {name}') else: - cleanup_rule('ip filter', chain, ifname) + cleanup_rule('ip filter', chain, if_prefix, ifname) ipv6_name = dict_search_args(if_firewall, direction, 'ipv6_name') if ipv6_name: - rule_exists = cleanup_rule('ip6 filter', ipv6_chain, ifname, ipv6_name) - rule_action = 'insert' - rule_prefix = '' + rule_exists = cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname, ipv6_name) if not rule_exists: + rule_action = 'insert' + rule_prefix = '' + handle = state_policy_handle('ip filter', chain) if handle: rule_action = 'add' @@ -154,7 +157,7 @@ def apply(if_firewall): run(f'nft {rule_action} rule ip6 filter {ipv6_chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {ipv6_name}') else: - cleanup_rule('ip6 filter', ipv6_chain, ifname) + cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname) return None diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 8e037c679..6016d94fa 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -53,14 +53,12 @@ preserve_chains = [ 'INPUT', 'FORWARD', 'OUTPUT', - 'VYOS_FW_IN', - 'VYOS_FW_OUT', + 'VYOS_FW_FORWARD', 'VYOS_FW_LOCAL', 'VYOS_FW_OUTPUT', 'VYOS_POST_FW', 'VYOS_FRAG_MARK', - 'VYOS_FW6_IN', - 'VYOS_FW6_OUT', + 'VYOS_FW6_FORWARD', 'VYOS_FW6_LOCAL', 'VYOS_FW6_OUTPUT', 'VYOS_POST_FW6', @@ -228,7 +226,7 @@ def cleanup_commands(firewall): commands.append(f'delete chain {table} {chain}') elif 'rule' in item: rule = item['rule'] - if rule['chain'] in ['VYOS_FW_IN', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL', 'VYOS_FW6_IN', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: + if rule['chain'] in ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL', 'VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: if 'expr' in rule and any([True for expr in rule['expr'] if dict_search_args(expr, 'jump', 'target') == state_chain]): if 'state_policy' not in firewall: chain = rule['chain'] @@ -303,7 +301,7 @@ def post_apply_trap(firewall): def state_policy_rule_exists(): # Determine if state policy rules already exist in nft - search_str = cmd(f'nft list chain ip filter VYOS_FW_IN') + search_str = cmd(f'nft list chain ip filter VYOS_FW_FORWARD') return 'VYOS_STATE_POLICY' in search_str def apply(firewall): @@ -317,10 +315,10 @@ def apply(firewall): raise ConfigError('Failed to apply firewall') if 'state_policy' in firewall and not state_policy_rule_exists(): - for chain in ['VYOS_FW_IN', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL']: + for chain in ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL']: cmd(f'nft insert rule ip filter {chain} jump VYOS_STATE_POLICY') - for chain in ['VYOS_FW6_IN', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: + for chain in ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: cmd(f'nft insert rule ip6 filter {chain} jump VYOS_STATE_POLICY6') apply_sysfs(firewall) diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/high-availability.py index c72efc61f..7d51bb393 100755 --- a/src/conf_mode/vrrp.py +++ b/src/conf_mode/high-availability.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2022 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -40,33 +40,41 @@ def get_config(config=None): else: conf = Config() - base = ['high-availability', 'vrrp'] + base = ['high-availability'] + base_vrrp = ['high-availability', 'vrrp'] if not conf.exists(base): return None - vrrp = conf.get_config_dict(base, key_mangling=('-', '_'), + ha = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # We have gathered the dict representation of the CLI, but there are default # options which we need to update into the dictionary retrived. - if 'group' in vrrp: - default_values = defaults(base + ['group']) - for group in vrrp['group']: - vrrp['group'][group] = dict_merge(default_values, vrrp['group'][group]) + if 'vrrp' in ha: + if 'group' in ha['vrrp']: + default_values_vrrp = defaults(base_vrrp + ['group']) + for group in ha['vrrp']['group']: + ha['vrrp']['group'][group] = dict_merge(default_values_vrrp, ha['vrrp']['group'][group]) + + # Merge per virtual-server default values + if 'virtual_server' in ha: + default_values = defaults(base + ['virtual-server']) + for vs in ha['virtual_server']: + ha['virtual_server'][vs] = dict_merge(default_values, ha['virtual_server'][vs]) ## Get the sync group used for conntrack-sync conntrack_path = ['service', 'conntrack-sync', 'failover-mechanism', 'vrrp', 'sync-group'] if conf.exists(conntrack_path): - vrrp['conntrack_sync_group'] = conf.return_value(conntrack_path) + ha['conntrack_sync_group'] = conf.return_value(conntrack_path) - return vrrp + return ha -def verify(vrrp): - if not vrrp: +def verify(ha): + if not ha: return None used_vrid_if = [] - if 'group' in vrrp: - for group, group_config in vrrp['group'].items(): + if 'vrrp' in ha and 'group' in ha['vrrp']: + for group, group_config in ha['vrrp']['group'].items(): # Check required fields if 'vrid' not in group_config: raise ConfigError(f'VRID is required but not set in VRRP group "{group}"') @@ -119,24 +127,37 @@ def verify(vrrp): if is_ipv4(group_config['peer_address']): raise ConfigError(f'VRRP group "{group}" uses IPv6 but peer-address is IPv4!') # Check sync groups - if 'sync_group' in vrrp: - for sync_group, sync_config in vrrp['sync_group'].items(): + if 'vrrp' in ha and 'sync_group' in ha['vrrp']: + for sync_group, sync_config in ha['vrrp']['sync_group'].items(): if 'member' in sync_config: for member in sync_config['member']: - if member not in vrrp['group']: + if member not in ha['vrrp']['group']: raise ConfigError(f'VRRP sync-group "{sync_group}" refers to VRRP group "{member}", '\ 'but it does not exist!') -def generate(vrrp): - if not vrrp: + # Virtual-server + if 'virtual_server' in ha: + for vs, vs_config in ha['virtual_server'].items(): + if 'port' not in vs_config: + raise ConfigError(f'Port is required but not set for virtual-server "{vs}"') + if 'real_server' not in vs_config: + raise ConfigError(f'Real-server ip is required but not set for virtual-server "{vs}"') + # Real-server + for rs, rs_config in vs_config['real_server'].items(): + if 'port' not in rs_config: + raise ConfigError(f'Port is required but not set for virtual-server "{vs}" real-server "{rs}"') + + +def generate(ha): + if not ha: return None - render(VRRP.location['config'], 'vrrp/keepalived.conf.tmpl', vrrp) + render(VRRP.location['config'], 'high-availability/keepalived.conf.tmpl', ha) return None -def apply(vrrp): +def apply(ha): service_name = 'keepalived.service' - if not vrrp: + if not ha: call(f'systemctl stop {service_name}') return None diff --git a/src/conf_mode/zone_policy.py b/src/conf_mode/zone_policy.py index 2535ea33b..d605e9639 100755 --- a/src/conf_mode/zone_policy.py +++ b/src/conf_mode/zone_policy.py @@ -152,7 +152,9 @@ def cleanup_commands(): continue for expr in item['rule']['expr']: target = dict_search_args(expr, 'jump', 'target') - if target and target.startswith("VZONE"): + if not target: + continue + if target.startswith("VZONE") or target.startswith("VYOS_STATE_POLICY"): commands.append(f'delete rule {table} {chain} handle {handle}') for item in obj['nftables']: if 'chain' in item: @@ -180,7 +182,7 @@ def generate(zone_policy): def apply(zone_policy): install_result = run(f'nft -f {nftables_conf}') - if install_result == 1: + if install_result != 0: raise ConfigError('Failed to apply zone-policy') return None |