The built-in rule management on the OPNSense is not only quite fast, it allows for pattern based enable/disable of rules via Policies. Truly, it is a good system and quite efficient! While this speed and control is useful, if you want to modify rules and resolve FPs in sometimes very needful and useful ways you generally will be after suricata-update and its disable/enable/drop/modify pattern matched and/or specific SIDs after download updated rule features.
Currently, and I want to see if I can help ‘enable’ this feature as a natural option (especially when an update happens to suricata-update allowing it to operate much faster), you must:
- Create a script for ensuring conf files are maintained (only needed for now, once this reaches a higher maturity we should resolve use of the ‘custom.yaml’ Suricata config file)
- Create a script for running suricata-update with flags and restarting Suricata if necessary
- Disable the default IDS Rule Update Web GUI Cron entry
- Create a new configd file for new Web GUI Cron entries (Suricata State, Suricata Update)
- Maintain a small group of files (yaml/rules/conf) to attain a complete OPNSense + Suricata-Update expression
If you haven’t heard about “suricata-update”, but you might be familiar with “oinkmaster” or “pulled-pork” of what IDS gurus used to use with Snort, it of course works with Suricata and updates the rules ecosystem. It is also already installed in your OPNSense, so there’s really no new software/plug-in to install, you’ve already got the binaries/python bits.
This guide expects the user to be familiar with the OPNSense/FreeBSD/Linux to a point, and certainly able to get into the OPNSense Shell via SSH and to know how to create folders and files (you can get vim by pkg install vim
). The scripts you will be creating do some logging to log file in the /root/ folder but attempts have been made to minimize the outputs.
This blog post will get updated and eventually will have a Github git repo with a default file set, possibly some updates to help setup and re-align the OPNSense – as of yet, I’m merely sharing how to get started.
That said, let’s go!
Disable Cron for OPNSense Policy based updates
Un-check the “enabled” box for the “IDS Rule Updates”, hit Save, then hit Apply
Create new actions configd Cron list file
This file will be located at:/usr/local/opnsense/service/conf/actions.d/actions_homelab.conf
This does refer to two files we will be creating later. We need this file to list Cron entries on the OPNSense Web GUI.
actions_homelab.conf
[cfidsreload]
command: /root/suricatamod.sh; exit 0
parameters:
type:script
message:copy over and reload intrusion detection custom conf
description:Copy over and reload intrusion detection custom conf
[cfgidsupdate]
command: /root/suricataupdate.sh; exit 0
parameters:
type:script
message:download and update and mod suricata rules
description:Download and update and mod Suricata Rules
Update the configd service
To have the new Cron entries show up in the OPNSense Web GUI, you must restart the configd service, we will enable them later
service configd restart
Create custom file modification script
This file will be located at:/root/suricatamod.sh
This does some work to keep the “custom.yaml” file and a few other file that enable the natural state of Suricata to work as expected. In short, the custom.yaml file gets over-wrote in some restart/rule update py script from OPNSense – so this would revert the file if it gets overwrote (such as it would by an update).
suricatamod.sh
#!/bin/sh
# Get current date and time
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# Define file paths
# Suricata config custom
ROOT_CUSTOM1="/root/suricata/custom.yaml"
SURICATA_CUSTOM1="/usr/local/etc/suricata/custom.yaml"
# Installed Rules File
ROOT_CUSTOM2="/root/suricata/installed_rules.yaml"
SURICATA_CUSTOM2="/usr/local/etc/suricata/installed_rules.yaml"
# Rules File
ROOT_RULES1="/root/suricata/novalabs.rules"
SURICATA_RULES1="/usr/local/etc/suricata/novalabs.yaml"
SURICATARULES_RULES1="/usr/local/etc/suricata/opnsense.rules/novalabs.yaml"
# Classification File
ROOT_CLASSIFICATION="/root/suricata/classification.config"
SURICATA_CLASSIFICATION1="/usr/local/share/suricata/rules/classification.config"
SURICATA_CLASSIFICATION2="/usr/local/share/suricata/classification.config"
SURICATA_CLASSIFICATION3="/usr/local/etc/suricata/classification.config"
SURICATA_CLASSIFICATION4="/usr/local/etc/suricata/opnsense.rules/classification.config"
# Extra - cannot use this file currently
SURICATA_TEMPLATE="/usr/local/opnsense/service/templates/OPNsense/IDS/custom.yaml"
# Start Logging
echo "$TIMESTAMP: File mod - Checking for configuration updates..." > /root/suricatamod.log
# Check for OPNSense running updates
script_name="rule-updater.py"
# Check if the script is running using ps
ps aux | grep "$script_name" | grep -v grep > /dev/null
if [ $? -eq 0 ]; then
echo "$TIMESTAMP: File mod - Script '$script_name' is already running... exiting." >> /root/suricatamod.log
exit 0 # Exit with a 0
else
echo "$TIMESTAMP: File mod - Script '$script_name' is not running. Proceeding..." >> /root/suricatamod.log
fi
script_name="installRules.py"
# Check if the script is running using ps
ps aux | grep "$script_name" | grep -v grep > /dev/null
if [ $? -eq 0 ]; then
echo "$TIMESTAMP: File mod - Script '$script_name' is already running... exiting." >> /root/suricatamod.log
exit 0 # Exit with a 0
else
echo "$TIMESTAMP: File mod - Script '$script_name' is not running. Proceeding..." >> /root/suricatamod.log
fi
# Check our files and fix them if necessary
RESTART_NEEDED="NO"
# Check if files are identical
if cmp -s "$ROOT_CUSTOM1" "$SURICATA_CUSTOM1"; then
echo "$TIMESTAMP: File mod - $ROOT_CUSTOM1 / $SURICATA_CUSTOM1 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CUSTOM1 to $SURICATA_CUSTOM1" >> /root/suricatamod.log
cp "$ROOT_CUSTOM1" "$SURICATA_CUSTOM1"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_CUSTOM2" "$SURICATA_CUSTOM2"; then
echo "$TIMESTAMP: File mod - $ROOT_CUSTOM2 / $SURICATA_CUSTOM2 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CUSTOM2 to $SURICATA_CUSTOM2" >> /root/suricatamod.log
cp "$ROOT_CUSTOM2" "$SURICATA_CUSTOM2"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_RULES1" "$SURICATA_RULES1"; then
echo "$TIMESTAMP: File mod - $ROOT_RULES1 / $SURICATA_RULES1 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_RULES1 to $SURICATA_RULES1" >> /root/suricatamod.log
cp "$ROOT_RULES1" "$SURICATA_RULES1"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_RULES1" "$SURICATARULES_RULES1"; then
echo "$TIMESTAMP: File mod - $ROOT_RULES1 / $SURICATARULES_RULES1 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_RULES1 to $SURICATARULES_RULES1" >> /root/suricatamod.log
cp "$ROOT_RULES1" "$SURICATARULES_RULES1"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION1"; then
echo "$TIMESTAMP: File mod - $ROOT_CLASSIFICATION / $SURICATA_CLASSIFICATION1 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CLASSIFICATION to $SURICATA_CLASSIFICATION1" >> /root/suricatamod.log
cp "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION1"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION2"; then
echo "$TIMESTAMP: File mod - $ROOT_CLASSIFICATION / $SURICATA_CLASSIFICATION2 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CLASSIFICATION to $SURICATA_CLASSIFICATION2" >> /root/suricatamod.log
cp "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION2"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION3"; then
echo "$TIMESTAMP: File mod - $ROOT_CLASSIFICATION / $SURICATA_CLASSIFICATION3 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CLASSIFICATION to $SURICATA_CLASSIFICATION3" >> /root/suricatamod.log
cp "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION3"
RESTART_NEEDED="YES"
fi
# Check if files are identical
if cmp -s "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION4"; then
echo "$TIMESTAMP: File mod - $ROOT_CLASSIFICATION / $SURICATA_CLASSIFICATION4 Files are identical." >> /root/suricatamod.log
else
echo "$TIMESTAMP: File mod - Different, copying $ROOT_CLASSIFICATION to $SURICATA_CLASSIFICATION4" >> /root/suricatamod.log
cp "$ROOT_CLASSIFICATION" "$SURICATA_CLASSIFICATION4"
RESTART_NEEDED="YES"
fi
# Check if rule update in process
if [ -e /root/suricata/inRunSuricataUpdate ]; then
echo "$TIMESTAMP: File mod - Rule update in progress, not restarting... exiting." > /root/suricataxtramod.log
exit 0 # Exit with a 0
fi
# We are not updating rules, so let us restart Suricata
if [ "$RESTART_NEEDED" == "YES" ]; then
#service suricata restart
pkill -USR2 suricata
echo "$TIMESTAMP: File mod - Suricata service restarted." >> /root/suricatarestart.log
fi
exit 0
Be sure to “chmod +x /root/suricatamod.sh
“
Create suricata-update runner
This file will be located at:/root/suricataupdate.sh
This runs the “suricata-update” python script with flags set for our OPNSense environment, it does a few checks to make sure it should run and if to restart Suricata or not.
suricataupdate.sh
#!/bin/sh
# Get current date and time
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# Check if I am already running
if [ ! -e /root/suricata/inRunSuricataUpdate ]; then
touch /root/suricata/inRunSuricataUpdate
else
echo "$TIMESTAMP: Rule update - I am already running... exiting." > /root/suricataxtrarules.log
exit 0 # Exit with a 0
fi
# Define file paths
ROOT_CUSTOM1="/root/suricata/suricata.rules"
SURICATA_CUSTOM1="/usr/local/etc/suricata/opnsense.rules/suricata.rules"
echo "$TIMESTAMP: Rule update - Checking for rule updates..." > /root/suricatarules.log
script_name="rule-updater.py"
# Check if the script is running using ps
ps aux | grep "$script_name" | grep -v grep > /dev/null
if [ $? -eq 0 ]; then
echo "$TIMESTAMP: Rule update - Script '$script_name' is already running... exiting." >> /root/suricatarules.log
exit 0 # Exit with a 0
else
echo "$TIMESTAMP: Rule update - Script '$script_name' is not running. Proceeding..." >> /root/suricatarules.log
fi
script_name="installRules.py"
# Check if the script is running using ps
ps aux | grep "$script_name" | grep -v grep > /dev/null
if [ $? -eq 0 ]; then
echo "$TIMESTAMP: Rule update - Script '$script_name' is already running... exiting." >> /root/suricatarules.log
exit 0 # Exit with a 0
else
echo "$TIMESTAMP: Rule update - Script '$script_name' is not running. Proceeding..." >> /root/suricatarules.log
fi
# Backup existing rules
cp "$SURICATA_CUSTOM1" "$ROOT_CUSTOM1"
# Run suricata-update
suricata-update update --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata --threshold-in=/root/suricata/threshold.in --threshold-out=/usr/local/etc/suricata/threshold.config --output /usr/local/etc/suricata/opnsense.rules -v --no-test --no-reload 2>&1 | tee /root/suricataupdate.log
# Make some check files to track the classtype to classification definitions
grep -Eo 'classtype:([^\;]+)' /usr/local/etc/suricata/opnsense.rules/suricata.rules | sed 's/classtype: /classtype:/g' | sort | uniq | cut -d':' -f2 > /root/suricata/classtype.list
grep -Eo 'classification: ([^\,]+)' /root/suricata/classification.config | cut -d' ' -f2 | sort > /root/suricata/classification.list
echo "$TIMESTAMP: Rule update - ==New classtype needing classification==" >> /root/suricatarules.log
diff /root/suricata/classtype.list /root/suricata/classification.list | grep '<' >> /root/suricatarules.log
echo "$TIMESTAMP: Rule update - ========================================" >> /root/suricatarules.log
# Check for Suricata restart / reload condition
RESTART_NEEDED="NO"
# Check if files are identical
if cmp -s "$ROOT_CUSTOM1" "$SURICATA_CUSTOM1"; then
echo "$TIMESTAMP: Rule update - $ROOT_CUSTOM1 Files are identical." >> /root/suricatarules.log
else
echo "$TIMESTAMP: Rule update - Rules file is different, restarting Suricata" >> /root/suricatarules.log
RESTART_NEEDED="YES"
fi
if [ "$RESTART_NEEDED" == "YES" ]; then
#service suricata restart
pkill -USR2 suricata
echo "$TIMESTAMP: Rule update - Suricata service restarted." >> /root/suricatarestart.log
fi
# Removing run check
rm /root/suricata/inRunSuricataUpdate
exit 0
Be sure to “chmod +x /root/suricataupdate.sh
“
Create Suricata-Update Folder for Yaml/Conf Files
Let’s create the folder and run a command to create our default Suricata-Update conf files.
mkdir /root/suricata
cd /root/suricata
Create suricata-update update.yaml file
This file will be located at:/root/suricata/update.yaml
This configures suricata-update, and we specify our ‘snortrules’ grab here because I haven’t figured out how to get the suricata-upate for the “oinkcode” to work and this works.
update.yaml
# Configuration with disable filters.
disable-conf: /root/suricata/disable.conf
# Configuration with enable filters.
enable-conf: /root/suricata/enable.conf
# Configuration with drop filters.
drop-conf: /root/suricata/drop.conf
# Configuration with modify filters.
modify-conf: /root/suricata/modify.conf
# List of files to ignore. Overrided by the --ignore command line option.
ignore:
- "*deleted.rules"
# Override the user-agent string.
#user-agent: "Suricata-Update"
# Provide an alternate command to the default test command.
#test-command: ${SURICATA_PATH} -T -S ${OUTPUT_FILENAME} -l /tmp
# Provide a command to reload the Suricata rules.
#reload-command: sudo systemctl reload suricata
# Remote rule sources. Simply a list of URLs.
sources:
- "https://www.snort.org/rules/snortrules-snapshot-29111.tar.gz?oinkcode=aaaaaaaaaaaaaaaaaaredactedaaaaaaaaaaaaaa"
# A list of local rule sources. Each entry can be a rule file, a
# directory or a wild card specification.
local:
- "/root/suricata/homelab.rules"
Create your homelab.rules file to bypass / home rule
This will be located at:/root/suricata/homelab.rules
This is a great place to get your IDS to focus on the important by NOT focusing on the unimportant, a pass+bypass rule on host paths that you do not want inspected will lower CPU utilization and cost!
homelab.rules
pass ip $GAMING_HOSTS any -> any any (msg:"Gaming Hosts"; bypass; sid:1000001; rev:1;)
pass ip any any -> $GAMING_HOSTS any (msg:"Gaming Hosts"; bypass; sid:1100001; rev:1;)
Create your custom.yaml file to customize suricata further
This file will be located at:/root/suricata/custom.yaml
We have talked about this file before on this site, here we mention it because this is how you will get your “address-groups” to us in your rules. In our example scripts here, we have setup a “Gaming Hosts” group to be bypassed in our “homelab.rules
” and/or your could use “modify.conf
” and change the text of “$HOME_NET
” in rules to “[$HOME_NET, !$GAMING_HOSTS]
” and thus ignore those hosts. No more False Positives on from those hosts!
custom.yaml
%YAML 1.1
---
vars:
address-groups:
HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]"
EXTERNAL_NET: "!$HOME_NET"
HTTP_SERVERS: "$HOME_NET"
SMTP_SERVERS: "$HOME_NET"
SQL_SERVERS: "$HOME_NET"
DNS_SERVERS: "$HOME_NET"
TELNET_SERVERS: "$HOME_NET"
AIM_SERVERS: "$EXTERNAL_NET"
DC_SERVERS: "$HOME_NET"
DNP3_SERVER: "$HOME_NET"
DNP3_CLIENT: "$HOME_NET"
MODBUS_CLIENT: "$HOME_NET"
MODBUS_SERVER: "$HOME_NET"
ENIP_CLIENT: "$HOME_NET"
ENIP_SERVER: "$HOME_NET"
SIP_SERVERS: "$HOME_NET"
INTERNAL_DEVICELIST: "[10.30.16.41,10.30.16.42,10.30.16.43]"
GAMING_HOSTS: "[10.40.1.2,10.40.1.3]"
port-groups:
HTTP_PORTS: "[80,8080]"
SHELLCODE_PORTS: "!80"
ORACLE_PORTS: 1521
SSH_PORTS: 22
DNP3_PORTS: 20000
MODBUS_PORTS: 502
FILE_DATA_PORTS: "[$HTTP_PORTS,110,143]"
FTP_PORTS: 21
GENEVE_PORTS: 6081
VXLAN_PORTS: 4789
TEREDO_PORTS: 3544
SIP_PORTS: "[5060,5061]"
outputs:
- eve-log:
enabled: yes
filetype: regular #regular|syslog|unix_dgram|unix_stream|redis
filename: evexff.json
xff:
enabled: yes
mode: overwrite
deployment: reverse
header: X-Forwarded-For
types:
- alert:
payload: no
payload-buffer-size: 100kb
payload-printable: no
metadata: yes # enable inclusion of app layer metadata with alert. Default yes
tagged-packets: yes
- eve-log:
enabled: yes
filetype: regular #regular|syslog|unix_dgram|unix_stream|redis
filename: eve.json
pcap-file: false
community-id: true
community-id-seed: 0
xff:
enabled: yes
mode: extra-data
deployment: reverse
header: X-Forwarded-For
types:
- alert:
payload: no
payload-buffer-size: 100kb
payload-printable: yes
metadata:
app-layer: true
flow: true
rule:
metadata: true
raw: true
tagged-packets: yes
- alert:
payload: yes
payload-buffer-size: 100kb
payload-printable: yes
metadata: yes # enable inclusion of app layer metadata with alert. Default yes
metadata:
app-layer: true
rule:
metadata: true
raw: true
tagged-packets: yes
- frame:
enabled: no
- anomaly:
enabled: no
- eve-log:
enabled: yes
type: syslog
identity: "suricata"
facility: local5
level: Info
community-id: true
community-id-seed: 0
xff:
enabled: yes
mode: extra-data
deployment: reverse
header: X-Forwarded-For
types:
- alert:
payload: no
payload-buffer-size: 100kb
payload-printable: yes
metadata:
app-layer: true
flow: true
rule:
metadata: true
raw: true
tagged-packets: yes
- frame:
enabled: no
- anomaly:
enabled: no
types:
applayer: no
- unified2-alert:
enabled: no
- http-log:
enabled: no
filename: http.log
append: yes
- tls-log:
enabled: no # Log TLS connections.
filename: tls.log # File to store TLS logs.
append: yes
- tls-store:
enabled: no
- pcap-log:
enabled: no
filename: log.pcap
limit: 1000mb
max-files: 2000
compression: none
mode: normal # normal, multi or sguil.
use-stream-depth: no #If set to "yes" packets seen after reaching stream inspection depth are ignored. "no" logs all packets
honor-pass-rules: no # If set to "yes", flows in which a pass rule matched will stop being logged.
- alert-debug:
enabled: no
filename: alert-debug.log
append: yes
- alert-prelude:
enabled: no
profile: suricata
log-packet-content: no
log-packet-header: yes
- stats:
enabled: yes
filename: stats.log
append: yes # append to file (yes) or overwrite it (no)
totals: yes # stats for all threads merged together
threads: no # per thread stats
- file-store:
version: 2
enabled: no
xff:
enabled: no
mode: extra-data
deployment: reverse
header: X-Forwarded-For
- file-store:
enabled: no
- tcp-data:
enabled: no
type: file
filename: tcp-data.log
- http-body-data:
enabled: no
type: file
filename: http-data.log
- lua:
enabled: no
scripts:
app-layer:
protocols:
telnet:
enabled: yes
rfb:
enabled: yes
detection-ports:
dp: 5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, 5908, 5909
mqtt:
enabled: yes
krb5:
enabled: yes
bittorrent-dht:
enabled: yes
snmp:
enabled: yes
ike:
enabled: yes
tls:
enabled: yes
detection-ports:
dp: 443
ja3-fingerprints: auto
pgsql:
enabled: yes
stream-depth: 0
max-tx: 1024
dcerpc:
enabled: yes
ftp:
enabled: yes
rdp:
ssh:
enabled: yes
http2:
enabled: yes
smtp:
enabled: yes
raw-extraction: no
mime:
decode-mime: yes
decode-base64: yes
decode-quoted-printable: yes
header-value-depth: 2000
extract-urls: yes
body-md5: no
inspected-tracker:
content-limit: 100000
content-inspect-min-size: 32768
content-inspect-window: 4096
imap:
enabled: detection-only
smb:
enabled: yes
detection-ports:
dp: 139, 445
nfs:
enabled: yes
tftp:
enabled: yes
dns:
tcp:
enabled: yes
detection-ports:
dp: 53
udp:
enabled: yes
detection-ports:
dp: 53
http:
enabled: yes
libhtp:
default-config:
personality: IDS
request-body-limit: 100kb
response-body-limit: 100kb
request-body-minimal-inspect-size: 32kb
request-body-inspect-window: 4kb
response-body-minimal-inspect-size: 40kb
response-body-inspect-window: 16kb
response-body-decompress-layer-limit: 2
http-body-inline: auto
swf-decompression:
enabled: no
type: both
compress-depth: 100kb
decompress-depth: 100kb
double-decode-path: no
double-decode-query: no
server-config:
modbus:
enabled: yes
detection-ports:
dp: 502
stream-depth: 0
dnp3:
enabled: yes
detection-ports:
dp: 20000
enip:
enabled: yes
detection-ports:
dp: 44818
sp: 44818
ntp:
enabled: yes
quic:
enabled: yes
dhcp:
enabled: yes
sip:
enabled: yes
asn1-max-frames: 256
datasets:
defaults:
rules:
host-os-policy:
windows: []
bsd: []
bsd-right: []
old-linux: []
linux: []
old-solaris: []
solaris: []
hpux10: []
hpux11: []
irix: []
macos: []
vista: []
windows2k3: []
netmap:
- interface: default
threads: auto
copy-mode: ips
disable-promisc: no # promiscuous mode
checksum-checks: auto
bpf-filter: not (( host 10.30.1.6 or 10.30.1.3 ) or ( net 10.30.14.0/24 or 10.30.21.0/24 ))
- interface: vlan0.1.10
copy-iface: vlan0.1.10^
- interface: vlan0.1.10^
copy-iface: vlan0.1.10
- interface: vlan0.1.50
copy-iface: vlan0.1.50^
- interface: vlan0.1.50^
copy-iface: vlan0.1.50
- interface: igb0
copy-iface: igb0^
- interface: igb0^
copy-iface: igb0
- interface: ix1
copy-iface: ix1^
- interface: ix1^
copy-iface: ix1
default-rule-path: /usr/local/etc/suricata/opnsense.rules
rule-files:
- suricata.rules
classification-file: /usr/local/etc/suricata/classification.config
reference-config-file: /usr/local/etc/suricata/reference.config
threshold-file: /usr/local/etc/suricata/threshold.config
Create a new “installed_rules.yaml” and
This file will be located at:/root/suricata/installed_rules.yaml
This insures that our “suricata.rules” file is used as expected and our “homelab.rules” is referenced, this step might not be as necessary as it was initially for me, but I leave it here to ensure success.
installed_rules.yaml
%YAML 1.1
---
rule-files:
- suricata.rules
- builtin.rules
- homelab.rules
Copy “installed_rules.yaml
” to Suricata’s directory
cp /root/suricata/installed_rules.yaml /usr/local/etc/suricata/installed_rules.yaml
Create disable/enable/drop/modify default conf files
cd /root/suricata
suricata-update --dump-sample-configs
Enable Suricata Update Sources
Update your Suricata sources:
suricata-update update-sources --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata
List the available rule update sources:
suricata-update list-sources --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata
Enable a source, in this example “et/open”:
suricata-update enable-source et/open --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata
List all enabled sources:
suricata-update list-sources --enabled --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata
Create new Web GUI Cron Entries
Go to System > Settings > Cron and create the following entries:
In Edit job, check-mark “enabled”, set minutes to a high frequency (*/5
or */10
), the rest of time fields at “*
“, and select “Copy over and reload intrusion detection custom…” as the Command, enter your own Description, hit “Save”
In Edit job, check-mark “enabled”, set to multiple times a day (*/6
for 4 times a day) putting a minute in and “*
” for the rest of the time fields, and set Command to “Download and update and mod Suricata Rules”, enter your own Description, hit “Save”, then hit “Apply”
Create the classification.conf file
If you are using CrowdSec and watching your Suricata logs/evelogs, I suggest this file to update the priority/classification of your rules, this is a bit more open but can be locked down by setting 2->1, and 3->2 and so on.
This file will be located at:/root/suricata/classification.conf
classification.conf
# config classification:shortname,short description,priority
config classification: not-suspicious,Not Suspicious Traffic,3
config classification: unknown,Unknown Traffic,3
config classification: bad-unknown,Potentially Bad Traffic, 2
config classification: attempted-recon,Attempted Information Leak,2
config classification: successful-recon-limited,Information Leak,2
config classification: successful-recon-largescale,Large Scale Information Leak,2
config classification: attempted-dos,Attempted Denial of Service,2
config classification: successful-dos,Denial of Service,2
config classification: attempted-user,Attempted User Privilege Gain,1
config classification: unsuccessful-user,Unsuccessful User Privilege Gain,1
config classification: successful-user,Successful User Privilege Gain,1
config classification: attempted-admin,Attempted Administrator Privilege Gain,1
config classification: successful-admin,Successful Administrator Privilege Gain,1
# NEW CLASSIFICATIONS
config classification: rpc-portmap-decode,Decode of an RPC Query,2
config classification: shellcode-detect,Executable code was detected,3
config classification: string-detect,A suspicious string was detected,3
config classification: suspicious-filename-detect,A suspicious filename was detected,2
config classification: suspicious-login,An attempted login using a suspicious username was detected,2
config classification: system-call-detect,A system call was detected,2
config classification: tcp-connection,A TCP connection was detected,4
config classification: trojan-activity,A Network Trojan was detected,2
config classification: unusual-client-port-connection,A client was using an unusual port,3
config classification: network-scan,Detection of a Network Scan,2
config classification: denial-of-service,Detection of a Denial of Service Attack,2
config classification: non-standard-protocol,Detection of a non-standard protocol or event,3
config classification: protocol-command-decode,Generic Protocol Command Decode,3
config classification: web-application-activity,access to a potentially vulnerable web application,2
config classification: web-application-attack,Web Application Attack,1
config classification: misc-activity,Misc activity,3
config classification: misc-attack,Misc Attack,3
config classification: icmp-event,Generic ICMP event,3
config classification: inappropriate-content,Inappropriate Content was Detected,3
config classification: policy-violation,Potential Corporate Privacy Violation,3
config classification: default-login-attempt,Attempt to login by a default username and password,2
# Update
config classification: targeted-activity,Targeted Malicious Activity was Detected,1
config classification: exploit-kit,Exploit Kit Activity Detected,1
config classification: external-ip-check,Device Retrieving External IP Address Detected,3
config classification: domain-c2,Domain Observed Used for C2 Detected,1
config classification: pup-activity,Possibly Unwanted Program Detected,2
config classification: credential-theft,Successful Credential Theft Detected,1
config classification: social-engineering,Possible Social Engineering Attempted,3
config classification: coin-mining,Crypto Currency Mining Activity Detected,3
config classification: command-and-control,Malware Command and Control Activity Detected,1
config classification: sdf,Sensitive Data File Content Detected,3
# OPNsense rules
config classification: file-transfer,File-Transfer app detection by OPNsense,3
config classification: mail,Mailprovider app detection by OPNsense,3
config classification: media-streaming,Media-Streaming app detection by OPNsense,3
config classification: messaging,Messenger app detection by OPNsense,3
config classification: social-media,Social-Media app detection by OPNsense,3
config classification: test,OPNsense Test Rules,3
config classification: uncategorized,Uncategorized app detection by OPNsense,3
Copy this file to Suricata folder
cp /root/suricata/classification.config /usr/local/etc/suricata/classification.config
Get faster Suricata-Update Processing
Get a “python” executable as ‘suricata-update’ looks for Python not Python3:ln -s /usr/local/bin/python3 /usr/local/bin/python
Then clone the Git repo:git clone https://github.com/OISF/suricata-update.git
Then update the ‘suricata-update update’ command from the ‘suricataupdate.sh’ script to be using the Python Module from the Git Repo (this is the new line):/root/suricata-update/bin/suricata-update update --config /root/suricata/update.yaml --suricata-conf /usr/local/etc/suricata/suricata.yaml --suricata /usr/local/bin/suricata --data-dir /usr/local/etc/suricata --threshold-in=/root/suricata/threshold.in --threshold-out=/usr/local/etc/suricata/threshold.config --output /usr/local/etc/suricata/opnsense.rules -v --no-test --no-reload | tee /root/suricataupdate.log
Soon I will share some suggested disable/enable/drop/modify configs, but at this time I am still changing my too often to want to publish here. Further, I don’t expect to be checking out the drop element until a later day – focusing on disable, enable, and modify for now.
Best of luck, please comment and suggest updates/fixes if necessary!