snort3: complete rework
- Add many options to config file. - Move rules and generated snort.lua to /tmp. - Add script for downloading rules. - Add preliminary reporting capabilites. Signed-off-by: Eric Fahlgren <ericfahlgren@gmail.com>
This commit is contained in:
parent
904438be39
commit
f21dffc2a3
10 changed files with 888 additions and 15 deletions
|
@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=snort3
|
PKG_NAME:=snort3
|
||||||
PKG_VERSION:=3.1.75.0
|
PKG_VERSION:=3.1.75.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=3
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://github.com/snort3/snort3/archive/refs/tags/
|
PKG_SOURCE_URL:=https://github.com/snort3/snort3/archive/refs/tags/
|
||||||
|
@ -25,7 +25,7 @@ define Package/snort3
|
||||||
SUBMENU:=Firewall
|
SUBMENU:=Firewall
|
||||||
SECTION:=net
|
SECTION:=net
|
||||||
CATEGORY:=Network
|
CATEGORY:=Network
|
||||||
DEPENDS:=+libstdcpp +libdaq3 +libdnet +libopenssl +libpcap +libpcre +libpthread +libuuid +zlib +libhwloc +libtirpc @HAS_LUAJIT_ARCH +luajit +libatomic
|
DEPENDS:=+libstdcpp +libdaq3 +libdnet +libopenssl +libpcap +libpcre +libpthread +libuuid +zlib +libhwloc +libtirpc @HAS_LUAJIT_ARCH +luajit +libatomic +kmod-nft-queue
|
||||||
TITLE:=Lightweight Network Intrusion Detection System
|
TITLE:=Lightweight Network Intrusion Detection System
|
||||||
URL:=http://www.snort.org/
|
URL:=http://www.snort.org/
|
||||||
MENU:=1
|
MENU:=1
|
||||||
|
@ -76,6 +76,10 @@ define Package/snort3/install
|
||||||
$(PKG_INSTALL_DIR)/usr/bin/u2{boat,spewfoo} \
|
$(PKG_INSTALL_DIR)/usr/bin/u2{boat,spewfoo} \
|
||||||
$(1)/usr/bin/
|
$(1)/usr/bin/
|
||||||
|
|
||||||
|
$(INSTALL_BIN) \
|
||||||
|
./files/snort-{mgr,rules} \
|
||||||
|
$(1)/usr/bin/
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/usr/lib/snort
|
$(INSTALL_DIR) $(1)/usr/lib/snort
|
||||||
$(CP) \
|
$(CP) \
|
||||||
$(PKG_INSTALL_DIR)/usr/lib/snort/daq/daq_hext.so \
|
$(PKG_INSTALL_DIR)/usr/lib/snort/daq/daq_hext.so \
|
||||||
|
@ -90,6 +94,19 @@ define Package/snort3/install
|
||||||
$(PKG_INSTALL_DIR)/usr/include/snort/lua/snort_plugin.lua \
|
$(PKG_INSTALL_DIR)/usr/include/snort/lua/snort_plugin.lua \
|
||||||
$(1)/usr/share/lua/
|
$(1)/usr/share/lua/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/usr/share/snort
|
||||||
|
$(INSTALL_CONF) \
|
||||||
|
./files/main.uc \
|
||||||
|
$(1)/usr/share/snort/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/usr/share/snort/templates
|
||||||
|
$(INSTALL_CONF) \
|
||||||
|
./files/nftables.uc \
|
||||||
|
$(1)/usr/share/snort/templates/
|
||||||
|
$(INSTALL_CONF) \
|
||||||
|
./files/snort.uc \
|
||||||
|
$(1)/usr/share/snort/templates/
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/etc/snort/{rules,lists,builtin_rules,so_rules}
|
$(INSTALL_DIR) $(1)/etc/snort/{rules,lists,builtin_rules,so_rules}
|
||||||
|
|
||||||
$(INSTALL_CONF) \
|
$(INSTALL_CONF) \
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
-- Unused when using 'snort-mgr', do not modify without deep understanding.
|
||||||
-- setup HOME_NET below with your IP range/ranges to protect
|
-- setup HOME_NET below with your IP range/ranges to protect
|
||||||
HOME_NET = [[ 192.168.1.0/24 10.1.0.1/24 ]]
|
--HOME_NET = [[ 192.168.1.0/24 10.1.0.0/24 ]]
|
||||||
EXTERNAL_NET = "!$HOME_NET"
|
--EXTERNAL_NET = "!$HOME_NET"
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
-- This file is no longer used if you are using 'snort-mgr' to create the
|
||||||
|
-- configuration. It is left as a sample.
|
||||||
|
--
|
||||||
-- use ths file to customize any functions defined in /etc/snort/snort.lua
|
-- use ths file to customize any functions defined in /etc/snort/snort.lua
|
||||||
|
|
||||||
-- switch tap to inline in ips and uncomment the below to run snort in inline mode
|
-- switch tap to inline in ips and uncomment the below to run snort in inline mode
|
||||||
|
|
263
net/snort3/files/main.uc
Normal file
263
net/snort3/files/main.uc
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
{%
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
//
|
||||||
|
// The tables defined using 'config_item' are the source of record for the
|
||||||
|
// configuration file, '/etc/config/snort'. If you wish to add new items,
|
||||||
|
// do that only in the tables and propagate that use into the templates.
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import { cursor } from 'uci';
|
||||||
|
let uci = cursor();
|
||||||
|
|
||||||
|
function wrn(fmt, ...args) {
|
||||||
|
if (getenv("QUIET"))
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
let msg = "ERROR: " + sprintf(fmt, ...args);
|
||||||
|
|
||||||
|
if (getenv("TTY"))
|
||||||
|
warn(`\033[33m${msg}\033[m\n`);
|
||||||
|
else
|
||||||
|
warn(`[!] ${msg}\n`);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function config_item(type, values, def) {
|
||||||
|
// If no default value is provided explicity, then values[0] is used as default.
|
||||||
|
if (! type in [ "enum", "range", "path", "str" ]) {
|
||||||
|
wrn(`Invalid item type '${type}', must be one of "enum", "range", "path" or "str".`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type == "range" && (length(values) != 2 || values[0] > values[1])) {
|
||||||
|
wrn(`A 'range' type item must have exactly 2 values in ascending order.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Maybe check paths for existence???
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: type,
|
||||||
|
values: values,
|
||||||
|
default: def ?? values[0],
|
||||||
|
|
||||||
|
contains: function(value) {
|
||||||
|
// Check if the value is contained in the listed values,
|
||||||
|
// depending on the item type.
|
||||||
|
switch (this.type) {
|
||||||
|
case "enum":
|
||||||
|
return value in this.values;
|
||||||
|
case "range":
|
||||||
|
return value >= this.values[0] && value <= this.values[1];
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
allowed: function() {
|
||||||
|
// Show a pretty version of the possible values, for error messages.
|
||||||
|
switch (this.type) {
|
||||||
|
case "enum":
|
||||||
|
return "one of [" + join(", ", this.values) + "]";
|
||||||
|
case "range":
|
||||||
|
return `${this.values[0]} <= x <= ${this.values[1]}`;
|
||||||
|
case "path":
|
||||||
|
return "a path string";
|
||||||
|
case "str":
|
||||||
|
return "a string";
|
||||||
|
default:
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const snort_config = {
|
||||||
|
enabled: config_item("enum", [ 0, 1 ], 0), // Defaults to off, so that user must configure before first start.
|
||||||
|
manual: config_item("enum", [ 0, 1 ], 1), // Allow user to manually configure, legacy behavior when enabled.
|
||||||
|
oinkcode: config_item("str", [ "" ]), // User subscription oinkcode. Much more in 'snort-rules' script.
|
||||||
|
home_net: config_item("str", [ "" ], "192.168.1.0/24"),
|
||||||
|
external_net: config_item("str", [ "" ], "any"),
|
||||||
|
|
||||||
|
config_dir: config_item("path", [ "/etc/snort" ]), // Location of the base snort configuration files.
|
||||||
|
temp_dir: config_item("path", [ "/var/snort.d" ]), // Location of all transient snort config, including downloaded rules.
|
||||||
|
log_dir: config_item("path", [ "/var/log" ]), // Location of the generated logs, and oh-by-the-way the snort PID file (why?).
|
||||||
|
logging: config_item("enum", [ 0, 1 ], 1),
|
||||||
|
openappid: config_item("enum", [ 0, 1 ], 0),
|
||||||
|
|
||||||
|
mode: config_item("enum", [ "ids", "ips" ]),
|
||||||
|
method: config_item("enum", [ "pcap", "afpacket", "nfq" ]),
|
||||||
|
action: config_item("enum", [ "alert", "block", "drop", "reject" ]),
|
||||||
|
interface: config_item("str", [ uci.get("network", "wan", "device") ]),
|
||||||
|
snaplen: config_item("range", [ 1518, 65535 ]), // int daq.snaplen = 1518: set snap length (same as -s) { 0:65535 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const nfq_config = {
|
||||||
|
queue_count: config_item("range", [ 1, 16 ], 4), // Count of queues to allocate in nft chain when method=nfq, usually 2-8.
|
||||||
|
queue_start: config_item("range", [ 1, 32768], 4), // Start of queue numbers in nftables.
|
||||||
|
queue_maxlen: config_item("range", [ 1024, 65536 ], 1024), // --daq-var queue_maxlen=int
|
||||||
|
fanout_type: config_item("enum", [ "hash", "lb", "cpu", "rollover", "rnd", "qm"], "hash"), // See below.
|
||||||
|
thread_count: config_item("range", [ 0, 32 ], 0), // 0 = use cpu count
|
||||||
|
chain_type: config_item("enum", [ "prerouting", "input", "forward", "output", "postrouting" ], "input"),
|
||||||
|
chain_priority: config_item("enum", [ "raw", "filter", "300"], "filter"),
|
||||||
|
include: config_item("path", [ "" ]), // User-defined rules to include inside queue chain.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let _snort_config_doc =
|
||||||
|
"
|
||||||
|
This is not an exhaustive list of configuration items, just those that
|
||||||
|
require more explanation than is given in the tables that define them, below.
|
||||||
|
|
||||||
|
https://openwrt.org/docs/guide-user/services/snort
|
||||||
|
|
||||||
|
snort
|
||||||
|
manual - When set to 1, use manual configuration for legacy behavior.
|
||||||
|
When disabled, then use this config.
|
||||||
|
interface - Default should usually be 'uci get network.wan.device',
|
||||||
|
something like 'eth0'
|
||||||
|
home_net - IP range/ranges to protect. May be 'any', but more likely it's
|
||||||
|
your lan range, default is '192.168.1.0/24'
|
||||||
|
external_net - IP range external to home. Usually 'any', but if you only
|
||||||
|
care about true external hosts (trusting all lan devices),
|
||||||
|
then '!$HOMENET' or some specific range
|
||||||
|
mode - 'ids' or 'ips', for detection-only or prevention, respectively
|
||||||
|
oinkcode - https://www.snort.org/oinkcodes
|
||||||
|
config_dir - Location of the base snort configuration files. Default /etc/snort
|
||||||
|
temp_dir - Location of all transient snort config, including downloaded rules
|
||||||
|
Default /var/snort.d
|
||||||
|
logging - Enable external logging of events thus enabling 'snort-mgr report',
|
||||||
|
otherwise events only go to system log (i.e., 'logread -e snort:')
|
||||||
|
log_dir - Location of the generated logs, and oh-by-the-way the snort
|
||||||
|
PID file (why?). Default /var/log
|
||||||
|
openappid - Enabled inspection using the 'openappid' package
|
||||||
|
See 'opkg info openappid'
|
||||||
|
action - 'alert', 'block', 'reject' or 'drop'
|
||||||
|
method - 'pcap', 'afpacket' or 'nfq'
|
||||||
|
snaplen - int daq.snaplen = 1518: set snap length (same as -s) { 0:65535 }
|
||||||
|
|
||||||
|
nfq - https://github.com/snort3/libdaq/blob/master/modules/nfq/README.nfq.md
|
||||||
|
queue_maxlen - nfq's '--daq-var queue_maxlen=int'
|
||||||
|
queue_count - Count of queues to use when method=nfq, usually 2-8
|
||||||
|
fanout_type - Sets kernel load balancing algorithm*, one of hash, lb, cpu,
|
||||||
|
rollover, rnd, qm.
|
||||||
|
thread_count - int snort.-z: <count> maximum number of packet threads
|
||||||
|
(same as --max-packet-threads); 0 gets the number of
|
||||||
|
CPU cores reported by the system; default is 1 { 0:max32 }
|
||||||
|
chain_type - Chain type when generating nft output
|
||||||
|
chain_priority - Chain priority when generating nft output
|
||||||
|
include - Full path to user-defined extra rules to include inside queue chain
|
||||||
|
|
||||||
|
* - for details on fanout_type, see these pages:
|
||||||
|
https://github.com/florincoras/daq/blob/master/README
|
||||||
|
https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
|
||||||
|
";
|
||||||
|
|
||||||
|
function snort_config_doc(comment) {
|
||||||
|
if (comment == null) comment = "";
|
||||||
|
if (comment != "") comment += " ";
|
||||||
|
for (let line in split(_snort_config_doc, "\n")) {
|
||||||
|
let msg = rtrim(sprintf("%s%s", comment, line));
|
||||||
|
print(msg, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function load(section, config) {
|
||||||
|
let self = {
|
||||||
|
".name": section,
|
||||||
|
".config": config,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the defaults from definitions in table.
|
||||||
|
for (let item in config) {
|
||||||
|
self[item] = config[item].default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite them with any uci config settings.
|
||||||
|
let cfg = uci.get_all("snort", section);
|
||||||
|
for (let item in cfg) {
|
||||||
|
// If you need to rename, delete or change the meaning of a
|
||||||
|
// config item, just intercept it and do the work here.
|
||||||
|
|
||||||
|
if (exists(config, item)) {
|
||||||
|
let val = cfg[item];
|
||||||
|
if (config[item].contains(val))
|
||||||
|
self[item] = val;
|
||||||
|
else {
|
||||||
|
wrn(`In option ${item}='${val}', must be ${config[item].allowed()}`);
|
||||||
|
// ??? self[item] = config[item][0]; ???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
let snort = null;
|
||||||
|
let nfq = null;
|
||||||
|
function load_all() {
|
||||||
|
snort = load("snort", snort_config);
|
||||||
|
nfq = load("nfq", nfq_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dump_config(settings) {
|
||||||
|
let section = settings[".name"];
|
||||||
|
let config = settings[".config"];
|
||||||
|
printf("config %s '%s'\n", section, section);
|
||||||
|
for (let item in config) {
|
||||||
|
printf("\toption %-15s %-17s# %s\n", item, `'${settings[item]}'`, config[item].allowed());
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_snort() {
|
||||||
|
include("templates/snort.uc", { snort, nfq });
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_nftables() {
|
||||||
|
include("templates/nftables.uc", { snort, nfq });
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_config() {
|
||||||
|
snort_config_doc("#");
|
||||||
|
dump_config(snort);
|
||||||
|
dump_config(nfq);
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_help() {
|
||||||
|
snort_config_doc();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
load_all();
|
||||||
|
|
||||||
|
switch (getenv("TYPE")) {
|
||||||
|
case "snort":
|
||||||
|
render_snort();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case "nftables":
|
||||||
|
render_nftables();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case "config":
|
||||||
|
render_config();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case "help":
|
||||||
|
render_help();
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print("Invalid table type.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
-%}
|
18
net/snort3/files/nftables.uc
Normal file
18
net/snort3/files/nftables.uc
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Do not edit, automatically generated. See /usr/share/snort/templates.
|
||||||
|
{%
|
||||||
|
// Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
let queues = `${nfq.queue_start}-${int(nfq.queue_start)+int(nfq.queue_count)-1}`;
|
||||||
|
let chain_type = nfq.chain_type;
|
||||||
|
-%}
|
||||||
|
|
||||||
|
table inet snort {
|
||||||
|
chain {{ chain_type }}_{{ snort.mode }} {
|
||||||
|
type filter hook {{ chain_type }} priority {{ nfq.chain_priority }}
|
||||||
|
policy accept
|
||||||
|
{% if (nfq.include) { include(nfq.include, { snort, nfq }); } %}
|
||||||
|
# tcp flags ack ct direction original ct state established counter accept
|
||||||
|
counter queue flags bypass to {{ queues }}
|
||||||
|
}
|
||||||
|
}
|
260
net/snort3/files/snort-mgr
Normal file
260
net/snort3/files/snort-mgr
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# shellcheck disable=SC2039 # "local" not defined in POSIX sh
|
||||||
|
|
||||||
|
PROG="/usr/bin/snort"
|
||||||
|
MAIN="/usr/share/snort/main.uc"
|
||||||
|
CONF_DIR="/var/snort.d"
|
||||||
|
CONF="${CONF_DIR}/snort_conf.lua"
|
||||||
|
|
||||||
|
VERBOSE=
|
||||||
|
TESTING=
|
||||||
|
NLINES=0
|
||||||
|
|
||||||
|
[ ! -e "$CONF_DIR" ] && mkdir "$CONF_DIR"
|
||||||
|
[ -e /dev/stdin ] && STDIN=/dev/stdin || STDIN=/proc/self/fd/0
|
||||||
|
[ -e /dev/stdout ] && STDOUT=/dev/stdout || STDOUT=/proc/self/fd/1
|
||||||
|
[ -t 2 ] && export TTY=1
|
||||||
|
|
||||||
|
die() {
|
||||||
|
[ -n "$QUIET" ] || echo "$@" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_offload()
|
||||||
|
{
|
||||||
|
# From https://forum.openwrt.org/t/snort-3-nfq-with-ips-mode/161172
|
||||||
|
# https://blog.snort.org/2016/08/running-snort-on-commodity-hardware.html
|
||||||
|
# Not needed when running the nft daq as defragmentation is done by the kernel.
|
||||||
|
# What about pcap?
|
||||||
|
|
||||||
|
local filter_method=$(uci -q get snort.snort.method)
|
||||||
|
if [ "$filter_method" = "afpacket" ]; then
|
||||||
|
local wan=$(uci get snort.snort.interface)
|
||||||
|
if [ -n "$wan" ] && ethtool -k "$wan" | grep -q -E '(tcp-segmentation-offload|receive-offload): on' ; then
|
||||||
|
ethtool -K "$wan" gro off lro off tso off 2> /dev/null
|
||||||
|
log "Disabled gro, lro and tso on '$wan' using ethtool."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_rm_table() {
|
||||||
|
for table_type in 'inet' 'netdev'; do
|
||||||
|
nft list tables | grep -q "${table_type} snort" && nft delete table "${table_type}" snort
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_add_table() {
|
||||||
|
if [ "$(uci -q get snort.snort.method)" = "nfq" ]; then
|
||||||
|
print nftables | nft $VERBOSE -f $STDIN
|
||||||
|
[ -n "$VERBOSE" ] && nft list table inet snort
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
# Generates all the configuration, then reports the config file for snort.
|
||||||
|
# Does NOT generate the rules file, you'll need to do 'update-rules' first.
|
||||||
|
nft_rm_table
|
||||||
|
print snort > "$CONF"
|
||||||
|
nft_add_table
|
||||||
|
echo "$CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
# Merely cleans up after.
|
||||||
|
nft_rm_table
|
||||||
|
[ -e "$CONF" ] && rm "$CONF"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_rules() {
|
||||||
|
/usr/bin/snort-rules $TESTING
|
||||||
|
}
|
||||||
|
|
||||||
|
print() {
|
||||||
|
# '$1' is file type to generate, one of:
|
||||||
|
# config, snort or nftables
|
||||||
|
TYPE=$1 utpl -S "$MAIN"
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local manual=$(uci get snort.snort.manual)
|
||||||
|
[ "$manual" = 1 ] && return 0
|
||||||
|
|
||||||
|
[ -n "$QUIET" ] && OUT=/dev/null || OUT=$STDOUT
|
||||||
|
local test_conf="${CONF_DIR}/test_conf.lua"
|
||||||
|
print snort > "${test_conf}" || die "Errors during generation of config."
|
||||||
|
if $PROG -T -q --warn-all -c "${test_conf}" 2> $OUT ; then
|
||||||
|
rm "${test_conf}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
die "Errors in snort config tests."
|
||||||
|
}
|
||||||
|
|
||||||
|
report() {
|
||||||
|
# Reported IPs have source port stripped, but destination port (if any)
|
||||||
|
# retained.
|
||||||
|
#
|
||||||
|
# json notes
|
||||||
|
# from alert_fast:
|
||||||
|
# 08/30-11:39:57.639021 [**] [1:382:11] "PROTOCOL-ICMP PING Windows" [**] [Classification: Misc activity] [Priority: 3] {ICMP} 10.1.1.186 -> 10.1.1.20
|
||||||
|
#
|
||||||
|
# same event in alert_json (single line broken for clarity):
|
||||||
|
# { "timestamp" : "08/30-11:39:57.639021", "pkt_num" : 5366, "proto" : "ICMP", "pkt_gen" : "raw",
|
||||||
|
# "pkt_len" : 60, "dir" : "C2S", "src_ap" : "10.1.1.186:0", "dst_ap" : "10.1.1.20:0",
|
||||||
|
# "rule" : "1:382:11", "action" : "allow" }
|
||||||
|
#
|
||||||
|
# Second part of "rule", 382, is "sid" in ruleset, suffixing 11 is "rev".
|
||||||
|
# grep '\bsid:382\b' /etc/snort/rules/snort.rules (again, single line broken for clarity):
|
||||||
|
# alert icmp $EXTERNAL_NET any -> $HOME_NET any ( msg:"PROTOCOL-ICMP PING Windows";
|
||||||
|
# itype:8; content:"abcdefghijklmnop",depth 16; metadata:ruleset community;
|
||||||
|
# classtype:misc-activity; sid:382; rev:11; )
|
||||||
|
#
|
||||||
|
# Not sure where the prefixing 1 comes from.
|
||||||
|
|
||||||
|
local logging=$(uci get snort.snort.logging)
|
||||||
|
local log_dir=$(uci get snort.snort.log_dir)
|
||||||
|
local pattern="$1"
|
||||||
|
|
||||||
|
if [ "$logging" = 0 ]; then
|
||||||
|
die "Logging is not enabled in snort config."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if [ -z "$pattern" ]; then
|
||||||
|
# die "Provide a valid IP and try again."
|
||||||
|
#fi
|
||||||
|
|
||||||
|
[ "$NLINES" = 0 ] && output="cat" || output="head -n $NLINES"
|
||||||
|
|
||||||
|
# Fix this to use json file.
|
||||||
|
tmp="/tmp/snort.report.$$"
|
||||||
|
echo "Intrusions involving ${pattern:-all IPs}"
|
||||||
|
grep "\b${pattern}\b" "$log_dir/alert_fast.txt" \
|
||||||
|
| sed 's/.*"\([^"]*\)".* \([^ :]*\)[: ].*-> \(.*\)/\1#\2#\3/' > "$tmp"
|
||||||
|
n_incidents="$(wc -l < $tmp)"
|
||||||
|
lines=$(sort "$tmp" | uniq -c | sort -nr \
|
||||||
|
| awk -F'#' '{printf "%-80s %-12s -> %s\n", $1, $2, $3}')
|
||||||
|
echo "$lines" | $output
|
||||||
|
n_lines=$(echo "$lines" | wc -l)
|
||||||
|
[ "$NLINES" -gt 0 ] && [ "$NLINES" -lt "$n_lines" ] && echo " ... Only showing $NLINES of $n_lines most frequent incidents."
|
||||||
|
printf "%7d total incidents\n" "$n_incidents"
|
||||||
|
rm "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
echo 'tbd'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while [ -n "$1" ]; do
|
||||||
|
case "$1" in
|
||||||
|
-q)
|
||||||
|
export QUIET=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-v)
|
||||||
|
export VERBOSE=-e
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-t)
|
||||||
|
TESTING=-t
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-n)
|
||||||
|
NLINES="$2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
setup)
|
||||||
|
setup
|
||||||
|
;;
|
||||||
|
teardown)
|
||||||
|
teardown
|
||||||
|
;;
|
||||||
|
resetup)
|
||||||
|
QUIET=1 check || die "The generated snort lua configuration contains errors, not restarting."
|
||||||
|
teardown
|
||||||
|
setup
|
||||||
|
;;
|
||||||
|
update-rules)
|
||||||
|
update_rules
|
||||||
|
;;
|
||||||
|
check)
|
||||||
|
check
|
||||||
|
;;
|
||||||
|
print)
|
||||||
|
print "$2"
|
||||||
|
;;
|
||||||
|
report)
|
||||||
|
report "$2"
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cat <<USAGE
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
-n = show only NLINES of output
|
||||||
|
-q = quiet
|
||||||
|
-v = verbose
|
||||||
|
-t = testing mode
|
||||||
|
|
||||||
|
$0 [-v] [-q] setup|teardown|resetup
|
||||||
|
|
||||||
|
Normally only used internally by init scripts to manage the generation
|
||||||
|
of configuration files and any needed firewall rules. None of these
|
||||||
|
modify the snort rules in any way (see 'update-rules').
|
||||||
|
setup = generates snort config, sets up firewall.
|
||||||
|
teardown = removes any firewall rules.
|
||||||
|
resetup = shorthand for teardown and then setup.
|
||||||
|
|
||||||
|
|
||||||
|
$0 [-n lines] report [pattern]
|
||||||
|
|
||||||
|
Report on incidents. Note this is somewhat experimental, so suggested
|
||||||
|
improvements are quite welcome.
|
||||||
|
pattern = IP or piece of IP or something in the message to filter.
|
||||||
|
|
||||||
|
$0 [-t] update-rules
|
||||||
|
|
||||||
|
Download and install the snort ruleset. Testing mode generates a canned
|
||||||
|
rule that matches IPv4 ping requests. A typical test scenario might look
|
||||||
|
like:
|
||||||
|
|
||||||
|
> snort-mgr -t update-rules
|
||||||
|
> /etc/init.d/snort start
|
||||||
|
> ping -c4 8.8.8.8
|
||||||
|
> logread -e "TEST ALERT"
|
||||||
|
|
||||||
|
|
||||||
|
$0 print config|snort|nftables
|
||||||
|
|
||||||
|
Print the rendered file contents.
|
||||||
|
config = Display contents of /etc/config/snort, but with all values and
|
||||||
|
descriptions. Missing values shown with defaults.
|
||||||
|
snort = The snort configuration file, which is a lua script.
|
||||||
|
nftables = The nftables script used to define the input queues when using
|
||||||
|
the 'nfq' DAQ.
|
||||||
|
|
||||||
|
|
||||||
|
$0 [-q] check
|
||||||
|
|
||||||
|
Test the rendered config using snort's check mode without
|
||||||
|
applying it to the running system.
|
||||||
|
|
||||||
|
|
||||||
|
$0 status
|
||||||
|
|
||||||
|
Print the nfq counter values and blah blah blah
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
;;
|
||||||
|
esac
|
92
net/snort3/files/snort-rules
Normal file
92
net/snort3/files/snort-rules
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# shellcheck disable=SC2039 # "local" not defined in POSIX sh
|
||||||
|
|
||||||
|
alias log='logger -s -t "snort-rules[$$]" -p "info"'
|
||||||
|
|
||||||
|
[ "$1" = "-t" ] && testing=true || testing=false
|
||||||
|
|
||||||
|
download_rules() {
|
||||||
|
# Further information:
|
||||||
|
# https://www.snort.org/products#rule_subscriptions
|
||||||
|
# https://www.snort.org/oinkcodes
|
||||||
|
#
|
||||||
|
# Also, what to do about "subscription" vs Talos_LightSPD rules when subbed?
|
||||||
|
# Add a "use_rules" list or option or something?
|
||||||
|
oinkcode=$(uci -q get snort.snort.oinkcode)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local conf_dir=$(uci -q get snort.snort.config_dir || echo "/etc/snort")
|
||||||
|
local rules_file="$conf_dir/rules/snort.rules"
|
||||||
|
local data_dir=$(uci -q get snort.snort.temp_dir || echo "/var/snort.d")
|
||||||
|
local data_tar="$data_dir/rules.tar.gz"
|
||||||
|
|
||||||
|
# Make sure everything exists.
|
||||||
|
[ -d "$data_dir" ] || mkdir -p "$data_dir"
|
||||||
|
|
||||||
|
|
||||||
|
if $testing ; then
|
||||||
|
log "Generating testing rules..."
|
||||||
|
new_rules="$data_dir/testing.rules"
|
||||||
|
rm -f "$new_rules"
|
||||||
|
echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v4"; icode:0; itype: 8; sid:10000010; rev:001;)' >> "$new_rules"
|
||||||
|
#echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v6"; icode:0; itype:33; sid:10000011; rev:001;)' >> "$new_rules"
|
||||||
|
#echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v6"; icode:0; itype:34; sid:10000012; rev:001;)' >> "$new_rules"
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ -z "$oinkcode" ]; then
|
||||||
|
# If you do not have a subscription, then we use the community rules:
|
||||||
|
log "Downloading community rules..."
|
||||||
|
url="https://www.snort.org/downloads/community/snort3-community-rules.tar.gz"
|
||||||
|
|
||||||
|
else
|
||||||
|
# If you have a subscription and its corresponding oinkcode, use this:
|
||||||
|
#
|
||||||
|
# 'snortver' is the version number of the snort executable in use on your
|
||||||
|
# router.
|
||||||
|
#
|
||||||
|
# Ideally, the 'snort --version' output would work, but OpenWrt builds
|
||||||
|
# are often between (or, more likely, newer than) those listed on the
|
||||||
|
# snort.org downloads page.
|
||||||
|
#
|
||||||
|
# So instead, we define it manually to be the value just before the
|
||||||
|
# installed version. Look on https://www.snort.org/advisories/ and
|
||||||
|
# select the most recent date. On that page, find the closest version
|
||||||
|
# number preceding your installed version and modify the hard-coded
|
||||||
|
# value below (for example, installed is 31600 then use 31470):
|
||||||
|
|
||||||
|
#snortver=$(snort --version | awk '/Version/ {print gensub("\\.", "", "", $NF)}')
|
||||||
|
snortver=31470
|
||||||
|
|
||||||
|
log "Downloading subscription rules..."
|
||||||
|
url="https://www.snort.org/rules/snortrules-snapshot-$snortver.tar.gz?oinkcode=$oinkcode"
|
||||||
|
fi
|
||||||
|
|
||||||
|
wget "$url" -O "$data_tar" 2>&1 | log || exit 1
|
||||||
|
|
||||||
|
# ??? Does non-community tar contain just the one "*.rules" file, too???
|
||||||
|
new_rules=$(tar tzf "$data_tar" | grep '\.rules$')
|
||||||
|
new_rules="$data_dir/$new_rules"
|
||||||
|
|
||||||
|
old_rules="$data_dir/old.rules"
|
||||||
|
if [ -e "$new_rules" ]; then
|
||||||
|
# Before we overwrite with the new download.
|
||||||
|
log "Stashing old rules to $old_rules ..."
|
||||||
|
mv -f "$new_rules" "$old_rules"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Unpacking $data_tar ..."
|
||||||
|
tar xzvf "$data_tar" -C "$data_dir" | log || exit 1
|
||||||
|
if [ -e "$old_rules" ] && ! cmp -s "$new_rules" "$old_rules" ; then
|
||||||
|
diff "$new_rules" "$old_rules" 2>&1 | log
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$rules_file"
|
||||||
|
ln -s "$new_rules" "$rules_file"
|
||||||
|
|
||||||
|
log "Snort rules loaded, restart snort now."
|
||||||
|
}
|
||||||
|
download_rules
|
|
@ -1,3 +1,74 @@
|
||||||
|
#
|
||||||
|
# This is not an exhaustive list of configuration items, just those that
|
||||||
|
# require more explanation than is given in the tables that define them, below.
|
||||||
|
#
|
||||||
|
# https://openwrt.org/docs/guide-user/services/snort
|
||||||
|
#
|
||||||
|
# snort
|
||||||
|
# manual - When set to 1, use manual configuration for legacy behavior.
|
||||||
|
# When disabled, then use this config.
|
||||||
|
# interface - Default should usually be 'uci get network.wan.device',
|
||||||
|
# something like 'eth0'
|
||||||
|
# home_net - IP range/ranges to protect. May be 'any', but more likely it's
|
||||||
|
# your lan range, default is '192.168.1.0/24'
|
||||||
|
# external_net - IP range external to home. Usually 'any', but if you only
|
||||||
|
# care about true external hosts (trusting all lan devices),
|
||||||
|
# then '!$HOMENET' or some specific range
|
||||||
|
# mode - 'ids' or 'ips', for detection-only or prevention, respectively
|
||||||
|
# oinkcode - https://www.snort.org/oinkcodes
|
||||||
|
# config_dir - Location of the base snort configuration files. Default /etc/snort
|
||||||
|
# temp_dir - Location of all transient snort config, including downloaded rules
|
||||||
|
# Default /var/snort.d
|
||||||
|
# logging - Enable external logging of events thus enabling 'snort-mgr report',
|
||||||
|
# otherwise events only go to system log (i.e., 'logread -e snort:')
|
||||||
|
# log_dir - Location of the generated logs, and oh-by-the-way the snort
|
||||||
|
# PID file (why?). Default /var/log
|
||||||
|
# openappid - Enabled inspection using the 'openappid' package
|
||||||
|
# See 'opkg info openappid'
|
||||||
|
# action - 'alert', 'block', 'reject' or 'drop'
|
||||||
|
# method - 'pcap', 'afpacket' or 'nfq'
|
||||||
|
# snaplen - int daq.snaplen = 1518: set snap length (same as -s) { 0:65535 }
|
||||||
|
#
|
||||||
|
# nfq - https://github.com/snort3/libdaq/blob/master/modules/nfq/README.nfq.md
|
||||||
|
# queue_maxlen - nfq's '--daq-var queue_maxlen=int'
|
||||||
|
# queue_count - Count of queues to use when method=nfq, usually 2-8
|
||||||
|
# fanout_type - Sets kernel load balancing algorithm*, one of hash, lb, cpu,
|
||||||
|
# rollover, rnd, qm.
|
||||||
|
# thread_count - int snort.-z: <count> maximum number of packet threads
|
||||||
|
# (same as --max-packet-threads); 0 gets the number of
|
||||||
|
# CPU cores reported by the system; default is 1 { 0:max32 }
|
||||||
|
# chain_type - Chain type when generating nft output
|
||||||
|
# chain_priority - Chain priority when generating nft output
|
||||||
|
# include - Full path to user-defined extra rules to include inside queue chain
|
||||||
|
#
|
||||||
|
# * - for details on fanout_type, see these pages:
|
||||||
|
# https://github.com/florincoras/daq/blob/master/README
|
||||||
|
# https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
|
||||||
|
#
|
||||||
config snort 'snort'
|
config snort 'snort'
|
||||||
option config_dir '/etc/snort/'
|
option enabled '0' # one of [0, 1]
|
||||||
option interface 'eth0'
|
option manual '1' # one of [0, 1]
|
||||||
|
option oinkcode '' # a string
|
||||||
|
option home_net '192.168.1.0/24' # a string
|
||||||
|
option external_net 'any' # a string
|
||||||
|
option config_dir '/etc/snort' # a path string
|
||||||
|
option temp_dir '/var/snort.d' # a path string
|
||||||
|
option log_dir '/var/log' # a path string
|
||||||
|
option logging '1' # one of [0, 1]
|
||||||
|
option openappid '0' # one of [0, 1]
|
||||||
|
option mode 'ids' # one of [ids, ips]
|
||||||
|
option method 'pcap' # one of [pcap, afpacket, nfq]
|
||||||
|
option action 'alert' # one of [alert, block, drop, reject]
|
||||||
|
option interface 'eth0' # a string
|
||||||
|
option snaplen '1518' # 1518 <= x <= 65535
|
||||||
|
|
||||||
|
config nfq 'nfq'
|
||||||
|
option queue_count '4' # 1 <= x <= 16
|
||||||
|
option queue_start '4' # 1 <= x <= 32768
|
||||||
|
option queue_maxlen '1024' # 1024 <= x <= 65536
|
||||||
|
option fanout_type 'hash' # one of [hash, lb, cpu, rollover, rnd, qm]
|
||||||
|
option thread_count '0' # 0 <= x <= 32
|
||||||
|
option chain_type 'input' # one of [prerouting, input, forward, output, postrouting]
|
||||||
|
option chain_priority 'filter' # one of [raw, filter, 300]
|
||||||
|
option include '' # a path string
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,58 @@
|
||||||
#!/bin/sh /etc/rc.common
|
#!/bin/sh /etc/rc.common
|
||||||
|
# shellcheck disable=SC2039 # "local" not defined in POSIX sh
|
||||||
|
|
||||||
START=99
|
START=99
|
||||||
STOP=10
|
STOP=10
|
||||||
|
|
||||||
USE_PROCD=1
|
USE_PROCD=1
|
||||||
PROG=/usr/bin/snort
|
PROG=/usr/bin/snort
|
||||||
|
MGR=/usr/bin/snort-mgr
|
||||||
|
|
||||||
validate_snort_section() {
|
validate_snort_section() {
|
||||||
|
$MGR -q check || return 1
|
||||||
uci_validate_section snort snort "${1}" \
|
uci_validate_section snort snort "${1}" \
|
||||||
|
'enabled:bool:0' \
|
||||||
|
'manual:bool:1' \
|
||||||
'config_dir:string' \
|
'config_dir:string' \
|
||||||
'interface:string'
|
'interface:string'
|
||||||
}
|
}
|
||||||
|
|
||||||
start_service() {
|
start_service() {
|
||||||
local config_file interface
|
# If you wish to use application-managed PID file:
|
||||||
|
# output.logdir, in the snort lua config, determines the PID file location.
|
||||||
|
# Add '--create-pidfile' to the 'command', below.
|
||||||
|
|
||||||
validate_snort_section snort || {
|
local enabled
|
||||||
echo "validation failed"
|
local manual
|
||||||
return 1
|
local config_dir
|
||||||
}
|
local interface
|
||||||
|
|
||||||
|
validate_snort_section snort || {
|
||||||
|
echo "Validation failed, try 'snort-mgr check'."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$enabled" = 0 ] && return
|
||||||
|
|
||||||
procd_open_instance
|
procd_open_instance
|
||||||
procd_set_param command $PROG -q -i "$interface" -c "${config_dir%/}/snort.lua" --tweaks local
|
if [ "$manual" = 0 ]; then
|
||||||
procd_set_param env SNORT_LUA_PATH="$config_dir"
|
local config_file=$($MGR setup)
|
||||||
procd_set_param file $CONFIGFILE
|
procd_set_param command "$PROG" -q -c "${config_file}"
|
||||||
|
else
|
||||||
|
procd_set_param command $PROG -q -i "$interface" -c "${config_dir%/}/snort.lua" --tweaks local
|
||||||
|
procd_set_param env SNORT_LUA_PATH="$config_dir"
|
||||||
|
procd_set_param file $CONFIGFILE
|
||||||
|
fi
|
||||||
procd_set_param respawn
|
procd_set_param respawn
|
||||||
|
procd_set_param stdout 0
|
||||||
|
procd_set_param stderr 1
|
||||||
procd_close_instance
|
procd_close_instance
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_service()
|
stop_service()
|
||||||
{
|
{
|
||||||
service_stop ${PROG}
|
service_stop "$PROG"
|
||||||
|
$MGR teardown
|
||||||
}
|
}
|
||||||
|
|
||||||
service_triggers()
|
service_triggers()
|
||||||
|
|
126
net/snort3/files/snort.uc
Normal file
126
net/snort3/files/snort.uc
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{%
|
||||||
|
// Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
// Create some snort-format-specific items.
|
||||||
|
|
||||||
|
let home_net = snort.home_net == 'any' ? "'any'" : snort.home_net;
|
||||||
|
let external_net = snort.external_net;
|
||||||
|
|
||||||
|
let line_mode = snort.mode == "ids" ? "tap" : "inline";
|
||||||
|
|
||||||
|
let inputs = null;
|
||||||
|
let vars = null;
|
||||||
|
switch (snort.method) {
|
||||||
|
case "pcap":
|
||||||
|
case "afpacket":
|
||||||
|
inputs = `{ '${snort.interface}' }`;
|
||||||
|
vars = "{}";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "nfq":
|
||||||
|
inputs = "{ ";
|
||||||
|
for (let i = int(nfq.queue_start); i < int(nfq.queue_start)+int(nfq.queue_count); i++) {
|
||||||
|
inputs += `'${i}', `
|
||||||
|
}
|
||||||
|
inputs += "}";
|
||||||
|
|
||||||
|
vars = `{ 'device=${snort.interface}', 'queue_maxlen=${nfq.queue_maxlen}', 'fanout_type=${nfq.fanout_type}', 'fail_open', }`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
-%}
|
||||||
|
-- Do not edit, automatically generated. See /usr/share/snort/templates.
|
||||||
|
|
||||||
|
-- These must be defined before processing snort.lua
|
||||||
|
-- The default include '/etc/snort/homenet.lua' must not redefine them.
|
||||||
|
HOME_NET = [[ {{ home_net }} ]]
|
||||||
|
EXTERNAL_NET = '{{ external_net }}'
|
||||||
|
|
||||||
|
include('{{ snort.config_dir }}/snort.lua')
|
||||||
|
|
||||||
|
snort = {
|
||||||
|
{% if (snort.mode == 'ips'): %}
|
||||||
|
['-Q'] = true,
|
||||||
|
{% endif %}
|
||||||
|
['--daq'] = {{ snort.method }},
|
||||||
|
--['--daq-dir'] = '/usr/lib/daq/',
|
||||||
|
{% if (snort.method == 'nfq'): %}
|
||||||
|
['--max-packet-threads'] = {{ nfq.thread_count }},
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
|
||||||
|
ips = {
|
||||||
|
mode = {{ line_mode }},
|
||||||
|
variables = default_variables,
|
||||||
|
action_override = {{ snort.action }},
|
||||||
|
include = "{{ snort.config_dir }}/" .. RULE_PATH .. '/snort.rules',
|
||||||
|
}
|
||||||
|
|
||||||
|
daq = {
|
||||||
|
inputs = {{ inputs }},
|
||||||
|
snaplen = {{ snort.snaplen }},
|
||||||
|
module_dirs = { '/usr/lib/daq/', },
|
||||||
|
modules = {
|
||||||
|
{
|
||||||
|
name = '{{ snort.method }}',
|
||||||
|
mode = {{ line_mode }},
|
||||||
|
variables = {{ vars }},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alert_syslog = {
|
||||||
|
level = 'info',
|
||||||
|
}
|
||||||
|
|
||||||
|
{% if (int(snort.logging)): %}
|
||||||
|
-- Note that this is also the location of the PID file, if you use it.
|
||||||
|
output.logdir = "{{ snort.log_dir }}"
|
||||||
|
|
||||||
|
-- Maybe add snort.log_type, 'fast', 'json' and 'full'?
|
||||||
|
-- Json would be best for reporting, see 'snort-mgr report' code.
|
||||||
|
-- alert_full = { file = true, }
|
||||||
|
|
||||||
|
alert_fast = {
|
||||||
|
-- bool alert_fast.file = false: output to alert_fast.txt instead of stdout
|
||||||
|
-- bool alert_fast.packet = false: output packet dump with alert
|
||||||
|
-- int alert_fast.limit = 0: set maximum size in MB before rollover (0 is unlimited) { 0:maxSZ }
|
||||||
|
file = true,
|
||||||
|
packet = false,
|
||||||
|
}
|
||||||
|
alert_json = {
|
||||||
|
-- bool alert_json.file = false: output to alert_json.txt instead of stdout
|
||||||
|
-- multi alert_json.fields = timestamp pkt_num proto pkt_gen pkt_len dir src_ap dst_ap rule action: selected fields will be output
|
||||||
|
-- int alert_json.limit = 0: set maximum size in MB before rollover (0 is unlimited) { 0:maxSZ }
|
||||||
|
-- string alert_json.separator = , : separate fields with this character sequence
|
||||||
|
file = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
normalizer = {
|
||||||
|
tcp = {
|
||||||
|
ips = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_policy = {
|
||||||
|
enable_type = true,
|
||||||
|
enable_signature = true,
|
||||||
|
rules = {
|
||||||
|
use = {
|
||||||
|
verdict = 'log',
|
||||||
|
enable_file_type = true,
|
||||||
|
enable_file_signature = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- To use openappid with snort, 'opkg install openappid' and enable in config.
|
||||||
|
{% if (int(snort.openappid)): %}
|
||||||
|
appid = {
|
||||||
|
log_stats = true,
|
||||||
|
app_detector_dir = '/usr/lib/openappid',
|
||||||
|
app_stats_period = 60,
|
||||||
|
}
|
||||||
|
{% endif %}
|
Loading…
Reference in a new issue