From 63f84b6d043a7c45da8e528e75764ba58ef6114a Mon Sep 17 00:00:00 2001 From: rafapolo Date: Thu, 15 Oct 2026 09:50:40 +0200 Subject: [PATCH] fix: ignore helvetiscan and ownerless ephemeral udp sockets in security monitor --- security-monitor.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/security-monitor.sh b/security-monitor.sh index b441803..f3e1d97 100755 --- a/security-monitor.sh +++ b/security-monitor.sh @@ -85,9 +85,17 @@ hash_files() { # Listening sockets, normalised: pid/fd stripped (they change on every restart) and duplicate # process entries collapsed (nginx reports one entry per worker, so a worker-count change from # a routine reload would otherwise look like a socket change). +# UDP sockets of IGNORE_UDP_PROCS are dropped: helvetiscan (a known, trusted scanner) opens and +# closes dozens of random-port UDP sockets per second, so every tick alerted on lines like +# "UNCONN *:13786 helvetiscan". Its TCP listeners are still tracked. Ownerless UDP sockets on a +# port >= 1024 are dropped too: they're the same scanner's sockets caught mid-teardown, already +# detached from the process (sequential inodes, a new port every second). Ownerless sockets on +# privileged ports (e.g. the DHCP client on :68) stay in the snapshot. +IGNORE_UDP_PROCS="${IGNORE_UDP_PROCS:-helvetiscan}" listening_sockets() { local flag="$1" - ss -"$flag"lnp 2>/dev/null | tail -n +2 | awk ' + ss -"$flag"lnp 2>/dev/null | tail -n +2 | awk -v flag="$flag" -v ignprocs="$IGNORE_UDP_PROCS" ' + BEGIN { n = split(ignprocs, ip, /[ ,]+/); for (i = 1; i <= n; i++) if (ip[i] != "") ign[ip[i]] = 1 } { proc = $6 gsub(/,?(pid|fd)=[0-9]+/, "", proc) @@ -102,6 +110,12 @@ listening_sockets() { out = (out == "" ? parts[i] : out "," parts[i]) } } + if (flag == "u") { + port = $4; sub(/.*:/, "", port) + if (out == "" && port + 0 >= 1024) next + n = split(out, names, ",") + for (i = 1; i <= n; i++) if (names[i] in ign) next + } print $1, $4, out }' | sort -u }