diff --git a/modules/security/live-attack-monitor-v2.sh b/modules/security/live-attack-monitor-v2.sh index 54dd95c..a52cb48 100755 --- a/modules/security/live-attack-monitor-v2.sh +++ b/modules/security/live-attack-monitor-v2.sh @@ -966,30 +966,49 @@ batch_block_ips() { echo "✓ IPset batch: $blocked blocked, $failed skipped" else - # Fallback to CSF (slower, but still batch where possible) - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: Using CSF path (IPSET_AVAILABLE=$IPSET_AVAILABLE)" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + # Fallback to CSF - use chain_DENY ipset directly for speed + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: Using CSF chain_DENY ipset path (IPSET_AVAILABLE=$IPSET_AVAILABLE)" >> "$TEMP_DIR/debug.log" 2>/dev/null || true - for ip in "${ip_list[@]}"; do - if ! is_valid_ip "$ip"; then - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: Invalid IP format: $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true - ((failed++)) - continue - fi + # Try CSF's chain_DENY ipset first (much faster than csf -td for batches) + if ipset list chain_DENY &>/dev/null 2>&1; then + for ip in "${ip_list[@]}"; do + if ! is_valid_ip "$ip"; then + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: Invalid IP format: $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + ((failed++)) + continue + fi - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: Attempting CSF block for $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + # Add directly to CSF's chain_DENY ipset (instant kernel-level blocking) + if ipset add chain_DENY "$ip" -exist 2>/dev/null; then + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: chain_DENY ipset SUCCESS for $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + ((blocked++)) + echo "$ip" >> "$TEMP_DIR/blocked_ips_cache" + else + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: chain_DENY ipset FAILED for $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + ((failed++)) + fi + done + sort -u "$TEMP_DIR/blocked_ips_cache" -o "$TEMP_DIR/blocked_ips_cache" 2>/dev/null + echo "✓ CSF chain_DENY ipset batch: $blocked blocked, $failed failed" + else + # Fallback to csf -td if chain_DENY ipset not available + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: chain_DENY ipset not available, falling back to csf -td" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + for ip in "${ip_list[@]}"; do + if ! is_valid_ip "$ip"; then + ((failed++)) + continue + fi - local csf_output=$(csf -td "$ip" 3600 "Batch auto-block" 2>&1) - if [ $? -eq 0 ]; then - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: CSF SUCCESS for $ip" >> "$TEMP_DIR/debug.log" 2>/dev/null || true - ((blocked++)) - else - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: CSF FAILED for $ip: $csf_output" >> "$TEMP_DIR/debug.log" 2>/dev/null || true - ((failed++)) - fi - done - - echo "✓ CSF batch: $blocked blocked, $failed failed" - echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: CSF batch complete - blocked=$blocked, failed=$failed" >> "$TEMP_DIR/debug.log" 2>/dev/null || true + # Use csf -td as last resort (slower) + if csf -td "$ip" 3600 "Auto-block: SYN attack" >/dev/null 2>&1; then + ((blocked++)) + else + ((failed++)) + fi + done + echo "✓ CSF -td batch: $blocked blocked, $failed failed" + fi + echo "[$(date +"%H:%M:%S")] BATCH_BLOCK: CSF fallback batch complete - blocked=$blocked, failed=$failed" >> "$TEMP_DIR/debug.log" 2>/dev/null || true fi # Update total counter atomically