#!/bin/bash # Permanent ban script for IPs that have been banned more than 4 times by fail2ban # Run via cron: 0 */6 * * * /home/hoborg/homelab/scripts/permanent-ban-repeat-offenders.sh LOGFILE="/var/log/permanent-ban.log" BANLIST_FILE="/etc/fail2ban/permanent-banlist.conf" THRESHOLD=4 # Function to log with timestamp log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOGFILE" } # Ensure permanent banlist file exists if [ ! -f "$BANLIST_FILE" ]; then touch "$BANLIST_FILE" chmod 644 "$BANLIST_FILE" fi log_message "Starting repeat offender analysis (threshold: $THRESHOLD bans)" # Get list of IPs with ban counts from fail2ban logs REPEAT_OFFENDERS=$(grep "Ban " /var/log/fail2ban.log* | \ grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \ sort | uniq -c | sort -nr | \ awk -v threshold="$THRESHOLD" '$1 > threshold {print $2 " " $1}') if [ -z "$REPEAT_OFFENDERS" ]; then log_message "No repeat offenders found above threshold" exit 0 fi # Process each repeat offender echo "$REPEAT_OFFENDERS" | while read ip ban_count; do # Skip if already permanently banned if grep -q "^$ip" "$BANLIST_FILE"; then log_message "IP $ip already permanently banned (skip)" continue fi # Get country information COUNTRY=$(whois "$ip" 2>/dev/null | grep -i "country:" | head -1 | awk '{print $2}') # Add to permanent banlist echo "$ip # Banned $(date '+%Y-%m-%d') - $ban_count offenses - Country: $COUNTRY" >> "$BANLIST_FILE" # Add permanent iptables rule iptables -I INPUT -s "$ip" -j DROP # Make iptables rule persistent (systemd approach) if command -v iptables-save >/dev/null 2>&1; then iptables-save > /etc/iptables/iptables.rules 2>/dev/null || true fi log_message "PERMANENTLY BANNED: $ip ($ban_count offenses, Country: $COUNTRY)" done # Reload fail2ban to ensure it sees the updated banlist if systemctl is-active --quiet fail2ban; then log_message "Reloading fail2ban service" systemctl reload fail2ban fi log_message "Repeat offender analysis completed"