diff options
-rw-r--r-- | debian/vyos-1x.postinst | 24 | ||||
-rw-r--r-- | op-mode-definitions/firewall.xml.in | 1 | ||||
-rw-r--r-- | python/vyos/utils/process.py | 2 | ||||
-rwxr-xr-x | src/op_mode/firewall.py | 93 |
4 files changed, 92 insertions, 28 deletions
diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst index f3dc00b46..b43416152 100644 --- a/debian/vyos-1x.postinst +++ b/debian/vyos-1x.postinst @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash # Turn off Debian default for %sudo sed -i -e '/^%sudo/d' /etc/sudoers || true @@ -29,6 +29,16 @@ do sed -i "/^# Standard Un\*x authentication\./i${PAM_CONFIG}" $file done +# We do not make use of a TACACS UNIX group - drop it +if grep -q '^tacacs' /etc/group; then + delgroup tacacs +fi + +# Both RADIUS and TACACS users belong to aaa group - this must be added first +if ! grep -q '^aaa' /etc/group; then + addgroup --firstgid 1000 --quiet aaa +fi + # Remove TACACS user added by base package - we use our own UID range and group # assignments - see below if grep -q '^tacacs' /etc/passwd; then @@ -37,6 +47,7 @@ if grep -q '^tacacs' /etc/passwd; then vyos_group=vyattaop while [ $level -lt 16 ]; do userdel tacacs${level} || true + rm -rf /home/tacacs${level} || true level=$(( level+1 )) done 2>&1 fi @@ -53,7 +64,7 @@ if ! grep -q '^tacacs' /etc/passwd; then level=0 vyos_group=vyattaop while [ $level -lt 16 ]; do - adduser --quiet --system --firstuid 900 --disabled-login --ingroup ${vyos_group} \ + adduser --quiet --system --firstuid 900 --disabled-login --ingroup users \ --no-create-home --gecos "TACACS+ mapped user at privilege level ${level}" \ --shell /bin/vbash tacacs${level} adduser --quiet tacacs${level} frrvty @@ -74,14 +85,9 @@ if ! grep -q '^tacacs' /etc/passwd; then done 2>&1 | grep -v 'User tacacs${level} already exists' fi - -if ! grep -q '^aaa' /etc/group; then - addgroup --firstgid 1000 --quiet aaa -fi - # Add RADIUS operator user for RADIUS authenticated users to map to if ! grep -q '^radius_user' /etc/passwd; then - adduser --quiet --firstuid 1000 --disabled-login --ingroup vyattaop \ + adduser --quiet --firstuid 1000 --disabled-login --ingroup users \ --no-create-home --gecos "RADIUS mapped user at privilege level operator" \ --shell /sbin/radius_shell radius_user adduser --quiet radius_user frrvty @@ -95,7 +101,7 @@ fi # Add RADIUS admin user for RADIUS authenticated users to map to if ! grep -q '^radius_priv_user' /etc/passwd; then - adduser --quiet --firstuid 1000 --disabled-login --ingroup vyattacfg \ + adduser --quiet --firstuid 1000 --disabled-login --ingroup users \ --no-create-home --gecos "RADIUS mapped user at privilege level admin" \ --shell /sbin/radius_shell radius_priv_user adduser --quiet radius_priv_user frrvty diff --git a/op-mode-definitions/firewall.xml.in b/op-mode-definitions/firewall.xml.in index 164ce6b60..0f296c272 100644 --- a/op-mode-definitions/firewall.xml.in +++ b/op-mode-definitions/firewall.xml.in @@ -119,6 +119,7 @@ <path>firewall group address-group</path> <path>firewall group network-group</path> <path>firewall group port-group</path> + <path>firewall group interface-group</path> <path>firewall group ipv6-address-group</path> <path>firewall group ipv6-network-group</path> </completionHelp> diff --git a/python/vyos/utils/process.py b/python/vyos/utils/process.py index 911547995..e09c7d86d 100644 --- a/python/vyos/utils/process.py +++ b/python/vyos/utils/process.py @@ -179,7 +179,7 @@ def rc_cmd(command, flag='', shell=None, input=None, timeout=None, env=None, return code, out def call(command, flag='', shell=None, input=None, timeout=None, env=None, - stdout=PIPE, stderr=PIPE, decode='utf-8'): + stdout=None, stderr=None, decode='utf-8'): """ A wrapper around popen, which print the stdout and will return the error code of a command diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index 852a7248a..581710b31 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -24,7 +24,7 @@ from vyos.config import Config from vyos.utils.process import cmd from vyos.utils.dict import dict_search_args -def get_config_firewall(conf, hook=None, priority=None, ipv6=False, interfaces=True): +def get_config_firewall(conf, hook=None, priority=None, ipv6=False): config_path = ['firewall'] if hook: config_path += ['ipv6' if ipv6 else 'ipv4', hook] @@ -38,12 +38,13 @@ def get_config_firewall(conf, hook=None, priority=None, ipv6=False, interfaces=T def get_nftables_details(hook, priority, ipv6=False): suffix = '6' if ipv6 else '' + aux = 'IPV6_' if ipv6 else '' name_prefix = 'NAME6_' if ipv6 else 'NAME_' if hook == 'name' or hook == 'ipv6-name': command = f'sudo nft list chain ip{suffix} vyos_filter {name_prefix}{priority}' else: up_hook = hook.upper() - command = f'sudo nft list chain ip{suffix} vyos_filter VYOS_{up_hook}_{priority}' + command = f'sudo nft list chain ip{suffix} vyos_filter VYOS_{aux}{up_hook}_{priority}' try: results = cmd(command) @@ -106,7 +107,7 @@ def output_firewall_name_statistics(hook, prior, prior_conf, ipv6=False, single_ ip_str = 'IPv6' if ipv6 else 'IPv4' print(f'\n---------------------------------\n{ip_str} Firewall "{hook} {prior}"\n') - details = get_nftables_details(prior, ipv6) + details = get_nftables_details(hook, prior, ipv6) rows = [] if 'rule' in prior_conf: @@ -117,8 +118,41 @@ def output_firewall_name_statistics(hook, prior, prior_conf, ipv6=False, single_ if 'disable' in rule_conf: continue - source_addr = dict_search_args(rule_conf, 'source', 'address') or '0.0.0.0/0' - dest_addr = dict_search_args(rule_conf, 'destination', 'address') or '0.0.0.0/0' + # Get source + source_addr = dict_search_args(rule_conf, 'source', 'address') + if not source_addr: + source_addr = dict_search_args(rule_conf, 'source', 'group', 'address_group') + if not source_addr: + source_addr = dict_search_args(rule_conf, 'source', 'group', 'network_group') + if not source_addr: + source_addr = dict_search_args(rule_conf, 'source', 'group', 'domain_group') + if not source_addr: + source_addr = '::/0' if ipv6 else '0.0.0.0/0' + + # Get destination + dest_addr = dict_search_args(rule_conf, 'destination', 'address') + if not dest_addr: + dest_addr = dict_search_args(rule_conf, 'destination', 'group', 'address_group') + if not dest_addr: + dest_addr = dict_search_args(rule_conf, 'destination', 'group', 'network_group') + if not dest_addr: + dest_addr = dict_search_args(rule_conf, 'destination', 'group', 'domain_group') + if not dest_addr: + dest_addr = '::/0' if ipv6 else '0.0.0.0/0' + + # Get inbound interface + iiface = dict_search_args(rule_conf, 'inbound_interface', 'interface_name') + if not iiface: + iiface = dict_search_args(rule_conf, 'inbound_interface', 'interface_group') + if not iiface: + iiface = 'any' + + # Get outbound interface + oiface = dict_search_args(rule_conf, 'outbound_interface', 'interface_name') + if not oiface: + oiface = dict_search_args(rule_conf, 'outbound_interface', 'interface_group') + if not oiface: + oiface = 'any' row = [rule_id] if rule_id in details: @@ -131,6 +165,8 @@ def output_firewall_name_statistics(hook, prior, prior_conf, ipv6=False, single_ row.append(rule_conf['action']) row.append(source_addr) row.append(dest_addr) + row.append(iiface) + row.append(oiface) rows.append(row) if 'default_action' in prior_conf and not single_rule_id: @@ -148,7 +184,7 @@ def output_firewall_name_statistics(hook, prior, prior_conf, ipv6=False, single_ rows.append(row) if rows: - header = ['Rule', 'Packets', 'Bytes', 'Action', 'Source', 'Destination'] + header = ['Rule', 'Packets', 'Bytes', 'Action', 'Source', 'Destination', 'Inbound-Interface', 'Outbound-interface'] print(tabulate.tabulate(rows, header) + '\n') def show_firewall(): @@ -204,7 +240,7 @@ def show_firewall_rule(hook, priority, rule_id, ipv6=False): def show_firewall_group(name=None): conf = Config() - firewall = get_config_firewall(conf, interfaces=False) + firewall = get_config_firewall(conf) if 'group' not in firewall: return @@ -225,18 +261,37 @@ def show_firewall_group(name=None): for item in family: for name_type in ['name', 'ipv6_name', 'forward', 'input', 'output']: - if name_type not in firewall[item]: - continue - for name, name_conf in firewall[item][name_type].items(): - if 'rule' not in name_conf: + if item in firewall: + if name_type not in firewall[item]: continue - for rule_id, rule_conf in name_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) - if source_group and group_name == source_group: - out.append(f'{name}-{rule_id}') - elif dest_group and group_name == dest_group: - out.append(f'{name}-{rule_id}') + for priority, priority_conf in firewall[item][name_type].items(): + if priority not in firewall[item][name_type]: + continue + 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') + if source_group: + if source_group[0] == "!": + source_group = source_group[1:] + if group_name == source_group: + out.append(f'{item}-{name_type}-{priority}-{rule_id}') + if dest_group: + if dest_group[0] == "!": + dest_group = dest_group[1:] + if group_name == dest_group: + out.append(f'{item}-{name_type}-{priority}-{rule_id}') + if in_interface: + if in_interface[0] == "!": + in_interface = in_interface[1:] + if group_name == in_interface: + out.append(f'{item}-{name_type}-{priority}-{rule_id}') + if out_interface: + if out_interface[0] == "!": + out_interface = out_interface[1:] + if group_name == out_interface: + out.append(f'{item}-{name_type}-{priority}-{rule_id}') return out header = ['Name', 'Type', 'References', 'Members'] @@ -257,6 +312,8 @@ def show_firewall_group(name=None): row.append("\n".join(sorted(group_conf['mac_address']))) elif 'port' in group_conf: row.append("\n".join(sorted(group_conf['port']))) + elif 'interface' in group_conf: + row.append("\n".join(sorted(group_conf['interface']))) else: row.append('N/A') rows.append(row) |