Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions plist
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_0_6.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_0_7.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_1_1.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_1_2.php
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/FieldTypes/CharonLogLevelField.php
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/FieldTypes/ConnnectionField.php
Expand Down Expand Up @@ -1144,6 +1145,7 @@
/usr/local/opnsense/scripts/filter/lib/alias/pf.py
/usr/local/opnsense/scripts/filter/lib/alias/uri.py
/usr/local/opnsense/scripts/filter/lib/states.py
/usr/local/opnsense/scripts/filter/list_divert_sockets.php
/usr/local/opnsense/scripts/filter/list_non_mvc_rules.php
/usr/local/opnsense/scripts/filter/list_osfp.py
/usr/local/opnsense/scripts/filter/list_pfsync.py
Expand Down
Empty file modified src/etc/suricata/conf.d/README
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,17 @@
<visible>false</visible>
</grid_view>
</field>
<!-- XXX: start as advanced, promote to non-advanced feature in a later version -->
<field>
<id>rule.divert-to</id>
<label>Divert-to</label>
<type>dropdown</type>
<advanced>true</advanced>
<grid_view>
<visible>false</visible>
</grid_view>
<help>Send packets matching this rule to the service specified, when the service is not running, packets will be dropped</help>
</field>
<field>
<type>header</type>
<label>Stateful firewall</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,32 @@
<help>Enable intrusion detection system.</help>
</field>
<field>
<id>ids.general.ips</id>
<label>IPS mode</label>
<type>checkbox</type>
<help><![CDATA[Enable protection mode (block traffic).<br />Before enabling, please disable all hardware offloading first <a href="/system_advanced_network.php">in advanced network</a>.]]></help>
<id>ids.general.mode</id>
<label>Capture mode</label>
<type>dropdown</type>
<help>Choose PCAP live capture mode for inspection only (IDS), Netmap to filter all traffic on the selected interfaces in IPS mode and Divert to integrate IPS in firewall rules.</help>
</field>
<field>
<id>ids.general.promisc</id>
<label>Promiscuous mode</label>
<type>checkbox</type>
<style>selectpicker ids_mode ids_mode_pcap ids_mode_netmap</style>
<help>Enable promiscuous mode, for certain setups (like IPS with vlans), this is required to actually capture data on the physical interface.</help>
</field>
<field>
<id>ids.general.interfaces</id>
<label>Interfaces</label>
<type>select_multiple</type>
<style>selectpicker ids_mode ids_mode_pcap ids_mode_netmap</style>
<help>Select interface(s) to use. When enabling IPS, make sure the (virtual) driver supports this feature.</help>
</field>
<field>
<id>ids.general.divert_listeners</id>
<label>Listeners</label>
<style>ids_mode ids_mode_divert</style>
<type>text</type>
<help>Specify the number of listeners to initiate, usually this equals the number of CPUs in your system.</help>
</field>
<field>
<type>header</type>
<label>Detection</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class FilterRule extends Rule
'tagged' => 'parsePlain, tagged ',
'allowopts' => 'parseBool,allow-opts',
'dn' => 'parsePlain',
'divert-to' => 'parsePlain,divert-to ',
'label' => 'parsePlain,label ",",63',
'descr' => 'parseComment'
);
Expand Down
6 changes: 6 additions & 0 deletions src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ public function performValidation($validateFullModel = false)
}
}
}
if (!$rule->{'divert-to'}->isEmpty() && $rule->action != 'pass') {
$messages->appendMessage(new Message(
gettext("Divert-to is only valid for pass rules."),
$rule->{'divert-to'}->__reference
));
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/opnsense/mvc/app/models/OPNsense/Firewall/Filter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@
<EnableAlias>Y</EnableAlias>
<ValidationMessage>Please specify a valid portnumber, name, alias or range.</ValidationMessage>
</destination_port>
<divert-to type="JsonKeyValueStoreField">
<ConfigdPopulateAct>filter list diverts</ConfigdPopulateAct>
<ValidationMessage>Specify a valid divert-to target.</ValidationMessage>
</divert-to>
<gateway type="JsonKeyValueStoreField">
<ConfigdPopulateAct>interface gateways list -g</ConfigdPopulateAct>
<ValidationMessage>Specify a valid gateway from the list matching the networks ip protocol.</ValidationMessage>
Expand Down
6 changes: 3 additions & 3 deletions src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/*
* Copyright (C) 2015 Deciso B.V.
* Copyright (C) 2015-2025 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -39,12 +39,12 @@ class IDS extends BaseModel
/**
* @var array internal list of all sid's in this object
*/
private $sid_list = array();
private $sid_list = [];

/**
* @var array internal list of all known actions (key/value)
*/
private $action_list = array();
private $action_list = [];

/**
* update internal cache of sid's and actions
Expand Down
20 changes: 16 additions & 4 deletions src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<model>
<mount>//OPNsense/IDS</mount>
<version>1.1.1</version>
<version>1.1.2</version>
<description>Intrusion detection</description>
<items>
<rules>
Expand Down Expand Up @@ -134,10 +134,22 @@
<Default>0</Default>
<Required>Y</Required>
</enabled>
<ips type="BooleanField">
<Default>0</Default>
<mode type="OptionField">
<Required>Y</Required>
</ips>
<Default>pcap</Default>
<OptionValues>
<pcap>pcap live mode (IDS)</pcap>
<netmap>Netmap (IPS)</netmap>
<divert>Divert (IPS)</divert>
</OptionValues>
<ValidationMessage>Please select a valid mode.</ValidationMessage>
</mode>
<divert_listeners type="IntegerField">
<Required>Y</Required>
<Default>1</Default>
<MinimumValue>1</MinimumValue>
<MaximumValue>256</MaximumValue>
</divert_listeners>
<promisc type="BooleanField">
<Default>0</Default>
<Required>Y</Required>
Expand Down
46 changes: 46 additions & 0 deletions src/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_1_2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
* Copyright (C) 2025 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\IDS\Migrations;

use OPNsense\Base\BaseModelMigration;
use OPNsense\Core\Config;
use OPNSense\IDS\IDS;

class M1_1_2 extends BaseModelMigration
{
public function run($model)
{
$cnf = Config::getInstance()->object();
if ($cnf?->OPNsense?->IDS?->general?->ips == '1') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no cast here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be safe, it's a config (simplexml) object.

$model->general->mode = 'netmap';
}

parent::run($model);
}
}
4 changes: 4 additions & 0 deletions src/opnsense/mvc/app/views/OPNsense/IDS/index.volt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@
$(".detect_custom").closest("tr").addClass("hidden");
}
});
$("#ids\\.general\\.mode").change(function(){
$(".ids_mode").closest("tr").hide();
$(".ids_mode_" + $(this).val()).closest("tr").show();
});
mapDataToFormUI({'frm_GeneralSettings':'/api/ids/settings/get'}).done(function(data){
// set schedule updates link to cron
$.each(data.frm_GeneralSettings.ids.general.UpdateCron, function(key, value) {
Expand Down
36 changes: 36 additions & 0 deletions src/opnsense/scripts/filter/list_divert_sockets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/local/bin/php
<?php
/*
* Copyright (C) 2025 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.
*/
require_once('script/load_phalcon.php');

/**
* currently IDPS (Suricata) is the only service offering divert sockets, as this might change in the future
* we reserve a simple command to list registered/active services which may be used as divert targets.
*/

echo json_encode(['8000' => gettext("Intrusion Detection")]);

7 changes: 7 additions & 0 deletions src/opnsense/service/conf/actions.d/actions_filter.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ type:script_output
description:Update and reload firewall aliases
message:refresh url table aliases

[list.diverts]
command:/usr/local/opnsense/scripts/filter/list_divert_sockets.php
parameters: %s
type:script_output
cache_ttl: 300
message:list divert options

[list.osfp]
command:/usr/local/opnsense/scripts/filter/list_osfp.py
parameters: %s
Expand Down
17 changes: 15 additions & 2 deletions src/opnsense/service/templates/OPNsense/IDS/rc.conf.d
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
suricata_flags="-D"
{% if not helpers.empty('OPNsense.IDS.general.enabled') %}
suricata_setup="/usr/local/opnsense/scripts/suricata/setup.sh"
suricata_enable="YES"
{% if not helpers.empty('OPNsense.IDS.general.verbosity') %}
suricata_flags="-D -{{OPNsense.IDS.general.verbosity}}"
suricata_flags="$suricata_flags -{{OPNsense.IDS.general.verbosity}}"
{% endif %}
{% if OPNsense.IDS.general.ips|default("0") == "1" %}
{% if OPNsense.IDS.general.mode|default("") == "netmap" %}
# IPS mode, switch to netmap
suricata_netmap="YES"

{% elif OPNsense.IDS.general.mode|default("") == "divert" %}
# IPS mode, divert sockets
suricata_divertport="8000"
{# add rest of listeners, above adds the first #}
{% set addFlags=[] %}
{% set listeners = OPNsense.IDS.general.divert_listeners|default('1')|int %}
{% for idx in range(1, listeners) %}
{% do addFlags.append('-d 8000') %}
{% endfor %}
suricata_flags="$suricata_flags {{ addFlags|join(' ') }}"

{% else %}
# IDS mode, pcap live mode
{% set addFlags=[] %}
Expand Down
4 changes: 2 additions & 2 deletions src/opnsense/service/templates/OPNsense/IDS/suricata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ flow-timeouts:
stream:
memcap: 64mb
checksum-validation: yes
inline: {% if OPNsense.IDS.general.ips|default("0") == "1" %}true{% else %}auto{% endif +%}
inline: {% if OPNsense.IDS.general.mode|default("") in ["netmap", "divert"] %}true{% else %}auto{% endif +%}

midstream-policy: ignore
reassembly:
Expand Down Expand Up @@ -405,7 +405,7 @@ netmap:
disable-promisc: {% if helpers.empty('OPNsense.IDS.general.promisc') %}yes{% else %}no{% endif +%}
checksum-checks: auto

{% if helpers.exists('OPNsense.IDS.general.interfaces') %}
{% if helpers.exists('OPNsense.IDS.general.interfaces') and OPNsense.IDS.general.mode|default("") == "netmap" %}
{% for intfName in OPNsense.IDS.general.interfaces.split(',') %}

- interface: {{helpers.physical_interface(intfName)}}
Expand Down