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:
@@ -3263,35 +3263,67 @@ detect_distributed_attacks() {
|
|||||||
|
|
||||||
# Check for same attack type from 5+ different IPs (use awk for performance)
|
# 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
|
for attack_type in RCE SQL_INJECTION XSS PATH_TRAVERSAL BRUTEFORCE; do
|
||||||
# Single AWK pass to count attacks and unique IPs
|
# Single AWK pass to extract all attacking IPs
|
||||||
local result=$(echo "$recent" | awk -v pattern="$attack_type" '
|
local attacking_ips=$(echo "$recent" | awk -v pattern="$attack_type" '
|
||||||
$0 ~ pattern {
|
$0 ~ pattern {
|
||||||
count++
|
|
||||||
# Extract IP (first field matching IP pattern)
|
# Extract IP (first field matching IP pattern)
|
||||||
for(i=1; i<=NF; i++) {
|
for(i=1; i<=NF; i++) {
|
||||||
if($i ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
|
if($i ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
|
||||||
ips[$i]=1
|
print $i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END {
|
' | sort -u)
|
||||||
print count "|" length(ips)
|
|
||||||
}
|
|
||||||
')
|
|
||||||
IFS='|' read -r attack_count unique_ips <<< "$result"
|
|
||||||
|
|
||||||
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
|
if [ "${unique_ips:-0}" -ge 5 ]; then
|
||||||
# Distributed attack detected!
|
# Distributed attack detected!
|
||||||
local time_str=$(date +"%H:%M:%S")
|
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"
|
|
||||||
|
# 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
|
# Mark in a file for Quick Actions to see
|
||||||
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks"
|
echo "${attack_type}|${unique_ips}|$(date +%s)" >> "$TEMP_DIR/distributed_attacks"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user