#!/bin/sh set -eu NO_RELOAD=false if [ "${1:-}" = "--no-reload" ]; then NO_RELOAD=true fi if ! command -v suricata-update >/dev/null 2>&1; then cd "$(dirname "$0")/.." if command -v docker >/dev/null 2>&1; then exec docker compose exec -T ids /opt/ids/scripts/update-rules.sh "$@" fi echo "suricata-update is not installed; run this script inside the IDS container" >&2 exit 2 fi STATE_DIR="${SURICATA_STATE_DIR:-/data/suricata}" PERSIST_LIB_DIR="${SURICATA_PERSIST_LIB_DIR:-/data/lib/suricata}" RULES="${PERSIST_LIB_DIR}/rules/suricata.rules" SURICATA_CONFIG="${SURICATA_CONFIG:-/etc/suricata/suricata.yaml}" SURICATA_OUTPUT_CONFIG="${SURICATA_OUTPUT_CONFIG:-/opt/ids/suricata/ids-output.yaml}" SURICATA_HOME_NET="${SURICATA_HOME_NET:-[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]}" SURICATA_EXTRA_RULES_GLOB="${SURICATA_EXTRA_RULES_GLOB:-/data/suricata/*.rules}" SURICATA_THRESHOLD_CONFIG="${SURICATA_THRESHOLD_CONFIG:-/data/suricata/threshold.config}" mkdir -p "$STATE_DIR" "$PERSIST_LIB_DIR/rules" for name in disable.conf enable.conf modify.conf threshold.config; do [ -f "$STATE_DIR/$name" ] || : > "$STATE_DIR/$name" done TMP_DIR="$(mktemp -d /tmp/suricata-rule-update.XXXXXX)" BACKUP="$TMP_DIR/suricata.rules.previous" VALIDATE_LOG="$TMP_DIR/validate-log" mkdir -p "$VALIDATE_LOG" HAD_RULES=false if [ -s "$RULES" ]; then cp -p "$RULES" "$BACKUP" HAD_RULES=true fi cleanup() { rm -rf "$TMP_DIR" } trap cleanup EXIT HUP INT TERM restore_previous_rules() { if [ "$HAD_RULES" = "true" ]; then cp -p "$BACKUP" "$RULES" else rm -f "$RULES" fi } echo "[rules] downloading enabled feeds with suricata-update" if ! suricata-update \ -D "$PERSIST_LIB_DIR" \ --disable-conf="$STATE_DIR/disable.conf" \ --enable-conf="$STATE_DIR/enable.conf" \ --modify-conf="$STATE_DIR/modify.conf"; then echo "[rules] download/update failed; restoring previous rules" >&2 restore_previous_rules exit 10 fi [ -f "$RULES" ] || : > "$RULES" echo "[rules] validating downloaded rules before activation" if ! suricata -T \ -c "$SURICATA_CONFIG" \ --include "$SURICATA_OUTPUT_CONFIG" \ -l "$VALIDATE_LOG" \ -s "$SURICATA_EXTRA_RULES_GLOB" \ --set "vars.address-groups.HOME_NET=$SURICATA_HOME_NET" \ --set "threshold-file=$SURICATA_THRESHOLD_CONFIG" \ --set "default-rule-path=$PERSIST_LIB_DIR/rules" \ --set "app-layer.protocols.tls.ja3-fingerprints=yes" \ --set "app-layer.protocols.tls.ja4-fingerprints=yes" \ --set "app-layer.protocols.ssh.hassh=yes"; then echo "[rules] validation failed; restoring previous known-good rules" >&2 restore_previous_rules exit 11 fi chown suricata:suricata "$RULES" chmod 0644 "$RULES" if [ "$NO_RELOAD" = "true" ]; then echo "Rules downloaded, validated and installed; reload skipped" exit 0 fi PID="" if [ -f /run/suricata.pid ]; then PID="$(cat /run/suricata.pid)" fi if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then kill -USR2 "$PID" echo "Rules downloaded, validated and installed; live reload requested for Suricata PID $PID" else echo "Rules downloaded, validated and installed; Suricata is not currently running" fi