mirror of
https://github.com/opnsense/core.git
synced 2026-10-12 02:20:36 +00:00
Firewall: Migrate Multi-WAN advanced settings to new settings page
This commit is contained in:
@@ -801,6 +801,7 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_1_0.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_1_1.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_1_2.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Migrations/MFP1_1_3.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/static_aliases/core.json
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Hostdiscovery/ACL/ACL.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Hostdiscovery/Hostwatch.php
|
||||
|
||||
@@ -184,6 +184,7 @@ function filter_configure_sync($verbose = false, $load_aliases = true)
|
||||
|
||||
/* initialize fw plugin object */
|
||||
$fw = filter_core_get_initialized_plugin_system();
|
||||
$settings = config_read_array('OPNsense', 'Firewall', 'Filter', 'settings', false);
|
||||
filter_core_bootstrap($fw);
|
||||
$cnfint = iterator_to_array($fw->getInterfaceMapping());
|
||||
plugins_firewall($fw);
|
||||
@@ -342,8 +343,8 @@ function filter_configure_sync($verbose = false, $load_aliases = true)
|
||||
$limitrules .= "set limit frags {$config['system']['maximumfrags']}\n";
|
||||
}
|
||||
|
||||
if (isset($config['system']['lb_use_sticky']) && is_numeric($config['system']['srctrack'] ?? null) && ($config['system']['srctrack'] > 0)) {
|
||||
$limitrules .= "set timeout src.track {$config['system']['srctrack']}\n";
|
||||
if (!empty($settings['filter']['lb_use_sticky']) && !empty($settings['filter']['source_tracking_timeout'])) {
|
||||
$limitrules .= "set timeout src.track " . $settings['filter']['source_tracking_timeout'] . "\n";
|
||||
}
|
||||
|
||||
if (!empty($config['system']['syncookies'])) {
|
||||
|
||||
@@ -201,6 +201,7 @@ function filter_core_rules_system($fw, $defaults)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$settings = config_read_array('OPNsense', 'Firewall', 'Filter', 'settings', false);
|
||||
$ipv6_disabled = !is_ipv6_allowed();
|
||||
|
||||
$dhcrelay6_interfaces = plugins_run('dhcrelay_interfaces', ['inet6']);
|
||||
@@ -598,7 +599,7 @@ function filter_core_rules_system($fw, $defaults)
|
||||
// [out from this Firewall, using the selected gateway].
|
||||
// Our default setting has been to force traffic leaving a specific interface to use the associated gateway.
|
||||
// This behaviour can be disabled, so settings can be customized using manual firewall rules.
|
||||
if (empty($config['system']['pf_disable_force_gw'])) {
|
||||
if (empty($settings['filter']['pf_disable_force_gw'])) {
|
||||
foreach ($fw->getInterfaceMapping() as $ifdescr => $ifcfg) {
|
||||
if (!isset($ifcfg['internal_dynamic']) && $ifcfg['if'] != 'lo0') {
|
||||
$protos_found = [];
|
||||
@@ -622,7 +623,7 @@ function filter_core_rules_system($fw, $defaults)
|
||||
'statetype' => 'keep',
|
||||
'allowopts' => true,
|
||||
'quick' => false,
|
||||
'#ref' => 'system_advanced_firewall.php#pf_disable_force_gw',
|
||||
'#ref' => 'ui/firewall/settings#settings-filter',
|
||||
'descr' => "let out anything from firewall host itself (force gw)"],
|
||||
$defaults['pass']
|
||||
);
|
||||
|
||||
@@ -237,12 +237,13 @@ function ipsec_firewall(\OPNsense\Firewall\Plugin $fw)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$settings = config_read_array('OPNsense', 'Firewall', 'Filter', 'settings', false);
|
||||
if (
|
||||
(string)(new \OPNsense\IPsec\IPsec())->general->disablevpnrules == '0' &&
|
||||
isset($config['ipsec']['enable']) && ipsec_legacy()
|
||||
) {
|
||||
$enable_replyto = empty($config['system']['disablereplyto']);
|
||||
$enable_routeto = empty($config['system']['pf_disable_force_gw']);
|
||||
$enable_routeto = empty($settings['filter']['pf_disable_force_gw']);
|
||||
foreach ($config['ipsec']['phase1'] as $ph1ent) {
|
||||
if (!isset($ph1ent['disabled'])) {
|
||||
// detect remote ip
|
||||
|
||||
@@ -67,6 +67,8 @@ function system_sysctl_defaults()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$settings = config_read_array('OPNsense', 'Firewall', 'Filter', 'settings', false);
|
||||
|
||||
/* notes:
|
||||
* - always set 'default' so the backend can use it and the user can see it
|
||||
* - since this is a function the settings could be derived from configuration
|
||||
@@ -126,8 +128,8 @@ function system_sysctl_defaults()
|
||||
'net.link.tap.user_open' => [ 'default' => '1' ],
|
||||
'net.link.vlan.mtag_pcp' => [ 'default' => '1' ],
|
||||
'net.local.dgram.maxdgram' => [ 'default' => '8192' ],
|
||||
'net.pf.share_forward' => [ 'default' => !empty($config['system']['pf_share_forward']) ? '1' : '0' ],
|
||||
'net.pf.share_forward6' => [ 'default' => !empty($config['system']['pf_share_forward']) ? '1' : '0' ],
|
||||
'net.pf.share_forward' => [ 'default' => !empty($settings['filter']['pf_share_forward']) ? '1' : '0' ],
|
||||
'net.pf.share_forward6' => [ 'default' => !empty($settings['filter']['pf_share_forward']) ? '1' : '0' ],
|
||||
'net.route.multipath' => [ 'default' => '0' ],
|
||||
'security.bsd.see_other_gids' => [ 'default' => '0' ],
|
||||
'security.bsd.see_other_uids' => [ 'default' => '0' ],
|
||||
|
||||
@@ -46,6 +46,7 @@ class SettingsController extends ApiMutableModelControllerBase
|
||||
if ($this->request->isPost()) {
|
||||
$backend = new Backend();
|
||||
$backend->configdRun('cron restart');
|
||||
$backend->configdRun('service restart sysctl');
|
||||
return ['status' => $backend->configdRun('filter reload skip_alias')];
|
||||
}
|
||||
return ['status' => 'failed'];
|
||||
|
||||
@@ -34,6 +34,34 @@
|
||||
<type>checkbox</type>
|
||||
<help>By default, when a rule has a specific gateway set and this gateway is down, the rule is created and traffic is sent to the default gateway. This option overrides that behavior and the rule is not created when the gateway is down.</help>
|
||||
</field>
|
||||
<field>
|
||||
<type>header</type>
|
||||
<label>Multi-WAN</label>
|
||||
</field>
|
||||
<field>
|
||||
<id>filter.settings.filter.lb_use_sticky</id>
|
||||
<label>Sticky connections</label>
|
||||
<type>checkbox</type>
|
||||
<help>Successive connections are redirected in round-robin fashion while connections from the same source are sent to the same gateway for as long as matching states exist.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>filter.settings.filter.source_tracking_timeout</id>
|
||||
<label>Source tracking timeout</label>
|
||||
<type>text</type>
|
||||
<help>Set the source tracking timeout for sticky connections in seconds. The default of zero removes source tracking as soon as the state expires.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>filter.settings.filter.pf_share_forward</id>
|
||||
<label>Shared forwarding</label>
|
||||
<type>checkbox</type>
|
||||
<help>Share forwarding decisions between the packet filter, traffic shaper, and captive portal to support policy routing in complex setups.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>filter.settings.filter.pf_disable_force_gw</id>
|
||||
<label>Disable force gateway</label>
|
||||
<type>checkbox</type>
|
||||
<help>Disable automatic rules which force local services to use the assigned interface gateway. The system routing table is used instead.</help>
|
||||
</field>
|
||||
</tab>
|
||||
<tab id="settings-nat" description="NAT">
|
||||
<field>
|
||||
|
||||
@@ -133,6 +133,7 @@ class Plugin
|
||||
*/
|
||||
public function setGatewayGroups($groups)
|
||||
{
|
||||
$settings = config_read_array('OPNsense', 'Firewall', 'Filter', 'settings', false);
|
||||
if (is_array($groups)) {
|
||||
foreach ($groups as $key => $gwgr) {
|
||||
$routeto = [];
|
||||
@@ -162,7 +163,7 @@ class Plugin
|
||||
$routetologic .= " {$gwgr[0]['poolopts']} ";
|
||||
} elseif (count($routeto) > 1) {
|
||||
$routetologic .= " round-robin ";
|
||||
if (!empty(Config::getInstance()->object()->system->lb_use_sticky)) {
|
||||
if (!empty($settings['filter']['lb_use_sticky'])) {
|
||||
$routetologic .= " sticky-address ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ use OPNsense\Base\BaseModel;
|
||||
use OPNsense\Base\Messages\Message;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Dnsmasq\Dnsmasq;
|
||||
use OPNsense\Firewall\Filter;
|
||||
use OPNsense\Firewall\Util;
|
||||
use OPNsense\Routing\Gateways;
|
||||
|
||||
@@ -133,10 +134,8 @@ class InitialSetup extends BaseModel
|
||||
$this->interfaces->lan->configure_dhcp = '0';
|
||||
$this->interfaces->lan->disable = '1';
|
||||
}
|
||||
if (
|
||||
$this->getConfigItem('system.pf_disable_force_gw', true) ||
|
||||
$this->getConfigItem('system.disablereplyto', true)
|
||||
) {
|
||||
$settings = (new Filter())->settings;
|
||||
if (!$settings->filter->pf_disable_force_gw->isEmpty() || $this->getConfigItem('system.disablereplyto', true)) {
|
||||
$this->deployment_type->multiwan = '0';
|
||||
} else {
|
||||
$this->deployment_type->multiwan = '1';
|
||||
@@ -425,13 +424,16 @@ class InitialSetup extends BaseModel
|
||||
private function flush_deployment_type()
|
||||
{
|
||||
$target = Config::getInstance()->object();
|
||||
$model = new Filter();
|
||||
$settings = $model->settings;
|
||||
if ($this->deployment_type->multiwan->isEmpty()) {
|
||||
$target->system->pf_disable_force_gw = '1';
|
||||
$settings->filter->pf_disable_force_gw = '1';
|
||||
$target->system->disablereplyto = '1';
|
||||
} else {
|
||||
unset($target->system->pf_disable_force_gw);
|
||||
$settings->filter->pf_disable_force_gw = '0';
|
||||
unset($target->system->disablereplyto);
|
||||
}
|
||||
$model->serializeToConfig(false, true);
|
||||
|
||||
if (!$this->deployment_type->dhcp_dns_registration->isEmpty()) {
|
||||
/* only configure when set (do not touch otherwise) */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<model>
|
||||
<mount>//OPNsense/Firewall/Filter</mount>
|
||||
<version>1.1.2</version>
|
||||
<version>1.1.3</version>
|
||||
<migration_prefix>MFP</migration_prefix>
|
||||
<description>Firewall rules (new)</description>
|
||||
<items>
|
||||
@@ -22,6 +22,22 @@
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</skip_rules_gw_down>
|
||||
<lb_use_sticky type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</lb_use_sticky>
|
||||
<source_tracking_timeout type="IntegerField">
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<ValidationMessage>Source tracking timeout must be a non-negative integer.</ValidationMessage>
|
||||
</source_tracking_timeout>
|
||||
<pf_share_forward type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</pf_share_forward>
|
||||
<pf_disable_force_gw type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</pf_disable_force_gw>
|
||||
</filter>
|
||||
<nat>
|
||||
<reflection_dnat type="BooleanField">
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2026 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Firewall\Migrations;
|
||||
|
||||
use OPNsense\Base\BaseModelMigration;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Firewall\Filter;
|
||||
|
||||
class MFP1_1_3 extends BaseModelMigration
|
||||
{
|
||||
public function run($model)
|
||||
{
|
||||
if ($model instanceof Filter) {
|
||||
$config = Config::getInstance()->object();
|
||||
$legacy_system = $config->system;
|
||||
$model->settings->filter->setNodes([
|
||||
'lb_use_sticky' => !empty($legacy_system->lb_use_sticky) ? '1' : '0',
|
||||
'source_tracking_timeout' => (string)$legacy_system->srctrack,
|
||||
'pf_share_forward' => !empty($legacy_system->pf_share_forward) ? '1' : '0',
|
||||
'pf_disable_force_gw' => !empty($legacy_system->pf_disable_force_gw) ? '1' : '0',
|
||||
]);
|
||||
}
|
||||
|
||||
parent::run($model);
|
||||
}
|
||||
|
||||
public function post($model)
|
||||
{
|
||||
if ($model instanceof Filter) {
|
||||
$config = Config::getInstance()->object();
|
||||
$legacy_system = $config->system;
|
||||
unset(
|
||||
$legacy_system->lb_use_sticky,
|
||||
$legacy_system->srctrack,
|
||||
$legacy_system->pf_share_forward,
|
||||
$legacy_system->pf_disable_force_gw,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,10 +48,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
$pconfig['maximumtableentries'] = !empty($config['system']['maximumtableentries']) ? $config['system']['maximumtableentries'] : null ;
|
||||
$pconfig['disablereplyto'] = isset($config['system']['disablereplyto']);
|
||||
$pconfig['schedule_states'] = isset($config['system']['schedule_states']);
|
||||
$pconfig['lb_use_sticky'] = isset($config['system']['lb_use_sticky']);
|
||||
$pconfig['pf_share_forward'] = isset($config['system']['pf_share_forward']);
|
||||
$pconfig['pf_disable_force_gw'] = isset($config['system']['pf_disable_force_gw']);
|
||||
$pconfig['srctrack'] = !empty($config['system']['srctrack']) ? $config['system']['srctrack'] : null;
|
||||
$pconfig['bypassstaticroutes'] = isset($config['filter']['bypassstaticroutes']);
|
||||
$pconfig['syncookies'] = isset($config['system']['syncookies']) ? $config['system']['syncookies'] : null;
|
||||
$pconfig['syncookies_adaptstart'] = isset($config['system']['syncookies_adaptstart']) ? $config['system']['syncookies_adaptstart'] : null;
|
||||
@@ -120,24 +116,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
}
|
||||
}
|
||||
if (count($input_errors) == 0) {
|
||||
if (!empty($pconfig['pf_share_forward'])) {
|
||||
$config['system']['pf_share_forward'] = true;
|
||||
} elseif (isset($config['system']['pf_share_forward'])) {
|
||||
unset($config['system']['pf_share_forward']);
|
||||
}
|
||||
|
||||
if (!empty($pconfig['pf_disable_force_gw'])) {
|
||||
$config['system']['pf_disable_force_gw'] = true;
|
||||
} elseif (isset($config['system']['pf_disable_force_gw'])) {
|
||||
unset($config['system']['pf_disable_force_gw']);
|
||||
}
|
||||
|
||||
if (!empty($pconfig['lb_use_sticky'])) {
|
||||
$config['system']['lb_use_sticky'] = true;
|
||||
} elseif (isset($config['system']['lb_use_sticky'])) {
|
||||
unset($config['system']['lb_use_sticky']);
|
||||
}
|
||||
|
||||
if (!empty($pconfig['noantilockout'])) {
|
||||
$config['system']['webgui']['noantilockout'] = true;
|
||||
} elseif (isset($config['system']['webgui']['noantilockout'])) {
|
||||
@@ -168,12 +146,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
unset($config['system']['no_virusprot']);
|
||||
}
|
||||
|
||||
if (!empty($pconfig['srctrack'])) {
|
||||
$config['system']['srctrack'] = $pconfig['srctrack'];
|
||||
} elseif (isset($config['system']['srctrack'])) {
|
||||
unset($config['system']['srctrack']);
|
||||
}
|
||||
|
||||
if (!empty($pconfig['disablefilter'])) {
|
||||
$config['system']['disablefilter'] = "enabled";
|
||||
} elseif (isset($config['system']['disablefilter'])) {
|
||||
@@ -295,66 +267,6 @@ include("head.inc");
|
||||
?>
|
||||
<section class="col-xs-12">
|
||||
<form method="post" name="iform" id="iform">
|
||||
<div class="content-box tab-content table-responsive __mb">
|
||||
<table class="table table-striped opnsense_standard_table_form">
|
||||
<tr>
|
||||
<td style="width:22%"><strong><?= gettext('Multi-WAN') ?></strong></td>
|
||||
<td style="width:78%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_lb_use_sticky" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Sticky connections");?> </td>
|
||||
<td>
|
||||
<input name="lb_use_sticky" type="checkbox" id="lb_use_sticky" value="yes" <?= !empty($pconfig['lb_use_sticky']) ? 'checked="checked"' : '';?>/>
|
||||
<?=gettext("Use sticky connections"); ?>
|
||||
<div class="hidden" data-for="help_for_lb_use_sticky">
|
||||
<?=gettext("Successive connections will be redirected to the servers " .
|
||||
"in a round-robin manner with connections from the same " .
|
||||
"source being sent to the same gateway. This 'sticky " .
|
||||
"connection' will exist as long as there are states that " .
|
||||
"refer to this connection. Once the states expire, so will " .
|
||||
"the sticky connection. Further connections from that host " .
|
||||
"will be redirected to the next gateway in the round-robin."); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input placeholder="<?=gettext("Source tracking timeout");?>" title="<?=gettext("Source tracking timeout");?>" name="srctrack" id="srctrack" type="text" value="<?= !empty($pconfig['srctrack']) ? $pconfig['srctrack'] : "";?>"/>
|
||||
<div class="hidden" data-for="help_for_lb_use_sticky">
|
||||
<?=gettext("Set the source tracking timeout for sticky connections in seconds. " .
|
||||
"By default this is 0, so source tracking is removed as soon as the state expires. " .
|
||||
"Setting this timeout higher will cause the source/destination relationship to persist for longer periods of time."); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_pf_share_forward" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext('Shared forwarding');?> </td>
|
||||
<td>
|
||||
<input name="pf_share_forward" type="checkbox" id="pf_share_forward" value="yes" <?= !empty($pconfig['pf_share_forward']) ? 'checked="checked"' : '' ?>/>
|
||||
<?=gettext('Use shared forwarding between packet filter, traffic shaper and captive portal'); ?>
|
||||
<div class="hidden" data-for="help_for_pf_share_forward">
|
||||
<?= gettext('Using policy routing in the packet filter rules causes packets to skip ' .
|
||||
'processing for the traffic shaper and captive portal tasks. ' .
|
||||
'Using this option enables the sharing of such forwarding decisions ' .
|
||||
'between all components to accommodate complex setups.') ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_pf_disable_force_gw" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext('Disable force gateway');?> </td>
|
||||
<td>
|
||||
<input name="pf_disable_force_gw" type="checkbox" id="pf_disable_force_gw" value="yes" <?= !empty($pconfig['pf_disable_force_gw']) ? 'checked="checked"' : '' ?>/>
|
||||
<?=gettext('Disable automatic rules which force local services to use the assigned interface gateway.'); ?>
|
||||
<div class="hidden" data-for="help_pf_disable_force_gw">
|
||||
<?= gettext('Outgoing packets from this firewall on an interface which has a gateway ' .
|
||||
'will normally use the specified gateway for that interface. ' .
|
||||
'When this option is set the route will be selected by the system routing table instead.') ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="content-box tab-content table-responsive __mb">
|
||||
<table class="table table-striped opnsense_standard_table_form">
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user