net/frr: fix and complete automatic firewall rules (#5736)

* net/frr: fix and complete automatic firewall rules

Generate rules directly for every enabled routing protocol and remove the dependency on configured OSPF networks or interfaces.

* Tighten the OSPF rules a bit more

* Also guard creation of rules if frr is not enabled
This commit is contained in:
Monviech
2026-09-25 09:14:01 +02:00
committed by GitHub
parent 16e30e831c
commit d701990c65
+350 -143
View File
@@ -1,6 +1,7 @@
<?php
/*
* Copyright (C) 2026 Deciso B.V.
* Copyright (C) 2018 Franco Fichtner <[email protected]>
* Copyright (C) 2017 Fabian Franz
* All rights reserved.
@@ -30,14 +31,13 @@
function frr_enabled()
{
$model = new \OPNsense\Quagga\General();
return (string)$model->enabled == '1';
return !$model->enabled->isEmpty();
}
function frr_carp_enabled()
{
$model = new \OPNsense\Quagga\General();
return (string)$model->enabled == '1' &&
(string)$model->enablecarp == '1';
return !$model->enabled->isEmpty() && !$model->enablecarp->isEmpty();
}
function frr_configure()
@@ -59,153 +59,360 @@ function frr_configure_do($verbose = false)
function frr_firewall($fw)
{
global $config;
if (empty((string)(new \OPNsense\Quagga\General())->fwrules)) {
$model = new \OPNsense\Quagga\General();
if ($model->enabled->isEmpty() || $model->fwrules->isEmpty()) {
// automatic rules disabled
return;
}
$ospf = new \OPNsense\Quagga\OSPF();
if ((string)$ospf->enabled == '1') {
$ospf_default = [
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
];
foreach ($ospf->networks->network->iterateItems() as $network) {
if ((string)$network->enabled == '1') {
$fw->registerFilterRule(
1, /* priority */
[
'descr' => 'Pass OSPF (autogenerated)',
'from' => $network->ipaddr . '/' . $network->netmask,
'to' => '224.0.0.0/24',
'direction' => 'in'
],
$ospf_default
);
$fw->registerFilterRule(
1,
[
'descr' => 'Pass OSPF UNICAST (autogenerated)',
'from' => $network->ipaddr . '/' . $network->netmask,
'to' => '(self)',
'direction' => 'in'
],
$ospf_default
);
$fw->registerFilterRule(
1,
[
'descr' => 'Pass OSPF (autogenerated)',
'from' => '(self)',
'to' => '224.0.0.0/24',
'direction' => 'out'
],
$ospf_default
);
$fw->registerFilterRule(
1,
[
'descr' => 'Pass OSPF UNICAST (autogenerated)',
'from' => '(self)',
'to' => $network->ipaddr . '/' . $network->netmask,
'direction' => 'out',
],
$ospf_default
);
}
}
if (!(new \OPNsense\Quagga\OSPF())->enabled->isEmpty()) {
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF MULTICAST',
'to' => '224.0.0.5/32',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF MULTICAST DR',
'to' => '224.0.0.6/32',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF UNICAST',
'to' => '(self)',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF MULTICAST',
'from' => '(self)',
'to' => '224.0.0.5/32',
'direction' => 'out',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF MULTICAST DR',
'from' => '(self)',
'to' => '224.0.0.6/32',
'direction' => 'out',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF UNICAST',
'from' => '(self)',
'direction' => 'out',
]
);
}
$ospf6 = new \OPNsense\Quagga\OSPF6();
if (!(new \OPNsense\Quagga\OSPF6())->enabled->isEmpty()) {
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 MULTICAST',
'from' => 'fe80::0/10',
'to' => 'ff02::5/128',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 MULTICAST DR',
'from' => 'fe80::0/10',
'to' => 'ff02::6/128',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 UNICAST',
'from' => 'fe80::0/10',
'to' => '(self)',
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 MULTICAST',
'from' => '(self)',
'to' => 'ff02::5/128',
'direction' => 'out',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 MULTICAST DR',
'from' => '(self)',
'to' => 'ff02::6/128',
'direction' => 'out',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass OSPF6 UNICAST',
'from' => '(self)',
'to' => 'fe80::0/10',
'direction' => 'out',
]
);
}
if ((string)$ospf6->enabled == '1') {
$ospf6_default = [
'ipprotocol' => 'inet6',
'protocol' => 'ospf',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
];
if (!(new \OPNsense\Quagga\BGP())->enabled->isEmpty()) {
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'tcp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BGP',
'to' => '(self)',
'to_port' => 179,
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'tcp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BGP',
'from' => '(self)',
'to_port' => 179,
'direction' => 'out',
]
);
}
foreach ($ospf6->interfaces->interface->iterateItems() as $interface) {
if ((string)$interface->enabled == '1') {
$fw->registerFilterRule(
1, /* priority */
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 MULTICAST (autogenerated)',
'from' => 'fe80::0/10',
'to' => 'ff02::5/128',
'direction' => 'in'
],
$ospf6_default
);
$fw->registerFilterRule(
1, /* priority */
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 MULTICAST DR (autogenerated)',
'from' => 'fe80::0/10',
'to' => 'ff02::6/128',
'direction' => 'in'
],
$ospf6_default
);
$fw->registerFilterRule(
1,
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 UNICAST (autogenerated)',
'from' => 'fe80::0/10',
'to' => '(self)',
'direction' => 'in'
],
$ospf6_default
);
$fw->registerFilterRule(
1,
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 MULTICAST (autogenerated)',
'from' => '(self)',
'to' => 'ff02::5/128',
'direction' => 'out'
],
$ospf6_default
);
$fw->registerFilterRule(
1,
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 MULTICAST DR (autogenerated)',
'from' => '(self)',
'to' => 'ff02::6/128',
'direction' => 'out'
],
$ospf6_default
);
$fw->registerFilterRule(
1,
[
'interface' => (string)$interface->interfacename,
'descr' => 'Pass OSPF6 UNICAST (autogenerated)',
'from' => '(self)',
'to' => 'fe80::0/10',
'direction' => 'out'
],
$ospf6_default
);
}
}
if (!(new \OPNsense\Quagga\BFD())->enabled->isEmpty()) {
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BFD',
'to' => '(self)',
'to_port' => 3784,
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BFD',
'from' => '(self)',
'to_port' => 3784,
'direction' => 'out',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BFD MULTIHOP',
'to' => '(self)',
'to_port' => 4784,
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet46',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass BFD MULTIHOP',
'from' => '(self)',
'to_port' => 4784,
'direction' => 'out',
]
);
}
if (!(new \OPNsense\Quagga\RIP())->enabled->isEmpty()) {
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass RIP',
'to' => '(self),224.0.0.9,255.255.255.255',
'to_port' => 520,
'direction' => 'in',
]
);
$fw->registerFilterRule(
1,
[
'ipprotocol' => 'inet',
'protocol' => 'udp',
'statetype' => 'keep',
'type' => 'pass',
'disablereplyto' => 1,
'quick' => true,
'log' => !isset($config['syslog']['nologdefaultpass']),
'#ref' => 'ui/quagga/general/index',
'descr' => 'Pass RIP',
'from' => '(self)',
'to_port' => 520,
'direction' => 'out',
]
);
}
}