diff options
| -rw-r--r-- | op-mode-definitions/nat.xml.in | 4 | ||||
| -rw-r--r-- | op-mode-definitions/nat66.xml.in | 4 | ||||
| -rwxr-xr-x | src/op_mode/nat.py | 31 | ||||
| -rwxr-xr-x | src/op_mode/show_nat66_rules.py | 102 | 
4 files changed, 22 insertions, 119 deletions
| diff --git a/op-mode-definitions/nat.xml.in b/op-mode-definitions/nat.xml.in index 7148c1128..e89c3801f 100644 --- a/op-mode-definitions/nat.xml.in +++ b/op-mode-definitions/nat.xml.in @@ -16,7 +16,7 @@                  <properties>                    <help>Show configured source NAT rules</help>                  </properties> -                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction source</command> +                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction source --family inet</command>                </node>                <node name="statistics">                  <properties> @@ -58,7 +58,7 @@                  <properties>                    <help>Show configured destination NAT rules</help>                  </properties> -                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction destination</command> +                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction destination --family inet</command>                </node>                <node name="statistics">                  <properties> diff --git a/op-mode-definitions/nat66.xml.in b/op-mode-definitions/nat66.xml.in index 1ec46eb11..aba2d6add 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}/show_nat66_rules.py --source</command> +                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction source --family inet6</command>                </node>                <node name="statistics">                  <properties> @@ -58,7 +58,7 @@                  <properties>                    <help>Show configured destination NAT66 rules</help>                  </properties> -                <command>${vyos_op_scripts_dir}/show_nat66_rules.py --destination</command> +                <command>${vyos_op_scripts_dir}/nat.py show_rules --direction destination --family inet6</command>                </node>                <node name="statistics">                  <properties> diff --git a/src/op_mode/nat.py b/src/op_mode/nat.py index 12fc4c782..2dffc378b 100755 --- a/src/op_mode/nat.py +++ b/src/op_mode/nat.py @@ -27,7 +27,7 @@ from vyos.util import dict_search  import vyos.opmode -def _get_json_data(direction): +def _get_json_data(direction, family):      """      Get NAT format JSON      """ @@ -35,14 +35,15 @@ def _get_json_data(direction):          chain = 'POSTROUTING'      if direction == 'destination':          chain = 'PREROUTING' -    return cmd(f'sudo nft --json list chain ip nat {chain}') +    family = 'ip6' if family == 'inet6' else 'ip' +    return cmd(f'sudo nft --json list chain {family} nat {chain}') -def _get_raw_data_rules(direction): +def _get_raw_data_rules(direction, family):      """Get interested rules      :returns dict      """ -    data = _get_json_data(direction) +    data = _get_json_data(direction, family)      data_dict = json.loads(data)      rules = []      for rule in data_dict['nftables']: @@ -51,10 +52,12 @@ def _get_raw_data_rules(direction):      return rules -def _get_formatted_output_rules(data, direction): +def _get_formatted_output_rules(data, direction, family):      # Add default values before loop      sport, dport, proto = 'any', 'any', 'any' -    saddr, daddr = '0.0.0.0/0', '0.0.0.0/0' +    saddr = '::/0' if family == 'inet6' else '0.0.0.0/0' +    daddr = '::/0' if family == 'inet6' else '0.0.0.0/0' +      data_entries = []      for rule in data:          if 'comment' in rule['rule']: @@ -69,11 +72,13 @@ def _get_formatted_output_rules(data, direction):                  if 'prefix' in match['right'] or 'set' in match['right']:                      # Merge dict src/dst l3_l4 parameters                      my_dict = {**match['left']['payload'], **match['right']} +                    my_dict['op'] = match['op'] +                    op = '!' if my_dict.get('op') == '!=' else ''                      proto = my_dict.get('protocol').upper()                      if my_dict['field'] == 'saddr': -                        saddr = f'{my_dict["prefix"]["addr"]}/{my_dict["prefix"]["len"]}' +                        saddr = f'{op}{my_dict["prefix"]["addr"]}/{my_dict["prefix"]["len"]}'                      elif my_dict['field'] == 'daddr': -                        daddr = f'{my_dict["prefix"]["addr"]}/{my_dict["prefix"]["len"]}' +                        daddr = f'{op}{my_dict["prefix"]["addr"]}/{my_dict["prefix"]["len"]}'                      elif my_dict['field'] == 'sport':                          # Port range or single port                          if jmespath.search('set[*].range', my_dict): @@ -96,8 +101,8 @@ def _get_formatted_output_rules(data, direction):                      if jmespath.search('left.payload.field', match) == 'daddr':                          daddr = match.get('right')              else: -                saddr = '0.0.0.0/0' -                daddr = '0.0.0.0/0' +                saddr = '::/0' if family == 'inet6' else '0.0.0.0/0' +                daddr = '::/0' if family == 'inet6' else '0.0.0.0/0'                  sport = 'any'                  dport = 'any'                  proto = 'any' @@ -175,12 +180,12 @@ def _get_formatted_output_statistics(data, direction):      return output -def show_rules(raw: bool, direction: str): -    nat_rules = _get_raw_data_rules(direction) +def show_rules(raw: bool, direction: str, family: str): +    nat_rules = _get_raw_data_rules(direction, family)      if raw:          return nat_rules      else: -        return _get_formatted_output_rules(nat_rules, direction) +        return _get_formatted_output_rules(nat_rules, direction, family)  def show_statistics(raw: bool, direction: str): diff --git a/src/op_mode/show_nat66_rules.py b/src/op_mode/show_nat66_rules.py deleted file mode 100755 index 967ec9d37..000000000 --- a/src/op_mode/show_nat66_rules.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2021 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 -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -import jmespath -import json - -from argparse import ArgumentParser -from jinja2 import Template -from sys import exit -from vyos.util import cmd -from vyos.util import dict_search - -parser = ArgumentParser() -group = parser.add_mutually_exclusive_group() -group.add_argument("--source", help="Show statistics for configured source NAT rules", action="store_true") -group.add_argument("--destination", help="Show statistics for configured destination NAT rules", action="store_true") -args = parser.parse_args() - -if args.source or args.destination: -    tmp = cmd('sudo nft -j list table ip6 nat') -    tmp = json.loads(tmp) -     -    format_nat66_rule = '{0: <10} {1: <50} {2: <50} {3: <10}' -    print(format_nat66_rule.format("Rule", "Source" if args.source else "Destination", "Translation", "Outbound Interface" if args.source else "Inbound Interface")) -    print(format_nat66_rule.format("----", "------" if args.source else "-----------", "-----------", "------------------" if args.source else "-----------------")) -     -    data_json = jmespath.search('nftables[?rule].rule[?chain]', tmp) -    for idx in range(0, len(data_json)): -        data = data_json[idx] -         -        # The following key values must exist -        # When the rule JSON does not have some keys, this is not a rule we can work with -        continue_rule = False -        for key in ['comment', 'chain', 'expr']: -            if key not in data: -                continue_rule = True -                continue -        if continue_rule: -            continue -         -        comment = data['comment'] -         -        # Check the annotation to see if the annotation format is created by VYOS -        continue_rule = True -        for comment_prefix in ['SRC-NAT66-', 'DST-NAT66-']: -            if comment_prefix in comment: -                continue_rule = False -        if continue_rule: -            continue -         -        # When log is detected from the second index of expr, then this rule should be ignored -        if 'log' in data['expr'][2]: -            continue -         -        rule = comment.replace('SRC-NAT66-','') -        rule = rule.replace('DST-NAT66-','') -        chain = data['chain'] -        if not ((args.source and chain == 'POSTROUTING') or (not args.source and chain == 'PREROUTING')): -            continue -        interface = dict_search('match.right', data['expr'][0]) -        srcdest = dict_search('match.right.prefix.addr', data['expr'][2]) -        if srcdest: -            addr_tmp = dict_search('match.right.prefix.len', data['expr'][2]) -            if addr_tmp: -                srcdest = srcdest + '/' + str(addr_tmp) -        else: -            srcdest = dict_search('match.right', data['expr'][2]) -         -        tran_addr_json = dict_search('snat.addr' if args.source else 'dnat.addr', data['expr'][3]) -        if tran_addr_json: -            if isinstance(srcdest_json,str): -                tran_addr = tran_addr_json - -            if 'prefix' in tran_addr_json: -                addr_tmp = dict_search('snat.addr.prefix.addr' if args.source else 'dnat.addr.prefix.addr', data['expr'][3]) -                len_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3]) -                if addr_tmp: -                    tran_addr = addr_tmp + '/' + str(len_tmp) -        else: -            if 'masquerade' in data['expr'][3]: -                tran_addr = 'masquerade' -         -        print(format_nat66_rule.format(rule, srcdest, tran_addr, interface)) -     -    exit(0) -else: -    parser.print_help() -    exit(1) - | 
