Skip to content

Conversation

@aijayadams
Copy link

Add explicit port parameters for nat_port_forward

Fixes #59

Summary

This PR adds explicit source_port and destination_port parameters to the pfsense_nat_port_forward module, completing the IPv6 support work started in #219 (PR #220).

Problem

While #219 fixed IPv6 address parsing in firewall rules by treating IPv6 addresses as single units (not splitting on :), this created a new problem for NAT port forwarding: there is no way to specify ports with IPv6 addresses.

The old :port syntax (e.g., address:port) has two issues:

  1. Already deprecated: The module warns: "the :ports syntax at end of addresses is deprecated and support will be removed soon. Please use source_port and destination_port options."

  2. Incompatible with IPv6: IPv6 addresses contain colons (e.g., 2001:db8::1). After the [pfsense_rule]: Cannot use IPv6 in source and destination #219 fix, the parser correctly treats 2001:db8::1 as a single address, making 2001:db8::1:443 ambiguous - is :443 part of the address or a port?

Proposed Change

This PR adds the parameters that the deprecation warning promised:

  • source_port: Explicit source port or range specification
  • destination_port: Explicit destination port or range specification

These parameters:

  • ✅ Enable IPv6 NAT port forwarding with port specifications
  • ✅ Remove the deprecation warning for IPv4 users
  • ✅ Provide a clean, unambiguous API
  • ✅ Support port ranges (e.g., "8000-9000")
  • ✅ Support port aliases
  • ✅ Maintain backward compatibility with existing :port syntax

Examples

Before this patch (BROKEN for IPv6)

- name: IPv6 NAT port forward - NO WAY TO SPECIFY PORT!
  pfsensible.core.pfsense_nat_port_forward:
    descr: "Forward HTTPS to internal IPv6 server"
    interface: wan
    ipprotocol: inet6
    protocol: tcp
    source: any
    destination: "2001:db8:cafe::1"  # How do we specify port 443?
    target: "fd00::1:443"
    state: present

Problem: Cannot specify destination port. The old syntax 2001:db8:cafe::1:443 doesn't work because after #219, IPv6 addresses are not split on :.

After this patch (WORKS)

- name: IPv6 NAT port forward with explicit port
  pfsensible.core.pfsense_nat_port_forward:
    descr: "Forward HTTPS to internal IPv6 server"
    interface: wan
    ipprotocol: inet6
    protocol: tcp
    source: any
    destination: "2001:db8:cafe::1"
    destination_port: "443"           # ✅ Clean, explicit port
    target: "fd00::1:8443"
    state: present

- name: Port range example
  pfsensible.core.pfsense_nat_port_forward:
    descr: "Forward port range"
    interface: wan
    ipprotocol: inet6
    protocol: tcp
    source: any
    source_port: "1024-65535"         # ✅ Source port filtering
    destination: "2001:db8:cafe::2"
    destination_port: "8000-9000"     # ✅ Destination port range
    target: "fd00::2:8000"
    state: present

IPv4 benefits too

- name: IPv4 with explicit syntax
  pfsensible.core.pfsense_nat_port_forward:
    descr: "IPv4 with explicit ports"
    interface: wan
    ipprotocol: inet
    protocol: tcp
    source: any
    destination: "192.168.1.1"
    destination_port: "443"           # ✅ No deprecation warning
    target: "10.0.0.5:8443"
    state: present

Implementation Details

Changes to plugins/module_utils/nat_port_forward.py:

  • Added source_port parameter to NAT_PORT_FORWARD_ARGUMENT_SPEC
  • Added destination_port parameter to NAT_PORT_FORWARD_ARGUMENT_SPEC
  • Added port validation using existing is_port_or_alias() method
  • Added port assignment to source/destination dictionaries

Changes to plugins/modules/pfsense_nat_port_forward.py:

  • Documented source_port parameter with examples
  • Documented destination_port parameter with examples

Backward Compatibility

This change is fully backward compatible:

  • Existing playbooks using :port syntax continue to work
  • The deprecation warning remains for the old syntax
  • New explicit parameters are optional
  • If both old and new syntax are used, explicit parameters take precedence

Testing

Tested with:

  • IPv6 addresses with explicit ports
  • IPv6 networks with port ranges
  • IPv4 addresses (both old and new syntax)
  • Port aliases
  • Source port filtering

Example test cases are provided in:

Related Work

This PR completes the IPv6 support started in:

That work fixed IPv6 parsing in the pfsense_rule module, but pfsense_nat_port_forward needed additional parameters to make port specifications work with IPv6.

Notes for Reviewers

The implementation closely follows the pattern used in pfsense_rule module and the existing address parsing infrastructure. The validation uses the existing is_port_or_alias() method to ensure consistency with other modules.

References to Issue #219

The fix for #219 (commit 7d91ba4) introduced this code in addresses.py:

def parse_address(self, param, allow_self=True):
    """ validate param address field and returns it as a dict """
    if self.is_ipv6_address(param) or self.is_ipv6_network(param):
        addr = [param]  # Don't split IPv6 addresses on ':'
    else:
        addr = param.split(':', maxsplit=3)

This correctly handles IPv6 addresses but eliminates the ability to use :port syntax with IPv6. The deprecation warning (line 148-149) already pointed toward using explicit parameters:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add destination_port etc to nat_port_forward

1 participant