From 26c69175cddf2efda5c5c574f94e8d48ef510277 Mon Sep 17 00:00:00 2001 From: cschantz Date: Wed, 24 Dec 2025 19:24:35 -0500 Subject: [PATCH] Add full reputation tracking and auto-blocking for SYN flood attacks CRITICAL FIX for active SYN flood attacks PROBLEM: - SYN_RECV connection monitoring only logged events - NO reputation scoring for active SYN flood attackers - NO auto-blocking even with 100+ simultaneous connections - User report: "server with active attack cant auto block ips" ROOT CAUSE: SYN_RECV monitoring (lines 2225-2247) only logged to recent_events without updating IP_DATA or reputation database. This meant: - IPs with massive connection counts got no reputation score - Auto-mitigation engine never saw these IPs - Manual blocking was the only option SOLUTION IMPLEMENTED: 1. Full IP Reputation Tracking (lines 2243-2317) - Reads/updates IP reputation file (ip_X_X_X_X) - Increments hit counter for each detection - Adds "SYN_FLOOD" to attack list 2. Progressive Scoring by Connection Count - 20-50 connections: +15 points - 50-100 connections: +25 points - 100+ connections: +40 points per hit - Can quickly reach score 100 for instant blocking 3. Advanced Intelligence Integration - Attack velocity tracking (rapid successive hits) - Attack diversity bonuses (multiple attack vectors) - Subnet attack detection (coordinated DDoS) - Timing pattern analysis (botnet identification) 4. Reputation Database Logging (line 2325) - Logs to IP reputation DB: flag_ip_attack() - Persistent tracking across sessions - Historical attack data preserved 5. Auto-Mitigation Integration (line 2317) - Writes IP data to file for auto_mitigation_engine() - Stores block reasons for detailed logging - Enables automatic blocking when score >= 80 - INSTANT blocking when score = 100 ATTACK PROGRESSION EXAMPLE: - Detection 1 (50 conns): Score 25 - Detection 2 (75 conns): Score 25 + 25 + bonuses = ~60 - Detection 3 (100 conns): Score 60 + 40 + bonuses = 100 - RESULT: INSTANT_BLOCK triggered automatically This restores full auto-blocking for network-layer attacks. --- modules/security/live-attack-monitor.sh | 110 +++++++++++++++++++++--- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/modules/security/live-attack-monitor.sh b/modules/security/live-attack-monitor.sh index c3dbb7f..535492d 100755 --- a/modules/security/live-attack-monitor.sh +++ b/modules/security/live-attack-monitor.sh @@ -2224,24 +2224,114 @@ monitor_network_attacks() { if command -v ss &>/dev/null; then # Count SYN_RECV connections per IP (sign of SYN flood) while read -r ip count; do - if [ "$count" -gt 20 ]; then # More than 20 SYN_RECV connections + # Skip local/private IPs first + if [[ "$ip" =~ ^127\. ]] || \ + [[ "$ip" =~ ^10\. ]] || \ + [[ "$ip" =~ ^192\.168\. ]] || \ + [[ "$ip" =~ ^172\.(1[6-9]|2[0-9]|3[01])\. ]]; then + continue + fi + + # Track connection count for this IP + CONNECTION_COUNT[$ip]=$count + + if [ "$count" -gt 20 ]; then # More than 20 SYN_RECV connections = DDoS + # Only process once per detection window if [ -z "${ALERT_SENT[$ip]}" ]; then ALERT_SENT[$ip]=1 - # Skip local/private IPs - if [[ "$ip" =~ ^127\. ]] || \ - [[ "$ip" =~ ^10\. ]] || \ - [[ "$ip" =~ ^192\.168\. ]] || \ - [[ "$ip" =~ ^172\.(1[6-9]|2[0-9]|3[01])\. ]]; then - continue + # Update IP reputation via file (subshell can't access IP_DATA array) + local ip_file="$TEMP_DIR/ip_${ip//\./_}" + local current_data="0|0|human||0|0" + if [ -f "$ip_file" ]; then + current_data=$(cat "$ip_file") + fi + IFS='|' read -r score hits bot_type attacks ban_count rep_score <<< "$current_data" + + # Increment hits + hits=$((hits + 1)) + + # Record attack intelligence + record_attack_timestamp "$ip" + record_attack_vector "$ip" "NETWORK" + track_subnet_attack "$ip" + + # Add SYN_FLOOD to attacks if not already present + if [[ ! "$attacks" =~ SYN_FLOOD ]]; then + [ -z "$attacks" ] && attacks="SYN_FLOOD" || attacks="${attacks},SYN_FLOOD" fi - # Log high connection count + # Progressive scoring based on connection count + # 20-50 conns: +15 pts, 50-100: +25 pts, 100+: +40 pts + local conn_bonus=0 + if [ "$count" -ge 100 ]; then + conn_bonus=40 + elif [ "$count" -ge 50 ]; then + conn_bonus=25 + else + conn_bonus=15 + fi + + # First hit or add to existing score + if [ "${hits:-0}" -eq 1 ]; then + score=$conn_bonus + else + score=$((score + conn_bonus)) + fi + + # Apply advanced intelligence bonuses + local block_reasons="" + local velocity_data=$(calculate_attack_velocity "$ip") + IFS='|' read -r vel_count vel_bonus vel_reason <<< "$velocity_data" + [ "$vel_bonus" -gt 0 ] && score=$((score + vel_bonus)) && block_reasons="${vel_reason}" + + local div_data=$(calculate_diversity_bonus "$ip") + IFS='|' read -r div_count div_bonus div_reason <<< "$div_data" + if [ "$div_bonus" -gt 0 ]; then + score=$((score + div_bonus)) + [ -n "$block_reasons" ] && block_reasons="${block_reasons}+" || block_reasons="" + block_reasons="${block_reasons}${div_reason}" + fi + + local subnet_bonus=$(calculate_subnet_bonus "$ip") + if [ "$subnet_bonus" -gt 0 ]; then + score=$((score + subnet_bonus)) + local context_reason="SUBNET_ATTACK" + [ -n "$block_reasons" ] && block_reasons="${block_reasons}+" || block_reasons="" + block_reasons="${block_reasons}${context_reason}" + fi + + # Detect timing patterns + local timing_result=$(detect_timing_pattern "$ip") + IFS='|' read -r timing_type timing_bonus timing_reason <<< "$timing_result" + if [ "$timing_bonus" -gt 0 ]; then + score=$((score + timing_bonus)) + [ -n "$block_reasons" ] && block_reasons="${block_reasons}+" || block_reasons="" + block_reasons="${block_reasons}${timing_reason}" + fi + + # Cap at 100 + [ "$score" -gt 100 ] && score=100 + + # Write to file for main process + echo "$score|$hits|$bot_type|$attacks|$ban_count|$rep_score" > "$ip_file" + + # Store block reasons for auto-mitigation + if [ -n "$block_reasons" ]; then + echo "$block_reasons" > "$TEMP_DIR/block_reason_${ip//\./_}" + fi + + # Log to reputation DB + flag_ip_attack "$ip" "SYN_FLOOD" 0 "SYN flood: $count connections" >/dev/null 2>&1 & + + # Log event with reputation score local time_str=$(date +"%H:%M:%S") - echo -e "${HIGH_COLOR}[${time_str}] $ip | 💥HIGH_CONN_COUNT | $count SYN_RECV connections (possible DDoS)${NC}" >> "$TEMP_DIR/recent_events" + local level=$(get_threat_level "$score") + local color=$(get_threat_color "$level") + echo -e "${color}[${time_str}] $ip | Score:$score [$level] | 💥SYN_FLOOD | $count SYN_RECV connections${NC}" >> "$TEMP_DIR/recent_events" fi else - # Reset alert if connections drop + # Reset alert if connections drop below threshold unset ALERT_SENT[$ip] fi done < <(ss -tn state syn-recv 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | sort | uniq -c | awk '$1 > 5 {print $2, $1}')