Firewall - refactor getInterfaceGateway() to support extracting a dynamic property instead of the fixed address, refactor route-to behaviour to match reply-to and outbound nat. remove getInterfaceGateways() from firewall plugin as being unused now. closes https://github.com/opnsense/core/issues/5230

This commit is contained in:
Ad Schellevis 2021-09-22 15:37:55 +02:00
parent 60eba47090
commit 500c82f181
4 changed files with 25 additions and 59 deletions

View File

@ -594,33 +594,29 @@ function filter_core_rules_system($fw, $defaults)
if (empty($config['system']['pf_disable_force_gw'])) {
foreach ($fw->getInterfaceMapping() as $ifdescr => $ifcfg) {
if (!isset($ifcfg['internal_dynamic']) && $ifcfg['if'] != 'lo0') {
$intf_has_v4 = false;
$intf_has_v6 = false;
$protos_found = [];
$address_check = ['inet' => 'is_subnetv4', 'inet6' => 'is_subnetv6'];
foreach (array_keys(interfaces_addresses($ifcfg['if'], true, $fw->getIfconfigDetails())) as $addr) {
$intf_has_v4 = $intf_has_v4 || is_subnetv4($addr);
$intf_has_v6 = $intf_has_v6 || is_subnetv6($addr);
}
foreach ($fw->getInterfaceGateways($ifcfg['if']) as $gwname) {
$gwcfg = $fw->getGateway($gwname);
if (empty($gwcfg['gateway'])) {
// XXX: only force traffic on explict gateway [address] selection,
// exclude gateway_interface types.
continue;
}
// only try to add gateway rules for traffic leaving this interface
// when the correct protocol is assigned to the interface
if (($gwcfg['proto'] == 'inet' && $intf_has_v4) || ($gwcfg['proto'] == 'inet6' && $intf_has_v6)) {
$fw->registerFilterRule(
100000,
array('from' => "({$ifcfg['if']})", 'direction' => 'out', 'gateway' => $gwname,
'destination' => array('network' => $ifdescr, "not" => true),
'statetype' => 'keep',
'allowopts' => true,
'quick' => false,
'#ref' => 'system_advanced_firewall.php#pf_disable_force_gw',
'descr' => "let out anything from firewall host itself (force gw)"),
$defaults['pass']
);
foreach (['inet', 'inet6'] as $inet) {
if (!in_array($inet, $protos_found) && $address_check[$inet]($addr)) {
$gwname = $fw->getGateways()->getInterfaceGateway($ifdescr, $inet, true, 'name');
if (!empty($gwname)) {
// only try to add gateway rules for traffic leaving this interface
// when the correct protocol is assigned to the interface
$fw->registerFilterRule(
100000,
array('from' => "({$ifcfg['if']})", 'direction' => 'out', 'gateway' => $gwname,
'destination' => array('network' => $ifdescr, "not" => true),
'statetype' => 'keep',
'allowopts' => true,
'quick' => false,
'#ref' => 'system_advanced_firewall.php#pf_disable_force_gw',
'descr' => "let out anything from firewall host itself (force gw)"),
$defaults['pass']
);
}
$protos_found[] = $inet;
}
}
}
}

View File

@ -268,18 +268,7 @@ function ipsec_firewall(\OPNsense\Firewall\Plugin $fw)
);
// find gateway
$gwname = null;
foreach ($fw->getInterfaceMapping() as $intfnm => $intf) {
if ($intfnm == $interface) {
foreach ($fw->getInterfaceGateways($intf['if']) as $gwnm) {
$gw = $fw->getGateway($gwnm);
if ($gw['proto'] == $ph1ent['protocol']) {
$gwname = $gwnm;
break;
}
}
}
}
$gwname = $fw->getGateways()->getInterfaceGateway($interface, $ph1ent['protocol'], true, 'name');
// register rules
$fw->registerFilterRule(
500000,

View File

@ -160,25 +160,6 @@ class Plugin
}
}
/**
* fetch gateway (names) for provided interface, would return both ipv4/ipv6
* @param string $intf interface (e.g. em0, igb0,...)
*/
public function getInterfaceGateways($intf)
{
$result = array();
$protos_found = array();
foreach ($this->gatewayMapping as $key => $gw) {
if ($gw['type'] == 'gateway' && $gw['interface'] == $intf) {
if (!in_array($gw['proto'], $protos_found)) {
$result[] = $key;
$protos_found[] = $gw['proto'];
}
}
}
return $result;
}
/**
* Fetch gateway
* @param string $gw gateway name

View File

@ -403,7 +403,7 @@ class Gateways
* @param boolean $only_configured only return configured in interface or dynamic gateways
* @return string|null gateway address
*/
public function getInterfaceGateway($interface, $ipproto = "inet", $only_configured = false)
public function getInterfaceGateway($interface, $ipproto = "inet", $only_configured = false, $property='gateway')
{
foreach ($this->getGateways() as $gateway) {
if (!empty($gateway['disabled']) || $gateway['ipprotocol'] != $ipproto) {
@ -424,7 +424,7 @@ class Gateways
// are not returned as valid gateway address (automatic outbound nat rules).
// An alternative setup option would be practical here, less fuzzy.
if (!$only_configured || $intf_gateway == $gateway['name'] || !empty($gateway['dynamic'])) {
return $gateway['gateway'];
return isset($gateway[$property]) ? $gateway[$property] : null ;
}
}
}