From 0df992200c3ab9bcff0c584604cc1563c68b34b3 Mon Sep 17 00:00:00 2001 From: Steve Kerrison Date: Thu, 18 Sep 2025 11:39:58 +0800 Subject: [PATCH] Allow source NAT to use interface networks The old interface only lists interface addesses, not nets, and the rule parser parser only looks for interface names suffixed by "ip". In pf, interface address is used dynamically by being surrounded by parenthesis and includes the ":0" modifier to exclude aliases. By combining this with the ":network" modifier, source nat can also use an interface's network, dynamically, i.e. "($iface:network:0)". This is different to one-to-one nat because the source and target networks do not need to be the same size. Any of pf's pool options are valid in this situation. Signed-off-by: Steve Kerrison --- .../mvc/app/library/OPNsense/Firewall/SNatRule.php | 8 ++++++-- src/www/firewall_nat_out_edit.php | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php b/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php index a739bde9fd..e629037c84 100644 --- a/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php +++ b/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php @@ -91,12 +91,16 @@ class SNatRule extends Rule $this->log('SNAT / pool type not round-robin'); $rule['disabled'] = true; } - } elseif (preg_match("/^(wan|lan|opt[0-9]+)ip$/", $rule['target'], $matches)) { + } elseif (preg_match("/^(wan|lan|opt[0-9]+)(ip)?$/", $rule['target'], $matches)) { if (empty($this->interfaceMapping["{$matches[1]}"])) { $this->log("SNAT / target missing"); $rule['disabled'] = true; - } else { + } elseif (count($matches) == 3) { + // interface was suffixed by "ip", use its primary address $rule['target'] = "({$this->interfaceMapping["{$matches[1]}"]['if']}:0)"; + } else { + // network is possible here also, but only without aliases + $rule['target'] = "({$this->interfaceMapping["{$matches[1]}"]['if']}:network:0)"; } } foreach (array("sourceport", "dstport", "natport") as $fieldname) { diff --git a/src/www/firewall_nat_out_edit.php b/src/www/firewall_nat_out_edit.php index 4f47bf881c..6a504e982e 100644 --- a/src/www/firewall_nat_out_edit.php +++ b/src/www/firewall_nat_out_edit.php @@ -40,6 +40,7 @@ function formTranslateAddresses() { // add this hosts ips foreach (legacy_config_get_interfaces(array('virtual' => false, "enable" => true)) as $intf => $intfdata) { + $retval[$intf] = (!empty($intfdata['descr']) ? $intfdata['descr'] : $intf ) . " " . gettext("net"); $retval[$intf."ip"] = (!empty($intfdata['descr']) ? $intfdata['descr'] : $intf ) . " " . gettext("address"); }