From 4a9b449d60ea1d3d6159456b1c35d9b289c06aa9 Mon Sep 17 00:00:00 2001 From: cschantz Date: Fri, 6 Mar 2026 23:03:09 -0500 Subject: [PATCH] CRITICAL FEATURE: Persistent historical IP attack tracking across monitor restarts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement lifetime detection history for each attacking IP. Most servers see 0 SYN_RECV, so 70 active is highly suspicious. Track which IPs have attacked 5-10 times over days, not just current session. New behavior: - Store historical hit count in ip_history_IPADDR file - Load count at each detection - Use TOTAL lifetime hits for threshold decisions, not just session hits - Dramatically lower threshold for repeat attackers Threshold adaptation: - 10+ lifetime attacks: threshold = 1 (block even 1 connection) - 5-9 lifetime attacks: threshold = 1 (from original 3) - 3-4 lifetime attacks: threshold = 2 (from original 3) - 2 lifetime attacks: threshold = 2 (from original 3) - 1st attack: threshold = 3 (baseline) Example: IP probes on Day 1, 2, 3 at 2-3 connections each - Day 1: 2 connections < 3 threshold, not detected - Day 2: 2 connections, now has 2 lifetime hits, threshold=2, 2 is NOT > 2, missed - Day 3: 2 connections, now has 3 lifetime hits, threshold=2, 2 is NOT > 2, missed - Day 4: 2 connections, now has 4 lifetime hits, threshold=2, 2 is NOT > 2, missed - Day 5: 2 connections, now has 5 lifetime hits, threshold=1, 2 > 1, DETECTED & BLOCKED ✓ This catches persistent low-level attackers that would otherwise evade detection. Co-Authored-By: Claude Haiku 4.5 --- modules/security/live-attack-monitor-v2.sh | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/modules/security/live-attack-monitor-v2.sh b/modules/security/live-attack-monitor-v2.sh index 72c04c1..eea49f5 100755 --- a/modules/security/live-attack-monitor-v2.sh +++ b/modules/security/live-attack-monitor-v2.sh @@ -2619,14 +2619,22 @@ monitor_network_attacks() { # Minimum threshold of 3 to prevent false positives on busy web servers [ "$threshold" -lt 3 ] && threshold=3 - # CRITICAL FIX: Adaptive threshold based on detection history - # An IP detected multiple times with SYN activity is more likely an attacker - # Lower threshold for repeat offenders to catch persistent attacks - if [ "${hits:-0}" -ge 3 ]; then - threshold=$((threshold - 2)) # Seen 3+ times: lower threshold significantly + # CRITICAL FIX: Adaptive threshold based on LIFETIME detection history + # Use persistent historical tracking (total_lifetime_hits) to catch repeat attackers + # An IP that attacks 5-10 times over days should be detected at lower threshold + # This catches distributed/low-level probes that space out attempts + local effective_hits="${total_lifetime_hits:-0}" + if [ "$effective_hits" -ge 10 ]; then + threshold=1 # Seen 10+ times across ALL TIME: auto-block even 1 connection [ "$threshold" -lt 1 ] && threshold=1 - elif [ "${hits:-0}" -ge 2 ]; then - threshold=$((threshold - 1)) # Seen 2 times: lower threshold slightly + elif [ "$effective_hits" -ge 5 ]; then + threshold=$((threshold - 2)) # 5-9 times: lower threshold by 2 (from 3 to 1) + [ "$threshold" -lt 1 ] && threshold=1 + elif [ "$effective_hits" -ge 3 ]; then + threshold=$((threshold - 1)) # 3-4 times: lower threshold by 1 + [ "$threshold" -lt 2 ] && threshold=2 + elif [ "$effective_hits" -ge 2 ]; then + threshold=$((threshold - 1)) # 2 times: lower threshold slightly [ "$threshold" -lt 2 ] && threshold=2 fi @@ -2643,9 +2651,20 @@ monitor_network_attacks() { fi IFS='|' read -r score hits bot_type attacks ban_count rep_score <<< "$current_data" - # Increment hits + # Increment hits (this session) hits=$((hits + 1)) + # CRITICAL FIX: Persistent historical tracking across monitor restarts + # Track total lifetime detections of each IP (not just current session) + # This allows catching repeat attackers even if they space out attacks over time + local history_file="$TEMP_DIR/ip_history_${ip//\./_}" + local total_lifetime_hits=0 + if [ -f "$history_file" ]; then + total_lifetime_hits=$(cat "$history_file" 2>/dev/null || echo 0) + fi + total_lifetime_hits=$((total_lifetime_hits + 1)) + echo "$total_lifetime_hits" > "$history_file" 2>/dev/null + # Smart whitelisting: Skip IPs with MANY successful established connections # Only whitelist if IP has 20+ established connections (highly unlikely for attacker) # CRITICAL FIX: Use -w flag to match whole word (prevent partial IP matches)