102 lines
3.1 KiB
Bash
Executable File
102 lines
3.1 KiB
Bash
Executable File
#!/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
|