Fix auto-blocking: Use file-based IPC for background process

CRITICAL FIX: Auto-mitigation engine was not blocking IPs

Root Cause:
- Auto-mitigation ran in subshell: ( ... ) &
- Subshells cannot access parent's associative arrays (IP_DATA)
- Engine was looping through empty array, blocking nothing
- This is why IP with score 100 sat for minutes without blocking

Solution:
- Main loop writes IP_DATA to $TEMP_DIR/ip_data every 2 seconds
- Auto-mitigation reads from file instead of array
- Tracks BLOCKED_THIS_SESSION to prevent duplicates
- Uses file-based counter for TOTAL_BLOCKS

How It Works Now:
1. Main process: Updates IP_DATA array in memory
2. Main loop: Writes IP_DATA to temp file every refresh (2 sec)
3. Auto-mitigation (background): Reads file every 10 sec
4. Auto-mitigation: Blocks IPs with score >= 80
5. Auto-mitigation: Writes to total_blocks file
6. Main loop: Reads total_blocks to update display

Performance:
- File write every 2 sec (100-500 bytes, negligible)
- File read every 10 sec by background process
- No CSF reload needed (csf -td is instant)

This finally enables automatic blocking at score >= 80
This commit is contained in:
cschantz
2025-11-14 20:02:12 -05:00
parent b153e9dc1a
commit 77cd46ac10
+33 -11
View File
@@ -53,6 +53,7 @@ mkdir -p "$TEMP_DIR" "$SNAPSHOT_DIR" 2>/dev/null
touch "$TEMP_DIR/recent_events" touch "$TEMP_DIR/recent_events"
touch "$TEMP_DIR/ip_data" touch "$TEMP_DIR/ip_data"
echo "0" > "$TEMP_DIR/event_counter" echo "0" > "$TEMP_DIR/event_counter"
echo "0" > "$TEMP_DIR/total_blocks"
# Save snapshot of IP data (for persistence across restarts) # Save snapshot of IP data (for persistence across restarts)
save_snapshot() { save_snapshot() {
@@ -1887,17 +1888,27 @@ detect_distributed_attacks() {
auto_mitigation_engine() { auto_mitigation_engine() {
# Run in background, check every 10 seconds # Run in background, check every 10 seconds
( (
# Track already blocked IPs in this session
declare -A BLOCKED_THIS_SESSION
while true; do while true; do
sleep 10 sleep 10
# Auto-block IPs that reach CRITICAL threshold # Read current IP data from snapshot file (updated by main process)
for ip in "${!IP_DATA[@]}"; do if [ -f "$TEMP_DIR/ip_data" ]; then
IFS='|' read -r score hits bot_type attacks ban_count rep_score <<< "${IP_DATA[$ip]}" while IFS='=' read -r ip data; do
[ -z "$ip" ] && continue
IFS='|' read -r score hits bot_type attacks ban_count rep_score <<< "$data"
# Auto-block at score >= 80 (CRITICAL) # Auto-block at score >= 80 (CRITICAL)
if [ "$score" -ge 80 ]; then if [ "$score" -ge 80 ]; then
# Check if already blocked # Skip if already blocked in this session
if ! is_ip_blocked "$ip" 2>/dev/null; then [ -n "${BLOCKED_THIS_SESSION[$ip]}" ] && continue
# Mark as blocked to prevent duplicate attempts
BLOCKED_THIS_SESSION[$ip]=1
# Auto-block # Auto-block
local time_str=$(date +"%H:%M:%S") local time_str=$(date +"%H:%M:%S")
echo -e "${CRITICAL_COLOR}[${time_str}] AUTO_BLOCK | $ip | Score:$score | ${attacks}${NC}" >> "$TEMP_DIR/recent_events" echo -e "${CRITICAL_COLOR}[${time_str}] AUTO_BLOCK | $ip | Score:$score | ${attacks}${NC}" >> "$TEMP_DIR/recent_events"
@@ -1910,16 +1921,15 @@ auto_mitigation_engine() {
fi fi
# Block for 1 hour with detailed reason # Block for 1 hour with detailed reason
block_ip_temporary "$ip" 1 "$block_reason" >/dev/null 2>&1 & block_ip_temporary "$ip" 1 "$block_reason" &
# Update ban count and total blocks # Increment total blocks counter
ban_count=$((ban_count + 1)) local current_total=$(cat "$TEMP_DIR/total_blocks" 2>/dev/null || echo "0")
TOTAL_BLOCKS=$((TOTAL_BLOCKS + 1)) echo $((current_total + 1)) > "$TEMP_DIR/total_blocks"
IP_DATA[$ip]="$score|$hits|$bot_type|$attacks|$ban_count|$rep_score"
fi fi
done < "$TEMP_DIR/ip_data"
fi fi
done done
done
) & ) &
} }
@@ -1962,6 +1972,18 @@ while true; do
draw_live_feed draw_live_feed
draw_quick_actions draw_quick_actions
# Write IP data to temp file for auto-mitigation engine (every loop)
{
for ip in "${!IP_DATA[@]}"; do
echo "$ip=${IP_DATA[$ip]}"
done
} > "$TEMP_DIR/ip_data" 2>/dev/null
# Update total blocks from file
if [ -f "$TEMP_DIR/total_blocks" ]; then
TOTAL_BLOCKS=$(cat "$TEMP_DIR/total_blocks")
fi
# Periodic cleanup (every 50 loops = ~100 seconds) # Periodic cleanup (every 50 loops = ~100 seconds)
((LOOP_COUNT++)) ((LOOP_COUNT++))
if [ $((LOOP_COUNT % 50)) -eq 0 ]; then if [ $((LOOP_COUNT % 50)) -eq 0 ]; then