diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/interfaces-vxlan.py | 20 | ||||
-rwxr-xr-x | src/migration-scripts/interfaces/31-to-32 | 9 | ||||
-rwxr-xr-x | src/op_mode/firewall.py | 147 | ||||
-rwxr-xr-x | src/op_mode/ssh.py | 6 |
4 files changed, 140 insertions, 42 deletions
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 7bd3fa692..6bf3227d5 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -54,7 +54,7 @@ def get_config(config=None): # VXLAN interfaces are picky and require recreation if certain parameters # change. But a VXLAN interface should - of course - not be re-created if # it's description or IP address is adjusted. Feels somehow logic doesn't it? - for cli_option in ['parameters', 'external', 'gpe', 'group', 'port', 'remote', + for cli_option in ['parameters', 'gpe', 'group', 'port', 'remote', 'source-address', 'source-interface', 'vni']: if is_node_changed(conf, base + [ifname, cli_option]): vxlan.update({'rebuild_required': {}}) @@ -95,17 +95,17 @@ def verify(vxlan): if not any(tmp in ['group', 'remote', 'source_address', 'source_interface'] for tmp in vxlan): raise ConfigError('Group, remote, source-address or source-interface must be configured') - if 'vni' not in vxlan and 'external' not in vxlan: - raise ConfigError( - 'Must either configure VXLAN "vni" or use "external" CLI option!') + if 'vni' not in vxlan and dict_search('parameters.external', vxlan) == None: + raise ConfigError('Must either configure VXLAN "vni" or use "external" CLI option!') - if {'external', 'vni'} <= set(vxlan): - raise ConfigError('Can not specify both "external" and "VNI"!') + if dict_search('parameters.external', vxlan): + if 'vni' in vxlan: + raise ConfigError('Can not specify both "external" and "VNI"!') - if {'external', 'other_tunnels'} <= set(vxlan): - other_tunnels = ', '.join(vxlan['other_tunnels']) - raise ConfigError(f'Only one VXLAN tunnel is supported when "external" '\ - f'CLI option is used. Additional tunnels: {other_tunnels}') + if 'other_tunnels' in vxlan: + other_tunnels = ', '.join(vxlan['other_tunnels']) + raise ConfigError(f'Only one VXLAN tunnel is supported when "external" '\ + f'CLI option is used. Additional tunnels: {other_tunnels}') if 'gpe' in vxlan and 'external' not in vxlan: raise ConfigError(f'VXLAN-GPE is only supported when "external" '\ diff --git a/src/migration-scripts/interfaces/31-to-32 b/src/migration-scripts/interfaces/31-to-32 index 35b397c39..ca3d19320 100755 --- a/src/migration-scripts/interfaces/31-to-32 +++ b/src/migration-scripts/interfaces/31-to-32 @@ -27,7 +27,8 @@ if len(argv) < 2: file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() - base = ['interfaces', 'vxlan'] + +base = ['interfaces', 'vxlan'] config = ConfigTree(config_file) if not config.exists(base): @@ -35,7 +36,11 @@ if not config.exists(base): exit(0) for vxlan in config.list_nodes(base): - if not config.exists(base + ['port']): + if config.exists(base + [vxlan, 'external']): + config.delete(base + [vxlan, 'external']) + config.set(base + [vxlan, 'parameters', 'external']) + + if not config.exists(base + [vxlan, 'port']): config.set(base + [vxlan, 'port'], value='8472') try: diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index 3434707ec..20f54b9ba 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2023 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 @@ -24,19 +24,28 @@ from vyos.config import Config from vyos.utils.process import cmd from vyos.utils.dict import dict_search_args -def get_config_firewall(conf, family=None, hook=None, priority=None): - config_path = ['firewall'] - if family: - config_path += [family] - if hook: - config_path += [hook] - if priority: - config_path += [priority] +def get_config_node(conf, node=None, family=None, hook=None, priority=None): + if node == 'nat': + if family == 'ipv6': + config_path = ['nat66'] + else: + config_path = ['nat'] - firewall = conf.get_config_dict(config_path, key_mangling=('-', '_'), + elif node == 'policy': + config_path = ['policy'] + else: + config_path = ['firewall'] + if family: + config_path += [family] + if hook: + config_path += [hook] + if priority: + config_path += [priority] + + node_config = conf.get_config_dict(config_path, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) - return firewall + return node_config def get_nftables_details(family, hook, priority): if family == 'ipv6': @@ -102,7 +111,15 @@ def output_firewall_name(family, hook, priority, firewall_conf, single_rule_id=N row.append(rule_details['conditions']) rows.append(row) - if 'default_action' in firewall_conf and not single_rule_id: + if hook in ['input', 'forward', 'output']: + def_action = firewall_conf['default_action'] if 'default_action' in firewall_conf else 'accept' + row = ['default', def_action, 'all'] + rule_details = details['default-action'] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + rows.append(row) + + elif 'default_action' in firewall_conf and not single_rule_id: row = ['default', firewall_conf['default_action'], 'all'] if 'default-action' in details: rule_details = details['default-action'] @@ -167,16 +184,16 @@ def output_firewall_name_statistics(family, hook, prior, prior_conf, single_rule dest_addr = 'any' # Get inbound interface - iiface = dict_search_args(rule_conf, 'inbound_interface', 'interface_name') + iiface = dict_search_args(rule_conf, 'inbound_interface', 'name') if not iiface: - iiface = dict_search_args(rule_conf, 'inbound_interface', 'interface_group') + iiface = dict_search_args(rule_conf, 'inbound_interface', 'group') if not iiface: iiface = 'any' # Get outbound interface - oiface = dict_search_args(rule_conf, 'outbound_interface', 'interface_name') + oiface = dict_search_args(rule_conf, 'outbound_interface', 'name') if not oiface: - oiface = dict_search_args(rule_conf, 'outbound_interface', 'interface_group') + oiface = dict_search_args(rule_conf, 'outbound_interface', 'group') if not oiface: oiface = 'any' @@ -198,8 +215,9 @@ def output_firewall_name_statistics(family, hook, prior, prior_conf, single_rule if hook in ['input', 'forward', 'output']: row = ['default'] - row.append('N/A') - row.append('N/A') + rule_details = details['default-action'] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) if 'default_action' in prior_conf: row.append(prior_conf['default_action']) else: @@ -234,7 +252,7 @@ def show_firewall(): print('Rulesets Information') conf = Config() - firewall = get_config_firewall(conf) + firewall = get_config_node(conf) if not firewall: return @@ -249,7 +267,7 @@ def show_firewall_family(family): print(f'Rulesets {family} Information') conf = Config() - firewall = get_config_firewall(conf) + firewall = get_config_node(conf) if not firewall or family not in firewall: return @@ -262,7 +280,7 @@ def show_firewall_name(family, hook, priority): print('Ruleset Information') conf = Config() - firewall = get_config_firewall(conf, family, hook, priority) + firewall = get_config_node(conf, 'firewall', family, hook, priority) if firewall: output_firewall_name(family, hook, priority, firewall) @@ -270,17 +288,20 @@ def show_firewall_rule(family, hook, priority, rule_id): print('Rule Information') conf = Config() - firewall = get_config_firewall(conf, family, hook, priority) + firewall = get_config_node(conf, 'firewall', family, hook, priority) if firewall: output_firewall_name(family, hook, priority, firewall, rule_id) def show_firewall_group(name=None): conf = Config() - firewall = get_config_firewall(conf) + firewall = get_config_node(conf, node='firewall') if 'group' not in firewall: return + nat = get_config_node(conf, node='nat') + policy = get_config_node(conf, node='policy') + def find_references(group_type, group_name): out = [] family = [] @@ -296,6 +317,7 @@ def show_firewall_group(name=None): family = ['ipv4', 'ipv6'] for item in family: + # Look references in firewall for name_type in ['name', 'ipv6_name', 'forward', 'input', 'output']: if item in firewall: if name_type not in firewall[item]: @@ -308,8 +330,8 @@ def show_firewall_group(name=None): for rule_id, rule_conf in priority_conf['rule'].items(): source_group = dict_search_args(rule_conf, 'source', 'group', group_type) dest_group = dict_search_args(rule_conf, 'destination', 'group', group_type) - in_interface = dict_search_args(rule_conf, 'inbound_interface', 'interface_group') - out_interface = dict_search_args(rule_conf, 'outbound_interface', 'interface_group') + in_interface = dict_search_args(rule_conf, 'inbound_interface', 'group') + out_interface = dict_search_args(rule_conf, 'outbound_interface', 'group') if source_group: if source_group[0] == "!": source_group = source_group[1:] @@ -330,6 +352,76 @@ def show_firewall_group(name=None): out_interface = out_interface[1:] if group_name == out_interface: out.append(f'{item}-{name_type}-{priority}-{rule_id}') + + # Look references in route | route6 + for name_type in ['route', 'route6']: + if name_type not in policy: + continue + if name_type == 'route' and item == 'ipv6': + continue + elif name_type == 'route6' and item == 'ipv4': + continue + else: + for policy_name, policy_conf in policy[name_type].items(): + if 'rule' not in policy_conf: + continue + for rule_id, rule_conf in policy_conf['rule'].items(): + source_group = dict_search_args(rule_conf, 'source', 'group', group_type) + dest_group = dict_search_args(rule_conf, 'destination', 'group', group_type) + in_interface = dict_search_args(rule_conf, 'inbound_interface', 'group') + out_interface = dict_search_args(rule_conf, 'outbound_interface', 'group') + if source_group: + if source_group[0] == "!": + source_group = source_group[1:] + if group_name == source_group: + out.append(f'{name_type}-{policy_name}-{rule_id}') + if dest_group: + if dest_group[0] == "!": + dest_group = dest_group[1:] + if group_name == dest_group: + out.append(f'{name_type}-{policy_name}-{rule_id}') + if in_interface: + if in_interface[0] == "!": + in_interface = in_interface[1:] + if group_name == in_interface: + out.append(f'{name_type}-{policy_name}-{rule_id}') + if out_interface: + if out_interface[0] == "!": + out_interface = out_interface[1:] + if group_name == out_interface: + out.append(f'{name_type}-{policy_name}-{rule_id}') + + ## Look references in nat table + for direction in ['source', 'destination']: + if direction in nat: + if 'rule' not in nat[direction]: + continue + for rule_id, rule_conf in nat[direction]['rule'].items(): + source_group = dict_search_args(rule_conf, 'source', 'group', group_type) + dest_group = dict_search_args(rule_conf, 'destination', 'group', group_type) + in_interface = dict_search_args(rule_conf, 'inbound_interface', 'group') + out_interface = dict_search_args(rule_conf, 'outbound_interface', 'group') + if source_group: + if source_group[0] == "!": + source_group = source_group[1:] + if group_name == source_group: + out.append(f'nat-{direction}-{rule_id}') + if dest_group: + if dest_group[0] == "!": + dest_group = dest_group[1:] + if group_name == dest_group: + out.append(f'nat-{direction}-{rule_id}') + if in_interface: + if in_interface[0] == "!": + in_interface = in_interface[1:] + if group_name == in_interface: + out.append(f'nat-{direction}-{rule_id}') + if out_interface: + if out_interface[0] == "!": + out_interface = out_interface[1:] + if group_name == out_interface: + out.append(f'nat-{direction}-{rule_id}') + return out header = ['Name', 'Type', 'References', 'Members'] @@ -356,6 +448,7 @@ def show_firewall_group(name=None): row.append('N/D') rows.append(row) + if rows: print('Firewall Groups\n') print(tabulate.tabulate(rows, header)) @@ -364,7 +457,7 @@ def show_summary(): print('Ruleset Summary') conf = Config() - firewall = get_config_firewall(conf) + firewall = get_config_node(conf) if not firewall: return @@ -410,7 +503,7 @@ def show_statistics(): print('Rulesets Statistics') conf = Config() - firewall = get_config_firewall(conf) + firewall = get_config_node(conf) if not firewall: return diff --git a/src/op_mode/ssh.py b/src/op_mode/ssh.py index c09b2166f..102becc55 100755 --- a/src/op_mode/ssh.py +++ b/src/op_mode/ssh.py @@ -64,18 +64,18 @@ def show_fingerprints(raw: bool, ascii: bool): def show_dynamic_protection(raw: bool): config = ConfigTreeQuery() - if not config.exists("service ssh dynamic-protection"): + if not config.exists(['service', 'ssh', 'dynamic-protection']): raise vyos.opmode.UnconfiguredSubsystem("SSH server dynamic-protection is not enabled.") attackers = [] try: # IPv4 - attackers = attackers + json.loads(cmd("sudo nft -j list set ip sshguard attackers"))["nftables"][1]["set"]["elem"] + attackers = attackers + json.loads(cmd("nft -j list set ip sshguard attackers"))["nftables"][1]["set"]["elem"] except: pass try: # IPv6 - attackers = attackers + json.loads(cmd("sudo nft -j list set ip6 sshguard attackers"))["nftables"][1]["set"]["elem"] + attackers = attackers + json.loads(cmd("nft -j list set ip6 sshguard attackers"))["nftables"][1]["set"]["elem"] except: pass if attackers: |