CRITICAL FIX: Resolve subshell data loss preventing auto-blocking
Problem:
- Scores showing 100 in display but IPs NOT being auto-blocked
- HTTP/SSH/network monitoring run in subshells (pipe/background processes)
- IP_DATA array updates in subshells invisible to parent process
- Auto-mitigation engine reading stale ip_data file with score=0
- Result: SUSPICIOUS_UA and other attacks never triggering blocks
Root Cause:
```bash
tail -F logs | while read line; do
IP_DATA[$ip]=100 # Updates in SUBSHELL - parent never sees it!
done
```
Solution:
1. Added write_ip_data_to_file() with flock-based locking
2. Every IP_DATA update now writes directly to ip_data file
3. Auto-mitigation engine can now see real-time scores
4. Fixed in 8 locations:
- update_ip_intelligence (main scoring)
- HTTP log monitoring (ET attacks)
- AbuseIPDB reputation boost (3 levels)
- cPHulk monitoring
- SYN flood detection
- Port scan detection
Testing:
- SUSPICIOUS_UA reaching score 100 will now auto-block
- All attack types properly trigger mitigation
- File locking prevents race conditions
- Background writes prevent blocking main loop
This fixes the #1 reported issue where attacks showed critical
scores but were never blocked.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -305,6 +305,32 @@ get_ip_intelligence() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Write IP data directly to file (for cross-process communication)
|
||||
write_ip_data_to_file() {
|
||||
local ip="$1"
|
||||
local data="$2"
|
||||
|
||||
# Use flock for thread-safe writes (with timeout to prevent deadlocks)
|
||||
(
|
||||
flock -w 2 200 || return 1
|
||||
|
||||
# Read existing data
|
||||
local temp_file="$TEMP_DIR/ip_data.tmp"
|
||||
cp "$TEMP_DIR/ip_data" "$temp_file" 2>/dev/null || touch "$temp_file"
|
||||
|
||||
# Remove old entry for this IP (if exists)
|
||||
grep -v "^${ip}=" "$temp_file" > "${temp_file}.new" 2>/dev/null || true
|
||||
|
||||
# Add new entry
|
||||
echo "${ip}=${data}" >> "${temp_file}.new"
|
||||
|
||||
# Atomic replacement
|
||||
mv "${temp_file}.new" "$TEMP_DIR/ip_data"
|
||||
rm -f "$temp_file"
|
||||
|
||||
) 200>"$TEMP_DIR/ip_data.lock"
|
||||
}
|
||||
|
||||
# Update IP intelligence
|
||||
update_ip_intelligence() {
|
||||
local ip="$1"
|
||||
@@ -343,6 +369,8 @@ update_ip_intelligence() {
|
||||
local new_score=$((old_score + 30))
|
||||
[ "${new_score:-0}" -gt 100 ] && new_score=100
|
||||
IP_DATA[$ip]="$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep"
|
||||
# Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep" 2>/dev/null
|
||||
elif [ "${abuse_conf:-0}" -ge 50 ]; then
|
||||
# Medium confidence - add 15 points
|
||||
local current_data="${IP_DATA[$ip]}"
|
||||
@@ -350,6 +378,8 @@ update_ip_intelligence() {
|
||||
local new_score=$((old_score + 15))
|
||||
[ "${new_score:-0}" -gt 100 ] && new_score=100
|
||||
IP_DATA[$ip]="$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep"
|
||||
# Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep" 2>/dev/null
|
||||
fi
|
||||
|
||||
# High-risk country adds 5 points
|
||||
@@ -359,6 +389,8 @@ update_ip_intelligence() {
|
||||
local new_score=$((old_score + 5))
|
||||
[ "${new_score:-0}" -gt 100 ] && new_score=100
|
||||
IP_DATA[$ip]="$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep"
|
||||
# Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$new_score|$old_hits|$old_bot|$old_attacks|$old_ban|$old_rep" 2>/dev/null
|
||||
fi
|
||||
) &
|
||||
fi
|
||||
@@ -453,6 +485,10 @@ update_ip_intelligence() {
|
||||
# Update cached data
|
||||
IP_DATA[$ip]="$score|$hits|$bot_type|$attacks|$ban_count|$rep_score"
|
||||
|
||||
# CRITICAL FIX: Write to file immediately for cross-process communication
|
||||
# This ensures auto-mitigation engine sees scores from HTTP/SSH monitoring subprocesses
|
||||
write_ip_data_to_file "$ip" "$score|$hits|$bot_type|$attacks|$ban_count|$rep_score" 2>/dev/null &
|
||||
|
||||
# Update IP reputation DB in background (if score > 0)
|
||||
if [ "${score:-0}" -gt 0 ]; then
|
||||
(update_ip_reputation "$ip" 1 "$score" 0 "Live monitor: $new_attacks" >/dev/null 2>&1) &
|
||||
@@ -1898,6 +1934,9 @@ monitor_apache_logs() {
|
||||
# Update IP data with ET-based score
|
||||
IP_DATA[$ip]="$new_score|$curr_hits|$curr_bot|$curr_attacks|$curr_ban|$curr_rep"
|
||||
|
||||
# CRITICAL FIX: Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$new_score|$curr_hits|$curr_bot|$curr_attacks|$curr_ban|$curr_rep" 2>/dev/null &
|
||||
|
||||
# Check rate anomaly
|
||||
if type record_request &>/dev/null && type detect_rate_anomaly &>/dev/null; then
|
||||
record_request "$ip"
|
||||
@@ -2229,6 +2268,9 @@ monitor_cphulk_blocks() {
|
||||
# Update IP_DATA
|
||||
IP_DATA[$ip]="$score|$hits|$bot_type|$attacks|$ban_count|$rep_score"
|
||||
|
||||
# CRITICAL FIX: Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$score|$hits|$bot_type|$attacks|$ban_count|$rep_score" 2>/dev/null &
|
||||
|
||||
# Log event
|
||||
local time_str=$(date +"%H:%M:%S")
|
||||
local level=$(get_threat_level "$score")
|
||||
@@ -2297,6 +2339,9 @@ monitor_network_attacks() {
|
||||
# Update IP_DATA
|
||||
IP_DATA[$ip]="$score|$hits|$bot_type|$attacks|$ban_count|$rep_score"
|
||||
|
||||
# CRITICAL FIX: Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$score|$hits|$bot_type|$attacks|$ban_count|$rep_score" 2>/dev/null &
|
||||
|
||||
# Log to reputation DB
|
||||
flag_ip_attack "$ip" "DDOS" 0 "SYN flood detected" >/dev/null 2>&1 &
|
||||
|
||||
@@ -2347,6 +2392,9 @@ monitor_network_attacks() {
|
||||
# Update IP_DATA
|
||||
IP_DATA[$ip]="$score|$hits|$bot_type|$attacks|$ban_count|$rep_score"
|
||||
|
||||
# CRITICAL FIX: Write to file for cross-process communication
|
||||
write_ip_data_to_file "$ip" "$score|$hits|$bot_type|$attacks|$ban_count|$rep_score" 2>/dev/null &
|
||||
|
||||
# Log event
|
||||
local time_str=$(date +"%H:%M:%S")
|
||||
local level=$(get_threat_level "$score")
|
||||
|
||||
Reference in New Issue
Block a user