Add auto-blocking for distributed attacks

When 5+ IPs perform same attack type (RCE, SQL_INJECTION, XSS, PATH_TRAVERSAL, BRUTEFORCE) within 2 minutes:
- Block all individual attacking IPs immediately via IPset
- If 25+ IPs from same /24 subnet, block entire subnet

Uses batch_block_ips() for efficient IPset operations.
All blocking is kernel-level via IPset (no CSF commands).
This commit is contained in:
cschantz
2026-01-06 21:55:58 -05:00
parent 46fad6107d
commit 7f2d236c49
+48 -16
View File
@@ -3263,34 +3263,66 @@ detect_distributed_attacks() {
# Check for same attack type from 5+ different IPs (use awk for performance)
for attack_type in RCE SQL_INJECTION XSS PATH_TRAVERSAL BRUTEFORCE; do
# Single AWK pass to count attacks and unique IPs
local result=$(echo "$recent" | awk -v pattern="$attack_type" '
# Single AWK pass to extract all attacking IPs
local attacking_ips=$(echo "$recent" | awk -v pattern="$attack_type" '
$0 ~ pattern {
count++
# Extract IP (first field matching IP pattern)
for(i=1; i<=NF; i++) {
if($i ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
ips[$i]=1
print $i
break
}
}
}
END {
print count "|" length(ips)
}
')
IFS='|' read -r attack_count unique_ips <<< "$result"
' | sort -u)
if [ "${attack_count:-0}" -ge 5 ]; then
# Count unique IPs
local unique_ips=$(echo "$attacking_ips" | grep -c "^[0-9]" 2>/dev/null || echo "0")
if [ "$unique_ips" -ge 5 ]; then
# Distributed attack detected!
local time_str=$(date +"%H:%M:%S")
echo -e "${CRITICAL_COLOR}[${time_str}] DISTRIBUTED_ATTACK | ${attack_type} from ${unique_ips} IPs in last 2min | Possible botnet${NC}" >> "$TEMP_DIR/recent_events"
if [ "${unique_ips:-0}" -ge 5 ]; then
# Distributed attack detected!
local time_str=$(date +"%H:%M:%S")
# Mark in a file for Quick Actions to see
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks"
# BLOCK ALL INDIVIDUAL IPs IN THE ATTACK
local -a batch_ips=()
while IFS= read -r ip; do
[ -n "$ip" ] && batch_ips+=("$ip")
done <<< "$attacking_ips"
if [ ${#batch_ips[@]} -gt 0 ]; then
batch_block_ips "${batch_ips[@]}"
echo -e "${CRITICAL_COLOR}[${time_str}] DISTRIBUTED_ATTACK | ${attack_type} from ${unique_ips} IPs | BLOCKED ALL${NC}" >> "$TEMP_DIR/recent_events"
fi
# Check for subnet-level coordination (25+ IPs from same /24)
declare -A subnet_counts
while IFS= read -r ip; do
[ -z "$ip" ] && continue
local subnet="${ip%.*}" # Get /24 subnet (bash built-in)
((subnet_counts[$subnet]++))
done <<< "$attacking_ips"
# Block entire subnets with 25+ attacking IPs
for subnet in "${!subnet_counts[@]}"; do
local subnet_ip_count=${subnet_counts[$subnet]}
if [ "$subnet_ip_count" -ge 25 ]; then
local subnet_cidr="${subnet}.0/24"
# Check if not already blocked
if ! grep -q "^${subnet_cidr}\$" "$TEMP_DIR/blocked_subnets" 2>/dev/null; then
echo "$subnet_cidr" >> "$TEMP_DIR/blocked_subnets"
# Add to IPset (kernel-level blocking)
if [ "$IPSET_AVAILABLE" -eq 1 ]; then
ipset add "$IPSET_NAME" "$subnet_cidr" -exist 2>/dev/null
echo -e "${CRITICAL_COLOR}[${time_str}] SUBNET_BLOCK | $subnet_cidr | ${attack_type} from ${subnet_ip_count} IPs | BLOCKED${NC}" >> "$TEMP_DIR/recent_events"
fi
fi
fi
done
# Mark in a file for Quick Actions to see
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks"
fi
done
fi