summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/nat.xml.in1
-rw-r--r--op-mode-definitions/nat.xml.in20
-rw-r--r--op-mode-definitions/show-log.xml.in50
-rw-r--r--python/vyos/nat.py6
-rwxr-xr-xsrc/op_mode/cgnat.py44
5 files changed, 104 insertions, 17 deletions
diff --git a/interface-definitions/nat.xml.in b/interface-definitions/nat.xml.in
index 0a639bd80..73a748137 100644
--- a/interface-definitions/nat.xml.in
+++ b/interface-definitions/nat.xml.in
@@ -141,6 +141,7 @@
</children>
</node>
#include <include/inbound-interface.xml.i>
+ #include <include/firewall/log.xml.i>
<node name="translation">
<properties>
<help>Translation address or prefix</help>
diff --git a/op-mode-definitions/nat.xml.in b/op-mode-definitions/nat.xml.in
index 6398c0e07..13e7fd81d 100644
--- a/op-mode-definitions/nat.xml.in
+++ b/op-mode-definitions/nat.xml.in
@@ -16,6 +16,26 @@
<properties>
<help>Show allocated CGNAT parameters</help>
</properties>
+ <children>
+ <tagNode name="external-address">
+ <properties>
+ <help>Show CGNAT allocations for an external IP address</help>
+ <completionHelp>
+ <list>&lt;x.x.x.x&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/cgnat.py show_allocation --external-address "$6"</command>
+ </tagNode>
+ <tagNode name="internal-address">
+ <properties>
+ <help>Show CGNAT allocations for an internal IP address</help>
+ <completionHelp>
+ <list>&lt;x.x.x.x&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/cgnat.py show_allocation --internal-address "$6"</command>
+ </tagNode>
+ </children>
<command>sudo ${vyos_op_scripts_dir}/cgnat.py show_allocation</command>
</node>
</children>
diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in
index e13270364..c3aa324ba 100644
--- a/op-mode-definitions/show-log.xml.in
+++ b/op-mode-definitions/show-log.xml.in
@@ -464,12 +464,56 @@
</properties>
<command>journalctl --no-hostname --boot --unit lldpd.service</command>
</leafNode>
- <leafNode name="nat">
+ <node name="nat">
<properties>
<help>Show log for Network Address Translation (NAT)</help>
</properties>
- <command>egrep -i "kernel:.*\[NAT-[A-Z]{3,}-[0-9]+(-MASQ)?\]" $(find /var/log -maxdepth 1 -type f -name messages\* | sort -t. -k2nr)</command>
- </leafNode>
+ <children>
+ <node name="destination">
+ <properties>
+ <help>Show NAT destination log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[DST-NAT-[0-9]+\]"</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show NAT destination log for specified rule</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[DST-NAT-$6\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ <node name="source">
+ <properties>
+ <help>Show NAT source log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[SRC-NAT-[0-9]+(-MASQ)?\]"&quot;"</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show NAT source log for specified rule</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[SRC-NAT-$6(-MASQ)?\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ <node name="static">
+ <properties>
+ <help>Show NAT static log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[STATIC-(SRC|DST)-NAT-[0-9]+\]"</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show NAT static log for specified rule</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[STATIC-(SRC|DST)-NAT-$6\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ <command>journalctl --no-hostname --boot -k | egrep "\[(STATIC-)?(DST|SRC)-NAT-[0-9]+(-MASQ)?\]"</command>
+ </node>
<leafNode name="ndp-proxy">
<properties>
<help>Show log for Neighbor Discovery Protocol (NDP) Proxy</help>
diff --git a/python/vyos/nat.py b/python/vyos/nat.py
index 2ada29add..e54548788 100644
--- a/python/vyos/nat.py
+++ b/python/vyos/nat.py
@@ -300,12 +300,12 @@ def parse_nat_static_rule(rule_conf, rule_id, nat_type):
output.append('counter')
- if translation_str:
- output.append(translation_str)
-
if 'log' in rule_conf:
output.append(f'log prefix "[{log_prefix}{log_suffix}]"')
+ if translation_str:
+ output.append(translation_str)
+
output.append(f'comment "{log_prefix}"')
return " ".join(output)
diff --git a/src/op_mode/cgnat.py b/src/op_mode/cgnat.py
index e58b15809..9ad8f92f9 100755
--- a/src/op_mode/cgnat.py
+++ b/src/op_mode/cgnat.py
@@ -16,6 +16,7 @@
import json
import sys
+import typing
from tabulate import tabulate
@@ -27,15 +28,11 @@ from vyos.utils.process import cmd
CGNAT_TABLE = 'cgnat'
-def _get_raw_data():
- """ Get CGNAT dictionary
- """
+def _get_raw_data(external_address: str = '', internal_address: str = '') -> list[dict]:
+ """Get CGNAT dictionary and filter by external or internal address if provided."""
cmd_output = cmd(f'nft --json list table ip {CGNAT_TABLE}')
data = json.loads(cmd_output)
- return data
-
-def _get_formatted_output(data):
elements = data['nftables'][2]['map']['elem']
allocations = []
for elem in elements:
@@ -44,23 +41,48 @@ def _get_formatted_output(data):
start_port = elem[1]['concat'][1]['range'][0]
end_port = elem[1]['concat'][1]['range'][1]
port_range = f'{start_port}-{end_port}'
- allocations.append((internal, external, port_range))
+ if (internal_address and internal != internal_address) or (
+ external_address and external != external_address
+ ):
+ continue
+
+ allocations.append(
+ {
+ 'internal_address': internal,
+ 'external_address': external,
+ 'port_range': port_range,
+ }
+ )
+
+ return allocations
+
+
+def _get_formatted_output(allocations: list[dict]) -> str:
+ # Convert the list of dictionaries to a list of tuples for tabulate
headers = ['Internal IP', 'External IP', 'Port range']
- output = tabulate(allocations, headers, numalign="left")
+ data = [
+ (alloc['internal_address'], alloc['external_address'], alloc['port_range'])
+ for alloc in allocations
+ ]
+ output = tabulate(data, headers, numalign="left")
return output
-def show_allocation(raw: bool):
+def show_allocation(
+ raw: bool,
+ external_address: typing.Optional[str],
+ internal_address: typing.Optional[str],
+) -> str:
config = ConfigTreeQuery()
if not config.exists('nat cgnat'):
raise vyos.opmode.UnconfiguredSubsystem('CGNAT is not configured')
if raw:
- return _get_raw_data()
+ return _get_raw_data(external_address, internal_address)
else:
- raw_data = _get_raw_data()
+ raw_data = _get_raw_data(external_address, internal_address)
return _get_formatted_output(raw_data)