#!/bin/sh # Copyright (c) 2023-2024 Eric Fahlgren # SPDX-License-Identifier: GPL-2.0 # shellcheck disable=SC2039,SC2155 # "local" not defined in POSIX sh set -o nounset alias log='logger -s -t "snort-rules[$$]" -p "info"' 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? local oinkcode=$(uci -q get snort.snort.oinkcode) local conf_dir=$(uci -q get snort.snort.config_dir || echo "/etc/snort") local rules_dir="$conf_dir/rules" local data_dir=$(uci -q get snort.snort.temp_dir || echo "/var/snort.d") local data_tar="$data_dir/rules.tar.gz" local new_rules local rules_file local archive_loc # Make sure everything exists. [ -d "$data_dir" ] || mkdir -p "$data_dir" if $testing ; then log "Generating testing rules..." archive_loc="testing-rules" new_rules="$data_dir/$archive_loc" rm -fr "${new_rules:?}" mkdir -p "$new_rules" rules_file="$new_rules/testing.rules" { echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v4"; icode:0; itype: 8; sid:99010;)' echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v6"; icode:0; itype:33; sid:99011;)' echo 'alert icmp any any <> any any (msg:"TEST ALERT ICMP v6"; icode:0; itype:34; sid:99012;)' } >> "$rules_file" 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" archive_loc="snort3-community-rules" 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" # Non-community tar contains many "*.rules" file, we only care about # the one directory. archive_loc="rules" fi wget "$url" -O "$data_tar" 2>&1 | log || exit 1 old_rules="$data_dir/old.rules" if $backup; then rm -fr "${old_rules:?}" mkdir -p "$old_rules" for rules_file in "$rules_dir"/*; do # Before we overwrite with the new download. log "Stashing '$rules_file' to '$old_rules/'..." mv -f "$rules_file" "$old_rules/" done fi log "Unpacking '$data_tar'..." tar xzvof "$data_tar" "$archive_loc" -C "$data_dir" | log || exit 1 # Get rid of the non-rule files and aggregator. new_rules="$data_dir/$archive_loc" find "$new_rules" \( -iname 'includes.rules' -o ! -iname '*.rules' -type f \) -exec rm '{}' \; # Old unfinished experiment with diffing old and new rules. #for rules_file in "$new_rules"/*; do #blah blah #if [ -e "$old_rules" ] && ! cmp -s "$new_rules" "$old_rules" ; then # diff "$new_rules" "$old_rules" 2>&1 | log #fi fi mkdir -p "$conf_dir" rm -fr "${rules_dir:?}" if $persist; then mv -f "$new_rules" "$rules_dir" else ln -s "$new_rules" "$rules_dir" fi log "Snort rules loaded, restart snort now." } #------------------------------------------------------------------------------- testing=false persist=false backup=false usage() { local msg="$1" [ -n "$msg" ] && printf "ERROR: %s\n\n" "$msg" cat <