diff --git a/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php b/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php index 29ebcd1b5..d502031b7 100644 --- a/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php +++ b/src/opnsense/mvc/app/library/OPNsense/Firewall/SNatRule.php @@ -51,6 +51,7 @@ class SNatRule extends Rule 'target' => 'parsePlain, -> ', 'natport' => 'parsePlain, port ', 'poolopts' => 'parsePlain', + 'poolopts_sourcehashkey' => 'parsePlain', 'staticnatport' => 'parseBool, static-port ', 'descr' => 'parseComment' ); @@ -109,6 +110,10 @@ class SNatRule extends Rule $rule[$fieldname] = "$".$rule[$fieldname]; } } + if (empty($rule['poolopts']) || $rule['poolopts'] != "source-hash"){ + // Make sure this is empty unless source-hash + $rule['poolopts_sourcehashkey'] = ''; + } if (!empty($rule['staticnatport']) || !empty($rule['nonat'])) { $rule['natport'] = ''; } elseif (empty($rule['natport'])) { diff --git a/src/www/firewall_nat_out_edit.php b/src/www/firewall_nat_out_edit.php index c8c08fa62..bc2634804 100644 --- a/src/www/firewall_nat_out_edit.php +++ b/src/www/firewall_nat_out_edit.php @@ -99,7 +99,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (isset($configId)) { // load data from config foreach (array('protocol','sourceport','dstport','natport','target','targetip' - ,'targetip_subnet','poolopts','interface','descr','nonat','log' + ,'targetip_subnet','poolopts','poolopts_sourcehashkey','interface','descr','nonat','log' ,'disabled','staticnatport','nosync','ipprotocol','tag','tagged') as $fieldname) { if (isset($a_out[$configId][$fieldname])) { $pconfig[$fieldname] = $a_out[$configId][$fieldname]; @@ -123,7 +123,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { // initialize unused elements foreach (array('protocol','sourceport','dstport','natport','target','targetip', - 'targetip_subnet','poolopts','interface','descr','nonat','tag','tagged', + 'targetip_subnet','poolopts','poolopts_sourcehashkey','interface','descr','nonat','tag','tagged', 'disabled','staticnatport','nosync','source','source_subnet','ipprotocol') as $fieldname) { if (!isset($pconfig[$fieldname])) { $pconfig[$fieldname] = null; @@ -195,7 +195,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (!empty($pconfig['targetip']) && is_alias($pconfig['targetip']) && !empty($pconfig['poolopts']) && substr($pconfig['poolopts'], 0, 11) != 'round-robin') { $input_errors[] = gettext("Only Round Robin pool options may be chosen when selecting an alias."); } - + /* Verify Source Hash Key if provided */ + if (!empty($pconfig['poolopts']) && $pconfig['poolopts'] == 'source-hash' && !empty($pconfig['poolopts_sourcehashkey'])){ + if (substr($pconfig['poolopts_sourcehashkey'], 0, 2) != "0x" || !ctype_xdigit(substr($pconfig['poolopts_sourcehashkey'], 2, 32)) ){ + $input_errors[] = gettext("Source Hash Key must be 0x followed by 32 hexadecimal digits"); + } + } // validate ipv4/v6, addresses should use selected address family foreach (array('source', 'destination', 'targetip') as $fieldname) { if (is_ipaddrv6($pconfig[$fieldname]) && $pconfig['ipprotocol'] != 'inet6') { @@ -215,6 +220,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { $natent['tag'] = $pconfig['tag']; $natent['tagged'] = $pconfig['tagged']; $natent['poolopts'] = $pconfig['poolopts']; + $natent['poolopts_sourcehashkey'] = $pconfig['poolopts_sourcehashkey']; $natent['ipprotocol'] = $pconfig['ipprotocol']; if (isset($a_out[$id]['created']) && is_array($a_out[$id]['created']) ){ @@ -715,37 +721,50 @@ include("head.inc");
|
+
+
+ =gettext("Only Round Robin types work with Host Aliases. Any type can be used with a Subnet.");?>
+ + * =gettext("Round Robin: Loops through the translation addresses.");?> + * =gettext("Random: Selects an address from the translation address pool at random.");?> + * =gettext("Source Hash: Uses a hash of the source address to determine the translation address, ensuring that the redirection address is always the same for a given source. Optionally provide a Source Hash Key to make it persist when the ruleset is reloaded. Must be 0x followed by 32 hexadecimal digits.");?> + * =gettext("Bitmask: Applies the subnet mask and keeps the last portion identical; 10.0.1.50 -> x.x.x.50.");?> + * =gettext("Sticky Address: The Sticky Address option can be used with the Random and Round Robin pool types to ensure that a particular source address is always mapped to the same translation address.");?> + |
+
| + + | +