diff --git a/docs/vyos.vyos.vyos_nat_module.rst b/docs/vyos.vyos.vyos_nat_module.rst index 2bacac84..af9a68fa 100644 --- a/docs/vyos.vyos.vyos_nat_module.rst +++ b/docs/vyos.vyos.vyos_nat_module.rst @@ -1,2803 +1,3293 @@ .. _vyos.vyos.vyos_nat_module: ****************** vyos.vyos.vyos_nat ****************** **NAT resource module** Version added: 1.0.0 .. contents:: :local: :depth: 1 Synopsis -------- -- This module manages NAT configuration on devices running Vyos +- This module manages NAT configuration on devices running VyOS. Parameters ---------- .. raw:: html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + - - - - + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + - - + - - - - - - - - - + - - + - - - - - + - - - - - + - - - - - - - - - - - - - - - - - - - -
Parameter Choices/Defaults Comments
config
dictionary
The desired configuration for the NAT resource represented as a dictionary.
nat
dictionary
Configuration for NAT rules.
cgnat
dictionary
Configuration for Carrier Grade NAT (CGNAT).
log_allocation
boolean
    Choices:
  • no
  • yes
-
Whether to log CGNAT address allocations.
+
Log CGNAT address allocations.
pool
dictionary
Configuration for CGNAT pools.
external
list / elements=dictionary
List of external NAT pools for CGNAT.
external_port_range
string
Port range to use for NAT translations in this external pool.
name
string / required
Name of the external NAT pool.
per_user_limit
dictionary
Per-user limit configuration for the external pool.
port
- integer + string
Maximum number of ports allocated per user.
range
list / elements=string
List of external IP addresses or prefixes in the pool.
internal
list / elements=dictionary
List of internal NAT pools for CGNAT.
name
string / required
Name of the internal NAT pool.
range
list / elements=string
List of internal IP addresses or prefixes in the pool.
rule
list / elements=dictionary
List of CGNAT rules.
id
integer / required
Rule number for CGNAT.
source
dictionary
-
Source configuration for CGNAT translation.
+
Source pool configuration for CGNAT translation.
pool
string
-
Source pool to use for CGNAT translation.
+
Source pool name to use for CGNAT translation.
translation
dictionary
-
Translation configuration for CGNAT.
+
Translation pool configuration for CGNAT.
pool
string
-
Translation pool to use for CGNAT translation.
+
Translation pool name to use for CGNAT translation.
destination
dictionary
Configuration for destination NAT rules.
rule
list / elements=dictionary
List of destination NAT rules.
description
string
User-friendly description of the destination NAT rule.
destination
dictionary
Match criteria for destination NAT.
address
string
-
IP address, subnet, or range to match for destination NAT.
+
IP address, subnet, or range to match.
+
+
+ address_group + +
+ string +
+
+ +
Address group name to match.
+
+
+ domain_group + +
+ string +
+
+ +
Domain group name to match.
+
+
+ fqdn + +
+ string +
+
+ +
Fully qualified domain name to match.
+
+
+ mac_group + +
+ string +
+
+ +
MAC address group name to match.
+
+
+ network_group + +
+ string +
+
+ +
Network group name to match.
+
+
+ port + +
+ string +
+
+ +
Port number or range to match.
+
+ port_group + +
+ string +
+
+ +
Port group name to match.
+
disable
boolean
    Choices:
  • no
  • yes
Disable this destination NAT rule.
+
exclude
boolean
    Choices:
  • no
  • yes
Exclude packets matching this rule from NAT.
+
+ id + +
+ integer + / required +
+
+ +
Rule number for destination NAT.
+
+
+ inbound_interface + +
+ dictionary +
+
+ +
Match inbound interface.
+
- fqdn + group
string
-
Fully qualified domain name to match for destination NAT.
+
Interface group to match.
- group + name
- dictionary + string
-
Address/network/port group to match for destination NAT.
+
Interface name to match.
+
+ log + +
+ boolean +
+
+
    Choices: +
  • no
  • +
  • yes
  • +
+
+
Log packets hitting this rule.
+
+
- address_group + packet_type
string
-
Address group name to match.
+
Packet type to match.
+
- domain_group + protocol
string
-
Domain group name to match.
+
Protocol to NAT (default all).
+
+ translation + +
+ dictionary +
+
+ +
Translation configuration for destination NAT.
+
+
- mac_group + address
string
-
MAC address group name to match.
+
IP address or prefix to translate destination to.
+
- network_group + address_mapping
string
+
    Choices: +
  • random
  • +
  • persistent
  • +
-
Network group name to match.
+
Address mapping mode for translation.
+
- port_group + port + +
+ string +
+
+ +
Port number or range to translate destination port to.
+
+
+ port_mapping + +
+ string +
+
+
    Choices: +
  • random
  • +
  • none
  • +
+
+
Port mapping mode for translation.
+
+
+ redirect_port + +
+ string +
+
+ +
Redirect to local port number.
+
+
+ source + +
+ dictionary +
+
+ +
Configuration for source NAT rules.
+
+
+ rule + +
+ list + / elements=dictionary +
+
+ +
List of source NAT rules.
+
+
+ description + +
+ string +
+
+ +
User-friendly description of the source NAT rule.
+
+
+ destination + +
+ dictionary +
+
+ +
Destination match criteria for source NAT.
+
+
+ address + +
+ string +
+
+ +
IP address, subnet, or range to match.
+
+
+ address_group + +
+ string +
+
+ +
Address group name to match.
+
+
+ domain_group + +
+ string +
+
+ +
Domain group name to match.
+
+
+ fqdn + +
+ string +
+
+ +
Fully qualified domain name to match.
+
+
+ mac_group + +
+ string +
+
+ +
MAC address group name to match.
+
+
+ network_group + +
+ string +
+
+ +
Network group name to match.
+
+
+ port + +
+ string +
+
+ +
Port number or range to match.
+
+
+ port_group + +
+ string +
+
+ +
Port group name to match.
+
+
+ disable + +
+ boolean +
+
+
    Choices: +
  • no
  • +
  • yes
  • +
+
+
Disable this source NAT rule.
+
+
+ exclude + +
+ boolean +
+
+
    Choices: +
  • no
  • +
  • yes
  • +
+
+
Exclude packets matching this rule from NAT.
+
+
+ id
- string + integer + / required
-
Port group name to match.
+
Rule number for source NAT.
+
log
boolean
    Choices:
  • no
  • yes
-
Log packets hitting this destination NAT rule.
+
Log packets hitting this rule.
+
- port + outbound_interface
- string + dictionary
-
Port number or range for destination NAT.
+
Match outbound interface.
- protocol + group
string
-
Protocol to match (TCP, UDP, ICMP, etc.).
+
Interface group to match.
+
- id + name
- integer - / required + string
-
Rule number for destination NAT.
+
Interface name to match.
-
- source - -
- dictionary -
-
- -
Configuration for source NAT rules.
-
+
- rule + packet_type
- list - / elements=dictionary + string
-
List of source NAT rules.
+
Packet type to match.
- description + protocol
string
-
User-friendly description of the source NAT rule.
+
Protocol to NAT (default all).
- destination + source
dictionary
-
Match criteria for source NAT.
+
Source match criteria for source NAT.
address
string
-
IP address, subnet, or range to match for source NAT.
+
IP address, subnet, or range to match.
- disable + address_group
- boolean + string
-
    Choices: -
  • no
  • -
  • yes
  • -
-
Disable this source NAT rule.
+
Address group name to match.
- exclude + domain_group
- boolean + string
-
    Choices: -
  • no
  • -
  • yes
  • -
-
Exclude packets matching this rule from NAT.
+
Domain group name to match.
fqdn
string
-
Fully qualified domain name to match for source NAT.
+
Fully qualified domain name to match.
- group + mac_group
- dictionary + string
-
Address/network/port group to match for source NAT.
+
MAC address group name to match.
+
- address_group + network_group
string
-
Address group name to match.
+
Network group name to match.
+
- domain_group + port
string
-
Domain group name to match.
+
Port number or range to match.
+
- mac_group + port_group
string
-
MAC address group name to match.
+
Port group name to match.
+
- network_group + translation
- string + dictionary
-
Network group name to match.
+
Translation configuration for source NAT.
+
- port_group + address
string
-
Port group name to match.
+
IP address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address.
- log + address_mapping
- boolean + string
    Choices: -
  • no
  • -
  • yes
  • +
  • random
  • +
  • persistent
-
Log packets hitting this source NAT rule.
+
Address mapping mode for translation.
port
string
-
Port number or range for source NAT.
+
Port number or range to translate source port to.
- protocol + port_mapping
string
+
    Choices: +
  • random
  • +
  • none
  • +
-
Protocol to match (TCP, UDP, ICMP, etc.).
+
Port mapping mode for translation.
-
- id - -
- integer - / required -
-
- -
Rule number for source NAT.
-
static
dictionary
-
Configuration for static NAT rules.
+
Configuration for static one-to-one NAT rules.
rule
list / elements=dictionary
List of static NAT rules.
description
string
User-friendly description of the static NAT rule.
destination
dictionary
Match criteria for static NAT.
address
string
-
IP address, subnet, or range to match for static NAT.
+
IP address, subnet, or range to match.
-
- disable - -
- boolean -
-
-
    Choices: -
  • no
  • -
  • yes
  • -
-
-
Disable this static NAT rule.
-
id
integer / required
-
Rule number for static NAT (one-to-one).
+
Rule number for static NAT.
inbound_interface
string
-
List of inbound interfaces that this static NAT rule applies to.
+
Inbound interface that this static NAT rule applies to.
log
boolean
    Choices:
  • no
  • yes
Log packets hitting this static NAT rule.
translation
dictionary
Translation configuration for static NAT.
address
string
IP address or prefix to translate to.
nat64
dictionary
-
Configuration for NAT64 (IPv6-to-IPv4 NAT) rules.
+
Configuration for NAT64 (IPv6-to-IPv4) rules.
source
dictionary
Configuration for NAT64 source rules.
rule
list / elements=dictionary
List of NAT64 source rules.
description
string
User-friendly description of the NAT64 source rule.
disable
boolean
    Choices:
  • no
  • yes
Disable this NAT64 source rule.
id
integer / required
-
Rule number for NAT64 source rule.
+
Rule number for NAT64 source rule (1-999999).
match
dictionary
Match criteria for NAT64 source rule.
mark
- integer + string
Match on firewall mark value (1-2147483647).
source
dictionary
-
Source prefix to match for NAT64 translation.
+
IPv6 source prefix to match for NAT64 translation.
prefix
string
IPv6 source prefix to match (h:h:h:h:h:h:h:h/x).
translation
dictionary
Translation configuration for NAT64 source rule.
pool
list / elements=dictionary
List of translation pools for NAT64.
address
string
IPv4 address or prefix for translation pool.
description
string
User-friendly description of the translation pool.
disable
boolean
    Choices:
  • no
  • yes
Disable this translation pool.
id
integer / required
Pool number (1-999999).
port
string
Port number or range for translation pool.
protocol
string
    Choices:
  • icmp
  • tcp
  • udp
Protocol for this translation pool entry.
nat66
dictionary
-
Configuration for NAT66 (IPv6-to-IPv6 NAT) rules.
+
Configuration for NAT66 (IPv6-to-IPv6) rules.
destination
dictionary
Configuration for NAT66 destination rules.
rule
list / elements=dictionary
List of NAT66 destination rules.
description
string
User-friendly description of the NAT66 destination rule.
destination
dictionary
Match criteria for NAT66 destination rule.
address
string
-
IPv6 address or prefix to match. Supports single address (h:h:h:h:h:h:h:h), prefix (h:h:h:h:h:h:h:h/x), and negated forms (!h:h:h:h:h:h:h:h, !h:h:h:h:h:h:h:h/x).
+
IPv6 address or prefix to match.
port
string
-
Port number, range, or name to match.
+
Port number or range to match.
disable
boolean
    Choices:
  • no
  • yes
Disable this NAT66 destination rule.
exclude
boolean
    Choices:
  • no
  • yes
Exclude packets matching this rule from NAT66.
id
integer / required
Rule number for NAT66 destination rule.
inbound_interface
dictionary
Inbound interface to match for NAT66 destination rule.
name
string
-
Interface name to match. Supports wildcard (txt*) and negated (!text) forms.
+
Interface name to match.
log
boolean
    Choices:
  • no
  • yes
Log packets hitting this NAT66 destination rule.
protocol
string
-
Protocol to match. Supports named protocols, numeric (0-255), negated (!protocol), all, and tcp_udp.
+
Protocol to match.
source
dictionary
Source match criteria for NAT66 destination rule.
address
string
-
IPv6 source address or prefix to match. Supports single address, prefix, and negated forms.
+
IPv6 source address or prefix to match.
port
string
-
Source port number, range, or name to match.
+
Source port number or range to match.
translation
dictionary
Translation configuration for NAT66 destination rule.
address
string
IPv6 address or prefix to translate destination to.
port
string
Port number or range to translate destination port to.
source
dictionary
Configuration for NAT66 source rules.
rule
list / elements=dictionary
List of NAT66 source rules.
description
string
User-friendly description of the NAT66 source rule.
destination
dictionary
Destination match criteria for NAT66 source rule.
port
string
-
Destination port number, range, or name to match.
+
Destination port number or range to match.
prefix
string
-
IPv6 destination prefix to match (h:h:h:h:h:h:h:h/x). Supports negated form (!h:h:h:h:h:h:h:h/x).
+
IPv6 destination prefix to match (h:h:h:h:h:h:h:h/x).
disable
boolean
    Choices:
  • no
  • yes
Disable this NAT66 source rule.
exclude
boolean
    Choices:
  • no
  • yes
Exclude packets matching this rule from NAT66.
id
integer / required
Rule number for NAT66 source rule.
log
boolean
    Choices:
  • no
  • yes
Log packets hitting this NAT66 source rule.
outbound_interface
dictionary
Outbound interface to match for NAT66 source rule.
name
string
-
Interface name to match. Supports wildcard (txt*) and negated (!text) forms.
+
Interface name to match.
protocol
string
-
Protocol to match. Supports named protocols, numeric (0-255), negated (!protocol), all, and tcp_udp.
+
Protocol to match.
source
dictionary
Source match criteria for NAT66 source rule.
port
string
-
Source port number, range, or name to match.
+
Source port number or range to match.
prefix
string
-
IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). Supports negated form (!h:h:h:h:h:h:h:h/x).
+
IPv6 source prefix to match (h:h:h:h:h:h:h:h/x).
translation
dictionary
Translation configuration for NAT66 source rule.
address
string
IPv6 address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address.
port
string
Port number or range to translate source port to.
running_config
string
This option is used only with state parsed.
-
The value of this option should be the output received from the VYOS device by executing the command show configuration commands | grep nat.
+
The value of this option should be the output received from the VyOS device by executing the command show configuration commands | grep nat.
+
The state parsed reads the configuration from show configuration commands | grep nat and transforms it into Ansible structured data as per the module argspec. The value is then returned in the parsed key within the result.
The states replaced and overridden have identical behaviour for this module.
-
The state parsed reads the configuration from show configuration commands | grep nat option and transforms it into Ansible structured data as per the resource module's argspec and the value is then returned in the parsed key within the result.
state
string
    Choices:
  • deleted
  • merged ←
  • overridden
  • replaced
  • gathered
  • rendered
  • parsed
The state the configuration should be left in.

Notes ----- .. note:: - - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 + - Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection ``network_cli``. Examples -------- .. code-block:: yaml - # Using merged - - name: Merge NAT source rule + # Using merged - configure CGNAT + - name: Merge CGNAT configuration + vyos.vyos.vyos_nat: + config: + nat: + cgnat: + log_allocation: true + pool: + external: + - name: ext-pool-1 + external_port_range: "10000-20000" + per_user_limit: + port: "200" + range: + - 203.0.113.0/24 + internal: + - name: int-pool-1 + range: + - 10.0.0.0/24 + rule: + - id: 1 + source: + pool: int-pool-1 + translation: + pool: ext-pool-1 + state: merged + + # Using merged - configure destination NAT + - name: Merge destination NAT rule + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Web server NAT" + protocol: tcp + log: true + destination: + address: 198.51.100.10 + port: "80" + translation: + address: 192.168.1.10 + port: "8080" + state: merged + + # Using merged - configure source NAT + - name: Merge source NAT rule + vyos.vyos.vyos_nat: + config: + nat: + source: + rule: + - id: 200 + description: "Outbound masquerade" + protocol: tcp + log: true + outbound_interface: + name: eth0 + translation: + address: masquerade + state: merged + + # Using merged - configure static NAT + - name: Merge static NAT rule + vyos.vyos.vyos_nat: + config: + nat: + static: + rule: + - id: 300 + description: "Static mapping" + inbound_interface: eth2 + destination: + address: 198.51.100.20 + translation: + address: 192.168.1.20 + log: true + state: merged + + # Using merged - configure NAT64 + - name: Merge NAT64 source rule + vyos.vyos.vyos_nat: + config: + nat64: + source: + rule: + - id: 10 + description: "NAT64 example" + source: + prefix: 2001:db8::/96 + match: + mark: "100" + translation: + pool: + - id: 1 + address: 192.168.100.10 + port: "1-65535" + protocol: udp + state: merged + + # Using merged - configure NAT66 + - name: Merge NAT66 destination rule vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Outbound masquerade" + nat66: + destination: + rule: + - id: 20 + description: "NAT66 DNAT" + protocol: tcp + inbound_interface: + name: eth1 + destination: + address: 2001:db8::1 + translation: + address: 2001:db8:1::10 + port: "8443" state: merged # Using gathered - name: Gather NAT config vyos.vyos.vyos_nat: state: gathered # Using deleted - - name: Delete NAT config + - name: Delete all NAT config vyos.vyos.vyos_nat: state: deleted # Using replaced - - name: Replace NAT config + - name: Replace NAT source rules vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Replaced rule" + nat: + source: + rule: + - id: 200 + description: "Replaced outbound rule" + translation: + address: masquerade state: replaced # Using parsed - - name: Parse NAT config + - name: Parse NAT config from file vyos.vyos.vyos_nat: running_config: "{{ lookup('file', './nat_config.cfg') }}" state: parsed # Using rendered - name: Render NAT config offline vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Rendered rule" + nat: + source: + rule: + - id: 200 + description: "Rendered rule" + translation: + address: masquerade state: rendered -Return Values -------------- -Common return values are documented `here `_, the following are the fields unique to this module: - -.. raw:: html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyReturnedDescription
-
- after - -
- dictionary -
-
when changed -
The resulting configuration after module execution.
-
-
Sample:
-
This output will always be in the same format as the module argspec.
-
-
- before - -
- dictionary -
-
when state is merged, replaced, overridden, deleted or purged -
The configuration prior to the module execution.
-
-
Sample:
-
This output will always be in the same format as the module argspec.
-
-
- commands - -
- list -
-
when state is merged, replaced, overridden, deleted or purged -
The set of commands pushed to the remote device.
-
-
Sample:
-
["set nat source rule 100 description 'Outbound masquerade'"]
-
-
- gathered - -
- dictionary -
-
when state is gathered -
Facts about the network resource gathered from the remote device as structured data.
-
-
Sample:
-
This output will always be in the same format as the module argspec.
-
-
- parsed - -
- dictionary -
-
when state is parsed -
The device native config provided in running_config option parsed into structured data as per module argspec.
-
-
Sample:
-
This output will always be in the same format as the module argspec.
-
-
- rendered - -
- list -
-
when state is rendered -
The provided configuration in the task rendered in device-native format (offline).
-
-
Sample:
-
["set nat source rule 100 description 'Rendered rule'"]
-
-

- Status ------ Authors ~~~~~~~ - Evgeny Molotkov (@omnom62) diff --git a/plugins/module_utils/network/vyos/rm_templates/nat.py b/plugins/module_utils/network/vyos/rm_templates/nat.py index c6d6eedb..abc7eb5b 100644 --- a/plugins/module_utils/network/vyos/rm_templates/nat.py +++ b/plugins/module_utils/network/vyos/rm_templates/nat.py @@ -1,1229 +1,1229 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function __metaclass__ = type import re from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) class NatTemplate(NetworkTemplate): def __init__(self, lines=None, module=None): prefix = {"set": "set", "remove": "delete"} super(NatTemplate, self).__init__(lines=lines, tmplt=self, prefix=prefix, module=module) # def parse(self): # data = super(NatTemplate, self).parse() # return self._normalize(data) # def _normalize(self, data): # def convert_rules(section): # if not section or "rule" not in section: # return section # rules = section["rule"] # if isinstance(rules, dict): # new_rules = [] # for rule_id, rule_data in rules.items(): # rule = rule_data.copy() # # normalize id # try: # rule["id"] = int(rule_id) # except (ValueError, TypeError): # rule["id"] = rule_id # new_rules.append(rule) # section["rule"] = sorted(new_rules, key=lambda x: x.get("id", 0)) # return section # if not data: # return data # for nat_type in ["nat", "nat64", "nat66"]: # if nat_type not in data: # continue # nat = data[nat_type] # for block in ["destination", "source", "static"]: # if block in nat: # nat[block] = convert_rules(nat[block]) # # CGNAT rules # if "cgnat" in nat and "rule" in nat["cgnat"]: # rules = nat["cgnat"]["rule"] # if isinstance(rules, list): # for r in rules: # if "id" in r: # r["id"] = int(r["id"]) # return data # def _normalize(self, data): # if not data: # return data # def normalize_rules(rules): # """Convert rules dict → sorted list with int IDs, or cast IDs in existing list.""" # if isinstance(rules, dict): # result = [] # for rule_id, rule_data in rules.items(): # rule = rule_data.copy() # try: # rule["id"] = int(rule_id) # except (ValueError, TypeError): # rule["id"] = rule_id # result.append(rule) # return sorted(result, key=lambda x: x.get("id", 0)) # if isinstance(rules, list): # for rule in rules: # if "id" in rule: # try: # rule["id"] = int(rule["id"]) # except (ValueError, TypeError): # pass # return rules # return rules # for nat_type in ["nat", "nat64", "nat66"]: # nat = data.get(nat_type) # if not nat: # continue # for block in ["destination", "source", "static", "cgnat"]: # section = nat.get(block) # if section and "rule" in section: # section["rule"] = normalize_rules(section["rule"]) # return data # fmt: off PARSERS = [ # # ------------------------- # CGNAT (keep explicit) # ------------------------- # { "name": "cgnat_log_allocation", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+log-allocation $""", re.VERBOSE, ), "setval": "nat cgnat log-allocation", "result": { "nat": { "cgnat": { "log_allocation": True, }, }, }, }, { "name": "cgnat_pool_external_range", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+pool \s+external \s+(?P\S+) \s+range \s+(?P\S+)(?:\s+seq\s+(?P\d+))? $""", re.VERBOSE, ), "setval": "nat cgnat pool external {{ name }} range {{ range }}{% if seq is defined %} seq {{ seq }}{% endif %}", "result": { "nat": { "cgnat": { "pool": { "external": [ { "name": "{{ name }}", "range": ["{{ range }}"], "seq": "{{ seq }}", }, ], }, }, }, }, }, { "name": "cgnat_pool_external_port_range", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+pool \s+external \s+(?P\S+) \s+external-port-range \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat cgnat pool external {{ name }} external-port-range {{ range }}", "result": { "nat": { "cgnat": { "pool": { "external": [ { "name": "{{ name }}", "external_port_range": "{{ range }}", }, ], }, }, }, }, }, { "name": "cgnat_pool_external_per_user", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+pool \s+external \s+(?P\S+) \s+per-user-limit \s+port \s+(?P\d+) $""", re.VERBOSE, ), "setval": "nat cgnat pool external {{ name }} per-user-limit port {{ limit }}", "result": { "nat": { "cgnat": { "pool": { "external": [ { "name": "{{ name }}", "per_user_limit": {"port": "{{ limit }}"}, }, ], }, }, }, }, }, { "name": "cgnat_pool_internal_range", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+pool \s+internal \s+(?P\S+) \s+range \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat cgnat pool internal {{ name }} range {{ range }}", "result": { "nat": { "cgnat": { "pool": { "internal": [ { "name": "{{ name }}", "range": ["{{ range }}"], }, ], }, }, }, }, }, { "name": "cgnat_rule_source_pool", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+rule \s+(?P\d+) \s+source \s+pool \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat cgnat rule {{ id }} source pool {{ pool }}", "result": { "nat": { "cgnat": { "rule": [ { "id": "{{ id }}", "source": {"pool": "{{ pool }}"}, }, ], }, }, }, }, { "name": "cgnat_rule_translation_pool", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+rule \s+(?P\d+) \s+translation \s+pool \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat cgnat rule {{ id }} translation pool {{ pool }}", "result": { "nat": { "cgnat": { "rule": [ { "id": "{{ id }}", "translation": {"pool": "{{ pool }}"}, }, ], }, }, }, }, # # ------------------------- # GENERIC NAT (destination/source/static) # ------------------------- # # description { "name": "nat_type_description", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+description \s+(?P.+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} description {{ description }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "description": "{{ description }}", }, ], }, }, }, }, # protocol { "name": "nat_type_protocol", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+protocol \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} protocol {{ protocol }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "protocol": "{{ protocol }}", }, ], }, }, }, }, # flags { "name": "nat_type_disable", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+disable $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} disable", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "disable": True, }, ], }, }, }, }, { "name": "nat_type_exclude", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+exclude $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} exclude", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "exclude": True, }, ], }, }, }, }, { "name": "nat_type_log", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+log $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} log", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "log": True, }, ], }, }, }, }, # address (destination/source) { "name": "nat_type_address", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} address {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"address": "{{ value }}"}, }, ], }, }, }, }, # prefix (destination/source) { "name": "nat_type_prefix", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+prefix \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} prefix {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"prefix": "{{ value }}"}, }, ], }, }, }, }, # fqdn { "name": "nat_type_fqdn", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+fqdn \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} fqdn {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"fqdn": "{{ value }}"}, }, ], }, }, }, }, # port { "name": "nat_type_port", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"port": "{{ value }}"}, }, ], }, }, }, }, # translation address { "name": "nat_type_translation_address", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+translation \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation address {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": {"address": "{{ value }}"}, }, ], }, }, }, }, # translation port { "name": "nat_type_translation_port", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": {"port": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_inbound_interface_name", "getval": re.compile( r""" ^set \s+nat \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+inbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat {{ type }} rule {{ id }} inbound-interface name {{ value }}", "result": { "nat": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "inbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_inbound_interface_group", "getval": re.compile( r""" ^set \s+nat \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+inbound-interface \s+group \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat {{ type }} rule {{ id }} inbound-interface group {{ value }}", "result": { "nat": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "inbound_interface": {"group": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_static_inbound_interface", "getval": re.compile( r""" ^set \s+nat \s+static \s+rule \s+(?P\S+) \s+inbound-interface \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat static rule {{ id }} inbound-interface {{ value }}", "result": { "nat": { "static": { "rule": [ { "id": "{{ id }}", "inbound_interface": "{{ value }}", }, ], }, }, }, }, # NAT6X inbound interface { "name": "nat6x_inbound_interface", "getval": re.compile( r""" ^set \s+(?Pnat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+inbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} inbound-interface name {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", - "inbound_interface": "{{ value }}", + "inbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, # outbound interface { "name": "nat_type_outbound_interface", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+outbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} outbound-interface name {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "outbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_type_outbound_interface_group", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+outbound-interface \s+group \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} outbound-interface group {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "outbound_interface": {"group": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_type_address_group", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+group \s+(?Paddress-group|domain-group|mac-group|network-group|port-group) \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} group {{ gtype }} {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": { "{{ gtype | replace('-', '_') }}": "{{ value }}", }, }, ], }, }, }, }, # packet type { "name": "nat_type_packet_type", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+packet-type \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} packet-type {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "packet_type": "{{ value }}", }, ], }, }, }, }, # load balance backend { "name": "nat_type_lb_backend", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+load-balance \s+backend \s+(?P\S+) \s+weight \s+(?P\d+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} load-balance backend {{ ip }} weight {{ weight }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "load_balance": { "backend": { "ip": "{{ ip }}", "weight": "{{ weight }}", }, }, }, ], }, }, }, }, # load balance hash { "name": "nat_type_lb_hash", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+load-balance \s+hash \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} load-balance hash {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "load_balance": {"hash": "{{ value }}"}, }, ], }, }, }, }, # translation options { "name": "nat_type_translation_options", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+options \s+(?Paddress-mapping|port-mapping) \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation options {{ opt }} {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": { "{{ opt | replace(\"-\", \"_\") }}": "{{ value }}", }, }, ], }, }, }, }, # redirect port { "name": "nat_type_translation_redirect", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+redirect \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation redirect port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": { "redirect_port": "{{ value }}", }, }, ], }, }, }, }, { "name": "nat64_match_mark", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+match \s+mark \s+(?P\d+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} match mark {{ mark }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "match": {"mark": "{{ mark }}"}, }, ], }, }, }, }, { "name": "nat64_translation_pool_address", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} address {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "address": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_description", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+description \s+(?P.+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} description {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "description": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_disable", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+disable $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} disable", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "disable": True}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_port", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} port {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "port": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_protocol", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+protocol \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} protocol {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "protocol": "{{ value }}"}], }, }, ], }, }, }, }, ] # fmt: on diff --git a/plugins/modules/vyos_nat.py b/plugins/modules/vyos_nat.py index 1bc9a544..a56432e9 100644 --- a/plugins/modules/vyos_nat.py +++ b/plugins/modules/vyos_nat.py @@ -1,639 +1,782 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # Copyright 2024 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The module file for vyos_nat """ from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = """ module: vyos_nat version_added: 1.0.0 short_description: NAT resource module description: -- This module manages NAT configuration on devices running Vyos +- This module manages NAT configuration on devices running VyOS. author: - Evgeny Molotkov (@omnom62) notes: -- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025 +- Tested against VyOS 1.3.8, 1.4.2, the upcoming 1.5, and the rolling release of spring 2025. - This module works with connection C(network_cli). options: config: description: - The desired configuration for the NAT resource represented as a dictionary. type: dict suboptions: nat: type: dict description: Configuration for NAT rules. suboptions: cgnat: type: dict description: Configuration for Carrier Grade NAT (CGNAT). suboptions: log_allocation: type: bool - description: Whether to log CGNAT address allocations. + description: Log CGNAT address allocations. pool: type: dict description: Configuration for CGNAT pools. suboptions: external: type: list elements: dict description: List of external NAT pools for CGNAT. suboptions: name: type: str required: true description: Name of the external NAT pool. external_port_range: type: str description: Port range to use for NAT translations in this external pool. per_user_limit: type: dict description: Per-user limit configuration for the external pool. suboptions: port: - type: int + type: str description: Maximum number of ports allocated per user. range: type: list elements: str description: List of external IP addresses or prefixes in the pool. internal: type: list elements: dict description: List of internal NAT pools for CGNAT. suboptions: name: type: str required: true description: Name of the internal NAT pool. range: type: list elements: str description: List of internal IP addresses or prefixes in the pool. rule: type: list elements: dict description: List of CGNAT rules. suboptions: id: type: int required: true description: Rule number for CGNAT. source: type: dict - description: Source configuration for CGNAT translation. + description: Source pool configuration for CGNAT translation. suboptions: pool: type: str - description: Source pool to use for CGNAT translation. + description: Source pool name to use for CGNAT translation. translation: type: dict - description: Translation configuration for CGNAT. + description: Translation pool configuration for CGNAT. suboptions: pool: type: str - description: Translation pool to use for CGNAT translation. + description: Translation pool name to use for CGNAT translation. destination: type: dict description: Configuration for destination NAT rules. suboptions: rule: type: list elements: dict description: List of destination NAT rules. suboptions: id: type: int required: true description: Rule number for destination NAT. description: type: str description: User-friendly description of the destination NAT rule. + protocol: + type: str + description: Protocol to NAT (default all). + packet_type: + type: str + description: Packet type to match. + exclude: + type: bool + description: Exclude packets matching this rule from NAT. + log: + type: bool + description: Log packets hitting this rule. + disable: + type: bool + description: Disable this destination NAT rule. + inbound_interface: + type: dict + description: Match inbound interface. + suboptions: + name: + type: str + description: Interface name to match. + group: + type: str + description: Interface group to match. destination: type: dict description: Match criteria for destination NAT. suboptions: address: type: str - description: IP address, subnet, or range to match for destination NAT. + description: IP address, subnet, or range to match. fqdn: type: str - description: Fully qualified domain name to match for destination NAT. - group: - type: dict - description: Address/network/port group to match for destination NAT. - suboptions: - address_group: - type: str - description: Address group name to match. - domain_group: - type: str - description: Domain group name to match. - mac_group: - type: str - description: MAC address group name to match. - network_group: - type: str - description: Network group name to match. - port_group: - type: str - description: Port group name to match. + description: Fully qualified domain name to match. port: type: str - description: Port number or range for destination NAT. - protocol: - type: str - description: Protocol to match (TCP, UDP, ICMP, etc.). - exclude: - type: bool - description: Exclude packets matching this rule from NAT. - log: - type: bool - description: Log packets hitting this destination NAT rule. - disable: - type: bool - description: Disable this destination NAT rule. + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + translation: + type: dict + description: Translation configuration for destination NAT. + suboptions: + address: + type: str + description: IP address or prefix to translate destination to. + port: + type: str + description: Port number or range to translate destination port to. + redirect_port: + type: str + description: Redirect to local port number. + address_mapping: + type: str + choices: + - random + - persistent + description: Address mapping mode for translation. + port_mapping: + type: str + choices: + - random + - none + description: Port mapping mode for translation. source: type: dict description: Configuration for source NAT rules. suboptions: rule: type: list elements: dict description: List of source NAT rules. suboptions: id: type: int required: true description: Rule number for source NAT. description: type: str description: User-friendly description of the source NAT rule. + protocol: + type: str + description: Protocol to NAT (default all). + packet_type: + type: str + description: Packet type to match. + exclude: + type: bool + description: Exclude packets matching this rule from NAT. + log: + type: bool + description: Log packets hitting this rule. + disable: + type: bool + description: Disable this source NAT rule. + outbound_interface: + type: dict + description: Match outbound interface. + suboptions: + name: + type: str + description: Interface name to match. + group: + type: str + description: Interface group to match. destination: type: dict - description: Match criteria for source NAT. + description: Destination match criteria for source NAT. suboptions: address: type: str - description: IP address, subnet, or range to match for source NAT. + description: IP address, subnet, or range to match. fqdn: type: str - description: Fully qualified domain name to match for source NAT. - group: - type: dict - description: Address/network/port group to match for source NAT. - suboptions: - address_group: - type: str - description: Address group name to match. - domain_group: - type: str - description: Domain group name to match. - mac_group: - type: str - description: MAC address group name to match. - network_group: - type: str - description: Network group name to match. - port_group: - type: str - description: Port group name to match. + description: Fully qualified domain name to match. port: type: str - description: Port number or range for source NAT. - protocol: - type: str - description: Protocol to match (TCP, UDP, ICMP, etc.). - exclude: - type: bool - description: Exclude packets matching this rule from NAT. - log: - type: bool - description: Log packets hitting this source NAT rule. - disable: - type: bool - description: Disable this source NAT rule. + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + source: + type: dict + description: Source match criteria for source NAT. + suboptions: + address: + type: str + description: IP address, subnet, or range to match. + fqdn: + type: str + description: Fully qualified domain name to match. + port: + type: str + description: Port number or range to match. + address_group: + type: str + description: Address group name to match. + domain_group: + type: str + description: Domain group name to match. + mac_group: + type: str + description: MAC address group name to match. + network_group: + type: str + description: Network group name to match. + port_group: + type: str + description: Port group name to match. + translation: + type: dict + description: Translation configuration for source NAT. + suboptions: + address: + type: str + description: IP address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address. + port: + type: str + description: Port number or range to translate source port to. + address_mapping: + type: str + choices: + - random + - persistent + description: Address mapping mode for translation. + port_mapping: + type: str + choices: + - random + - none + description: Port mapping mode for translation. static: type: dict - description: Configuration for static NAT rules. + description: Configuration for static one-to-one NAT rules. suboptions: rule: type: list elements: dict description: List of static NAT rules. suboptions: id: type: int required: true - description: Rule number for static NAT (one-to-one). + description: Rule number for static NAT. description: type: str description: User-friendly description of the static NAT rule. destination: type: dict description: Match criteria for static NAT. suboptions: address: type: str - description: IP address, subnet, or range to match for static NAT. + description: IP address, subnet, or range to match. + inbound_interface: + type: str + description: Inbound interface that this static NAT rule applies to. log: type: bool description: Log packets hitting this static NAT rule. - disable: - type: bool - description: Disable this static NAT rule. - inbound_interface: - type: str - description: List of inbound interfaces that this static NAT rule applies to. translation: type: dict description: Translation configuration for static NAT. suboptions: address: type: str description: IP address or prefix to translate to. nat64: type: dict - description: Configuration for NAT64 (IPv6-to-IPv4 NAT) rules. + description: Configuration for NAT64 (IPv6-to-IPv4) rules. suboptions: source: type: dict description: Configuration for NAT64 source rules. suboptions: rule: type: list elements: dict description: List of NAT64 source rules. suboptions: id: type: int required: true - description: Rule number for NAT64 source rule. + description: Rule number for NAT64 source rule (1-999999). description: type: str description: User-friendly description of the NAT64 source rule. disable: type: bool description: Disable this NAT64 source rule. match: type: dict description: Match criteria for NAT64 source rule. suboptions: mark: - type: int + type: str description: Match on firewall mark value (1-2147483647). source: type: dict - description: Source prefix to match for NAT64 translation. + description: IPv6 source prefix to match for NAT64 translation. suboptions: prefix: type: str description: IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). translation: type: dict description: Translation configuration for NAT64 source rule. suboptions: pool: type: list elements: dict description: List of translation pools for NAT64. suboptions: id: type: int required: true description: Pool number (1-999999). address: type: str description: IPv4 address or prefix for translation pool. description: type: str description: User-friendly description of the translation pool. disable: type: bool description: Disable this translation pool. port: type: str description: Port number or range for translation pool. protocol: type: str choices: - icmp - tcp - udp description: Protocol for this translation pool entry. nat66: type: dict - description: Configuration for NAT66 (IPv6-to-IPv6 NAT) rules. + description: Configuration for NAT66 (IPv6-to-IPv6) rules. suboptions: destination: type: dict description: Configuration for NAT66 destination rules. suboptions: rule: type: list elements: dict description: List of NAT66 destination rules. suboptions: id: type: int required: true description: Rule number for NAT66 destination rule. description: type: str description: User-friendly description of the NAT66 destination rule. destination: type: dict description: Match criteria for NAT66 destination rule. suboptions: address: type: str - description: > - IPv6 address or prefix to match. Supports single address - (h:h:h:h:h:h:h:h), prefix (h:h:h:h:h:h:h:h/x), and negated - forms (!h:h:h:h:h:h:h:h, !h:h:h:h:h:h:h:h/x). + description: IPv6 address or prefix to match. port: type: str - description: Port number, range, or name to match. + description: Port number or range to match. disable: type: bool description: Disable this NAT66 destination rule. exclude: type: bool description: Exclude packets matching this rule from NAT66. inbound_interface: type: dict description: Inbound interface to match for NAT66 destination rule. suboptions: name: type: str - description: > - Interface name to match. Supports wildcard (txt*) and - negated (!text) forms. + description: Interface name to match. log: type: bool description: Log packets hitting this NAT66 destination rule. protocol: type: str - description: > - Protocol to match. Supports named protocols, numeric (0-255), - negated (!protocol), all, and tcp_udp. + description: Protocol to match. source: type: dict description: Source match criteria for NAT66 destination rule. suboptions: address: type: str - description: > - IPv6 source address or prefix to match. Supports single - address, prefix, and negated forms. + description: IPv6 source address or prefix to match. port: type: str - description: Source port number, range, or name to match. + description: Source port number or range to match. translation: type: dict description: Translation configuration for NAT66 destination rule. suboptions: address: type: str description: IPv6 address or prefix to translate destination to. port: type: str description: Port number or range to translate destination port to. source: type: dict description: Configuration for NAT66 source rules. suboptions: rule: type: list elements: dict description: List of NAT66 source rules. suboptions: id: type: int required: true description: Rule number for NAT66 source rule. description: type: str description: User-friendly description of the NAT66 source rule. destination: type: dict description: Destination match criteria for NAT66 source rule. suboptions: port: type: str - description: Destination port number, range, or name to match. + description: Destination port number or range to match. prefix: type: str - description: > - IPv6 destination prefix to match (h:h:h:h:h:h:h:h/x). - Supports negated form (!h:h:h:h:h:h:h:h/x). + description: IPv6 destination prefix to match (h:h:h:h:h:h:h:h/x). disable: type: bool description: Disable this NAT66 source rule. exclude: type: bool description: Exclude packets matching this rule from NAT66. log: type: bool description: Log packets hitting this NAT66 source rule. outbound_interface: type: dict description: Outbound interface to match for NAT66 source rule. suboptions: name: type: str - description: > - Interface name to match. Supports wildcard (txt*) and - negated (!text) forms. + description: Interface name to match. protocol: type: str - description: > - Protocol to match. Supports named protocols, numeric (0-255), - negated (!protocol), all, and tcp_udp. + description: Protocol to match. source: type: dict description: Source match criteria for NAT66 source rule. suboptions: port: type: str - description: Source port number, range, or name to match. + description: Source port number or range to match. prefix: type: str - description: > - IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). - Supports negated form (!h:h:h:h:h:h:h:h/x). + description: IPv6 source prefix to match (h:h:h:h:h:h:h:h/x). translation: type: dict description: Translation configuration for NAT66 source rule. suboptions: address: type: str - description: > - IPv6 address or prefix to translate source to. - Use masquerade to masquerade as the outbound interface address. + description: IPv6 address or prefix to translate source to. Use masquerade to masquerade as the outbound interface address. port: type: str description: Port number or range to translate source port to. running_config: description: - This option is used only with state I(parsed). - - The value of this option should be the output received from the VYOS device by + - The value of this option should be the output received from the VyOS device by executing the command B(show configuration commands | grep nat). - - The states I(replaced) and I(overridden) have identical - behaviour for this module. - - The state I(parsed) reads the configuration from C(show configuration commands | grep nat) option and - transforms it into Ansible structured data as per the resource module's argspec - and the value is then returned in the I(parsed) key within the result. + - The state I(parsed) reads the configuration from C(show configuration commands | grep nat) + and transforms it into Ansible structured data as per the module argspec. + The value is then returned in the I(parsed) key within the result. + - The states I(replaced) and I(overridden) have identical behaviour for this module. type: str state: description: - The state the configuration should be left in. type: str choices: - deleted - merged - overridden - replaced - gathered - rendered - parsed default: merged """ EXAMPLES = """ -# Using merged -- name: Merge NAT source rule +# Using merged - configure CGNAT +- name: Merge CGNAT configuration vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Outbound masquerade" + nat: + cgnat: + log_allocation: true + pool: + external: + - name: ext-pool-1 + external_port_range: "10000-20000" + per_user_limit: + port: "200" + range: + - 203.0.113.0/24 + internal: + - name: int-pool-1 + range: + - 10.0.0.0/24 + rule: + - id: 1 + source: + pool: int-pool-1 + translation: + pool: ext-pool-1 + state: merged + +# Using merged - configure destination NAT +- name: Merge destination NAT rule + vyos.vyos.vyos_nat: + config: + nat: + destination: + rule: + - id: 100 + description: "Web server NAT" + protocol: tcp + log: true + destination: + address: 198.51.100.10 + port: "80" + translation: + address: 192.168.1.10 + port: "8080" + state: merged + +# Using merged - configure source NAT +- name: Merge source NAT rule + vyos.vyos.vyos_nat: + config: + nat: + source: + rule: + - id: 200 + description: "Outbound masquerade" + protocol: tcp + log: true + outbound_interface: + name: eth0 + translation: + address: masquerade + state: merged + +# Using merged - configure static NAT +- name: Merge static NAT rule + vyos.vyos.vyos_nat: + config: + nat: + static: + rule: + - id: 300 + description: "Static mapping" + inbound_interface: eth2 + destination: + address: 198.51.100.20 + translation: + address: 192.168.1.20 + log: true + state: merged + +# Using merged - configure NAT64 +- name: Merge NAT64 source rule + vyos.vyos.vyos_nat: + config: + nat64: + source: + rule: + - id: 10 + description: "NAT64 example" + source: + prefix: 2001:db8::/96 + match: + mark: "100" + translation: + pool: + - id: 1 + address: 192.168.100.10 + port: "1-65535" + protocol: udp + state: merged + +# Using merged - configure NAT66 +- name: Merge NAT66 destination rule + vyos.vyos.vyos_nat: + config: + nat66: + destination: + rule: + - id: 20 + description: "NAT66 DNAT" + protocol: tcp + inbound_interface: + name: eth1 + destination: + address: 2001:db8::1 + translation: + address: 2001:db8:1::10 + port: "8443" state: merged # Using gathered - name: Gather NAT config vyos.vyos.vyos_nat: state: gathered # Using deleted -- name: Delete NAT config +- name: Delete all NAT config vyos.vyos.vyos_nat: state: deleted # Using replaced -- name: Replace NAT config +- name: Replace NAT source rules vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Replaced rule" + nat: + source: + rule: + - id: 200 + description: "Replaced outbound rule" + translation: + address: masquerade state: replaced # Using parsed -- name: Parse NAT config +- name: Parse NAT config from file vyos.vyos.vyos_nat: running_config: "{{ lookup('file', './nat_config.cfg') }}" state: parsed # Using rendered - name: Render NAT config offline vyos.vyos.vyos_nat: config: - source: - rule: - - id: 100 - description: "Rendered rule" + nat: + source: + rule: + - id: 200 + description: "Rendered rule" + translation: + address: masquerade state: rendered """ -RETURN = """ -before: - description: The configuration prior to the module execution. - returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) - type: dict - sample: > - This output will always be in the same format as the - module argspec. -after: - description: The resulting configuration after module execution. - returned: when changed - type: dict - sample: > - This output will always be in the same format as the - module argspec. -commands: - description: The set of commands pushed to the remote device. - returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged) - type: list - sample: - - set nat source rule 100 description 'Outbound masquerade' -rendered: - description: The provided configuration in the task rendered in device-native format (offline). - returned: when I(state) is C(rendered) - type: list - sample: - - set nat source rule 100 description 'Rendered rule' -gathered: - description: Facts about the network resource gathered from the remote device as structured data. - returned: when I(state) is C(gathered) - type: dict - sample: > - This output will always be in the same format as the - module argspec. -parsed: - description: The device native config provided in I(running_config) option parsed into structured data as per module argspec. - returned: when I(state) is C(parsed) - type: dict - sample: > - This output will always be in the same format as the - module argspec. -""" - from ansible.module_utils.basic import AnsibleModule from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.nat.nat import ( NatArgs, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.nat.nat import ( Nat, ) def main(): """ Main entry point for module execution :returns: the result form module invocation """ module = AnsibleModule( argument_spec=NatArgs.argument_spec, mutually_exclusive=[["config", "running_config"]], required_if=[ ["state", "merged", ["config"]], ["state", "replaced", ["config"]], ["state", "overridden", ["config"]], ["state", "rendered", ["config"]], ["state", "parsed", ["running_config"]], ], supports_check_mode=True, ) result = Nat(module).execute_module() module.exit_json(**result) if __name__ == "__main__": main()