diff options
-rw-r--r-- | op-mode-definitions/nat66.xml.in | 8 | ||||
-rw-r--r-- | smoketest/config-tests/dialup-router-medium-vpn | 30 | ||||
-rwxr-xr-x | src/op_mode/firewall.py | 147 |
3 files changed, 139 insertions, 46 deletions
diff --git a/op-mode-definitions/nat66.xml.in b/op-mode-definitions/nat66.xml.in index 6a8a39000..4df20d847 100644 --- a/op-mode-definitions/nat66.xml.in +++ b/op-mode-definitions/nat66.xml.in @@ -16,7 +16,7 @@ <properties> <help>Show configured source NAT66 rules</help> </properties> - <command>${vyos_op_scripts_dir}/nat.py show_rules --direction source --family inet6</command> + <command>sudo ${vyos_op_scripts_dir}/nat.py show_rules --direction source --family inet6</command> </node> <node name="statistics"> <properties> @@ -39,7 +39,7 @@ <command>sudo ${vyos_op_scripts_dir}/nat.py show_translations --direction source --family inet6 --address "$6"</command> </tagNode> </children> - <command>${vyos_op_scripts_dir}/nat.py show_translations --direction source --family inet6</command> + <command>sudo ${vyos_op_scripts_dir}/nat.py show_translations --direction source --family inet6</command> </node> </children> </node> @@ -52,7 +52,7 @@ <properties> <help>Show configured destination NAT66 rules</help> </properties> - <command>${vyos_op_scripts_dir}/nat.py show_rules --direction destination --family inet6</command> + <command>sudo ${vyos_op_scripts_dir}/nat.py show_rules --direction destination --family inet6</command> </node> <node name="statistics"> <properties> @@ -75,7 +75,7 @@ <command>sudo ${vyos_op_scripts_dir}/nat.py show_translations --direction destination --family inet6 --address "$6"</command> </tagNode> </children> - <command>${vyos_op_scripts_dir}/nat.py show_translations --direction destination --family inet6</command> + <command>sudo ${vyos_op_scripts_dir}/nat.py show_translations --direction destination --family inet6</command> </node> </children> </node> diff --git a/smoketest/config-tests/dialup-router-medium-vpn b/smoketest/config-tests/dialup-router-medium-vpn index 37baee0fd..20edc0ecf 100644 --- a/smoketest/config-tests/dialup-router-medium-vpn +++ b/smoketest/config-tests/dialup-router-medium-vpn @@ -141,51 +141,51 @@ set interfaces wireguard wg1 peer sam preshared-key 'XpFtzx2Z+nR8pBv9/sSf7I94OkZ set interfaces wireguard wg1 peer sam public-key 'v5zfKGvH6W/lfDXJ0en96lvKo1gfFxMUWxe02+Fj5BU=' set interfaces wireguard wg1 port '7778' set nat destination rule 50 destination port '49371' -set nat destination rule 50 inbound-interface 'pppoe0' +set nat destination rule 50 inbound-interface name 'pppoe0' set nat destination rule 50 protocol 'tcp_udp' set nat destination rule 50 translation address '192.168.0.5' set nat destination rule 51 destination port '58050-58051' -set nat destination rule 51 inbound-interface 'pppoe0' +set nat destination rule 51 inbound-interface name 'pppoe0' set nat destination rule 51 protocol 'tcp' set nat destination rule 51 translation address '192.168.0.5' set nat destination rule 52 destination port '22067-22070' -set nat destination rule 52 inbound-interface 'pppoe0' +set nat destination rule 52 inbound-interface name 'pppoe0' set nat destination rule 52 protocol 'tcp' set nat destination rule 52 translation address '192.168.0.5' set nat destination rule 53 destination port '34342' -set nat destination rule 53 inbound-interface 'pppoe0' +set nat destination rule 53 inbound-interface name 'pppoe0' set nat destination rule 53 protocol 'tcp_udp' set nat destination rule 53 translation address '192.168.0.121' set nat destination rule 54 destination port '45459' -set nat destination rule 54 inbound-interface 'pppoe0' +set nat destination rule 54 inbound-interface name 'pppoe0' set nat destination rule 54 protocol 'tcp_udp' set nat destination rule 54 translation address '192.168.0.120' set nat destination rule 55 destination port '22' -set nat destination rule 55 inbound-interface 'pppoe0' +set nat destination rule 55 inbound-interface name 'pppoe0' set nat destination rule 55 protocol 'tcp' set nat destination rule 55 translation address '192.168.0.5' set nat destination rule 56 destination port '8920' -set nat destination rule 56 inbound-interface 'pppoe0' +set nat destination rule 56 inbound-interface name 'pppoe0' set nat destination rule 56 protocol 'tcp' set nat destination rule 56 translation address '192.168.0.5' set nat destination rule 60 destination port '80,443' -set nat destination rule 60 inbound-interface 'pppoe0' +set nat destination rule 60 inbound-interface name 'pppoe0' set nat destination rule 60 protocol 'tcp' set nat destination rule 60 translation address '192.168.0.5' set nat destination rule 70 destination port '5001' -set nat destination rule 70 inbound-interface 'pppoe0' +set nat destination rule 70 inbound-interface name 'pppoe0' set nat destination rule 70 protocol 'tcp' set nat destination rule 70 translation address '192.168.0.5' set nat destination rule 80 destination port '25' -set nat destination rule 80 inbound-interface 'pppoe0' +set nat destination rule 80 inbound-interface name 'pppoe0' set nat destination rule 80 protocol 'tcp' set nat destination rule 80 translation address '192.168.0.5' set nat destination rule 90 destination port '8123' -set nat destination rule 90 inbound-interface 'pppoe0' +set nat destination rule 90 inbound-interface name 'pppoe0' set nat destination rule 90 protocol 'tcp' set nat destination rule 90 translation address '192.168.0.7' set nat destination rule 91 destination port '1880' -set nat destination rule 91 inbound-interface 'pppoe0' +set nat destination rule 91 inbound-interface name 'pppoe0' set nat destination rule 91 protocol 'tcp' set nat destination rule 91 translation address '192.168.0.7' set nat destination rule 500 destination address '!192.168.0.0/24' @@ -194,12 +194,12 @@ set nat destination rule 500 inbound-interface 'eth1' set nat destination rule 500 protocol 'tcp_udp' set nat destination rule 500 source address '!192.168.0.1-192.168.0.5' set nat destination rule 500 translation address '192.168.0.1' -set nat source rule 1000 outbound-interface 'pppoe0' +set nat source rule 1000 outbound-interface name 'pppoe0' set nat source rule 1000 translation address 'masquerade' -set nat source rule 2000 outbound-interface 'vtun0' +set nat source rule 2000 outbound-interface name 'vtun0' set nat source rule 2000 source address '192.168.0.0/16' set nat source rule 2000 translation address 'masquerade' -set nat source rule 3000 outbound-interface 'vtun1' +set nat source rule 3000 outbound-interface name 'vtun1' set nat source rule 3000 translation address 'masquerade' set policy prefix-list user1-routes rule 1 action 'permit' set policy prefix-list user1-routes rule 1 prefix '192.168.0.0/24' 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 |