#!/bin/bash # === Config === LOG="/var/log/fail2ban.log" MASTODON_URL="https://chatwithus.live" MASTODON_TOKEN="DsusOr2Gr6UN-sgssHD1XOJr5q9eCbe95fYxUDPM9EQ" BAN_CACHE="/var/tmp/teamtalk_ban_cache.txt" UNBAN_CACHE="/var/tmp/teamtalk_unban_cache.txt" TTL=604800 # 7 days in seconds # === Functions === send_dm() { curl -s -X POST "$MASTODON_URL/api/v1/statuses" \ -H "Authorization: Bearer $MASTODON_TOKEN" \ -F "status=$1" \ -F "visibility=direct" > /dev/null } send_log_post() { curl -s -X POST "$MASTODON_URL/api/v1/statuses" \ -H "Authorization: Bearer $MASTODON_TOKEN" \ -F "status=$1" \ -F "visibility=unlisted" > /dev/null } cleanup_cache() { local cache_file="$1" local now=$(date +%s) local temp_file=$(mktemp) while IFS="|" read -r ip timestamp; do [[ -z "$ip" || -z "$timestamp" ]] && continue if (( now - timestamp < TTL )); then echo "$ip|$timestamp" >> "$temp_file" fi done < "$cache_file" mv "$temp_file" "$cache_file" } log_recent_ips() { local keyword="$1" # Ban or Unban grep "$keyword" "$LOG" | grep 'teamtalk' | awk -v now="$(date +%s)" ' { cmd = "date +%s -d \"" $1 " " $2 "\"" cmd | getline timestamp close(cmd) if ((now - timestamp) <= 3600) { print $NF } } ' | sort -u } # === Init Caches === touch "$BAN_CACHE" touch "$UNBAN_CACHE" cleanup_cache "$BAN_CACHE" cleanup_cache "$UNBAN_CACHE" # === Process Bans === log_recent_ips "Ban" | while read ip; do if ! grep -q "^$ip|" "$BAN_CACHE"; then echo "$ip|$(date +%s)" >> "$BAN_CACHE" send_dm "🚫 GenesisShield TeamTalk Fail2Ban alert: Banned IP $ip" send_log_post "🚫 #GenesisShield TeamTalk Banned IP $ip at $(date -Is)" fi done # === Process Unbans === log_recent_ips "Unban" | while read ip; do if ! grep -q "^$ip|" "$UNBAN_CACHE"; then echo "$ip|$(date +%s)" >> "$UNBAN_CACHE" send_dm "✅ TeamTalk Fail2Ban alert: IP $ip has been unbanned" send_log_post "✅ #GenesisShield TeamTalk Unbanned IP $ip at $(date -Is)" fi done