2 # Copyright (c) 2023 Eric Fahlgren <eric.fahlgren@gmail.com>
3 # SPDX-License-Identifier: GPL-2.0
4 # shellcheck disable=SC2039,SC2155 # "local" not defined in POSIX sh
7 MAIN
="/usr/share/snort/main.uc"
8 CONF_DIR
="/var/snort.d"
9 CONF
="${CONF_DIR}/snort_conf.lua"
15 [ ! -e "$CONF_DIR" ] && mkdir
"$CONF_DIR"
16 [ -e /dev
/stdin
] && STDIN
=/dev
/stdin || STDIN
=/proc
/self
/fd
/0
17 [ -e /dev
/stdout
] && STDOUT
=/dev
/stdout || STDOUT
=/proc
/self
/fd
/1
18 [ -t 2 ] && export TTY
=1
21 [ -n "$QUIET" ] ||
echo "$@" >&2
27 # From https://forum.openwrt.org/t/snort-3-nfq-with-ips-mode/161172
28 # https://blog.snort.org/2016/08/running-snort-on-commodity-hardware.html
29 # Not needed when running the nfq daq as defragmentation is done by the kernel.
32 local filter_method
=$
(uci
-q get snort.snort.method
)
33 if [ "$filter_method" = "afpacket" ]; then
34 local wan
=$
(uci get snort.snort.interface
)
35 if [ -n "$wan" ] && ethtool
-k "$wan" |
grep -q -E '(tcp-segmentation-offload|receive-offload): on' ; then
36 ethtool
-K "$wan" gro off lro off tso off
2> /dev
/null
37 log
"Disabled gro, lro and tso on '$wan' using ethtool."
43 for table_type
in 'inet' 'netdev'; do
44 nft list tables |
grep -q "${table_type} snort" && nft delete table
"${table_type}" snort
49 if [ "$(uci -q get snort.snort.method)" = "nfq" ]; then
50 print nftables | nft
$VERBOSE -f $STDIN
51 [ -n "$VERBOSE" ] && nft list table inet snort
56 # Generates all the configuration, then reports the config file for snort.
57 # Does NOT generate the rules file, you'll need to do 'update-rules' first.
58 local log_dir
=$
(uci get snort.snort.log_dir
)
59 [ ! -e "$log_dir" ] && mkdir
-p "$log_dir"
67 # Merely cleans up after.
69 [ -e "$CONF" ] && rm "$CONF"
73 /usr
/bin
/snort-rules
$TESTING
77 # '$1' is file type to generate, one of:
78 # config, snort or nftables
79 TYPE
=$1 utpl
-S "$MAIN"
83 local manual
=$
(uci get snort.snort.manual
)
84 [ "$manual" = 1 ] && return 0
86 [ -n "$QUIET" ] && OUT
=/dev
/null || OUT
=$STDOUT
88 if [ -n "$VERBOSE" ]; then
96 local test_conf
="${CONF_DIR}/test_conf.lua"
97 _SNORT_WITHOUT_RULES
="$no_rules" print snort
> "${test_conf}" || die
"Errors during generation of snort config."
98 if $PROG -T $warn -c "${test_conf}" 2> $OUT ; then
101 die
"Errors in snort config tests. Examine ${test_conf} for issues."
104 if [ "$(uci -q get snort.snort.method)" = "nfq" ]; then
105 local test_nft
="${CONF_DIR}/test_conf.nft"
106 print nftables
> "${test_nft}" || die
"Errors during generation of nftables config."
107 if nft
$VERBOSE --check -f "${test_nft}" ; then
110 die
"Errors in nftables config tests. Examine ${test_nft} for issues."
117 # Reported IPs have source port stripped, but destination port (if any)
122 # 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
124 # same event in alert_json (single line broken for clarity):
125 # { "timestamp" : "08/30-11:39:57.639021", "pkt_num" : 5366, "proto" : "ICMP", "pkt_gen" : "raw",
126 # "pkt_len" : 60, "dir" : "C2S", "src_ap" : "10.1.1.186:0", "dst_ap" : "10.1.1.20:0",
127 # "rule" : "1:382:11", "action" : "allow" }
129 # Second part of "rule", 382, is "sid" in ruleset, suffixing 11 is "rev".
130 # grep '\bsid:382\b' /etc/snort/rules/snort.rules (again, single line broken for clarity):
131 # alert icmp $EXTERNAL_NET any -> $HOME_NET any ( msg:"PROTOCOL-ICMP PING Windows";
132 # itype:8; content:"abcdefghijklmnop",depth 16; metadata:ruleset community;
133 # classtype:misc-activity; sid:382; rev:11; )
135 # Not sure where the prefixing 1 comes from.
137 local logging
=$
(uci get snort.snort.logging
)
138 local log_dir
=$
(uci get snort.snort.log_dir
)
141 if [ "$logging" = 0 ]; then
142 die
"Logging is not enabled in snort config."
145 [ "$NLINES" = 0 ] && output
="cat" || output
="head -n $NLINES"
147 local msg src dst dir
148 tmp
="/tmp/snort.report.$$"
149 for file in "${log_dir}"/*alert_json.txt
; do
150 while read -r line
; do
151 eval $
(jsonfilter
-s "$line" -e 'msg=$.msg' -e 'src=$.src_ap' -e 'dst=$.dst_ap' -e 'dir=$.dir')
152 src
=$
(echo "$src" |
sed 's/:.*$//') # Delete all source ports.
153 dst
=$
(echo "$dst" |
sed 's/:0$//') # Delete unspecified dest port.
154 echo "$msg#$src#$dst#$dir"
156 done |
grep -i "$pattern" > "$tmp"
158 echo "Events involving ${pattern:-all IPs}"
159 n_incidents
="$(wc -l < $tmp)"
160 lines
=$
(sort "$tmp" |
uniq -c |
sort -nr \
161 |
awk -F'#' '{printf "%-80s %s %-13s -> %s\n", $1, $4, $2, $3}')
162 echo "$lines" |
$output
163 n_lines
=$
(echo "$lines" |
wc -l)
164 [ "$NLINES" -gt 0 ] && [ "$NLINES" -lt "$n_lines" ] && echo " ... Only showing $NLINES of $n_lines most frequent incidents."
165 printf "%7d total incidents\n" "$n_incidents"
170 echo -n 'snort is ' ; service snort status
171 ps w |
grep -E 'PID|snort' |
grep -v grep
175 while [ -n "$1" ]; do
208 QUIET
=1 check || die
"The generated snort lua configuration contains errors, not restarting. Run 'snort-mgr check'"
231 -n = show only NLINES of output
236 $0 [-v] [-q] setup|teardown|resetup
238 Normally only used internally by init scripts to manage the generation
239 of configuration files and any needed firewall rules. None of these
240 modify the snort rules in any way (see 'update-rules').
241 setup = generates snort config, sets up firewall.
242 teardown = removes any firewall rules.
243 resetup = shorthand for teardown and then setup.
246 $0 [-n lines] report [pattern]
248 Report on incidents. Note this is somewhat experimental, so suggested
249 improvements are quite welcome.
250 pattern = A case-insensitive grep pattern used to filter output.
254 Download and install the snort ruleset. Testing mode generates a canned
255 rule that matches IPv4 ping requests. A typical test scenario might look
258 > snort-mgr -t update-rules
259 > /etc/init.d/snort start
261 > logread -e "TEST ALERT"
264 $0 print config|snort|nftables
266 Print the rendered file contents.
267 config = Display contents of /etc/config/snort, but with all values and
268 descriptions. Missing values shown with defaults.
269 snort = The snort configuration file, which is a lua script.
270 nftables = The nftables script used to define the input queues when using
272 help = Display config file help.
277 Test the rendered config using snort's check mode without
278 applying it to the running system.
283 Print the nfq counter values and blah blah blah