✅ 功能總覽
| 功能模組 | 說明 |
|----------------------|------|
| **白名單支援** | 不封鎖自己或其他可信來源 IP |
| **自動解封(12小時)** | 封鎖時同時預約解封(使用 `at`) |
| **Email 通知** | 每次封鎖都會發送 Email 通知(使用 `mail` 指令) |
✅ 預備需求 1. **安裝 `mailutils`(用於發送 email)** ```bash
sudo apt install mailutils -y
```
2. **確認有 `at` 指令可用於排定解封時間**
sudo apt install at -y
sudo systemctl enable --now atd
3. **設定 Email 收件人與白名單 IP**
建立白名單檔(以 IP 列表儲存)
echo -e "127.0.0.1\n你的本地 IP\nCloudflare IP(可選)" > /etc/fail2ban/whitelist.txt
設定收件人 email
export FAILBAN_NOTIFY_EMAIL="[email protected]"
✅ 強化後腳本:`fail404ban.sh`
#!/bin/bash
export FAILBAN_NOTIFY_EMAIL="[email protected]"
LOG_DIR="$1"
THRESHOLD_404="${2:-50}"
INTERVAL_MIN="${3:-10}"
BLOCKED_LIST="/var/log/ufw_404_banned.log"
WHITELIST="/etc/failban/whitelist.txt"
#NOTIFY_EMAIL="${FAILBAN_NOTIFY_EMAIL:[email protected]}"
UNBAN_HOURS=12
if [ ! -d "$LOG_DIR" ]; then
echo "❗請輸入有效目錄"
exit 1
fi
if [ ! -f "$WHITELIST" ]; then
touch "$WHITELIST"
fi
TIME_PATTERN=$(date --date="-$INTERVAL_MIN min" "+%d/%b/%Y:%H:%M")
TMP_LOG="/tmp/failban_combined.log"
> "$TMP_LOG"
find "$LOG_DIR" -type f \( -name "*.log" -o -name "*.access" \) | while read logfile; do
cat "$logfile" >> "$TMP_LOG"
done
ban_ip() {
local ip="$1"
local reason="$2"
grep -qx "$ip" "$WHITELIST" && {
echo "🛑 跳過白名單 IP: $ip"
return
}
sudo ufw deny from "$ip" comment "$reason"
echo "$(date '+%F %T') | Blocked $ip for $reason" >> "$BLOCKED_LIST"
echo -e "警告:IP $ip 已因 $reason 被封鎖。\n\n來源:$(hostname)\n時間:$(date)" | mail -s "【VPS 防火牆通知】封鎖 $ip" "$NOTIFY_EMAIL"
# 自動解除封鎖 after 12 hours
echo "sudo ufw delete deny from $ip" | at now + $UNBAN_HOURS hours
echo "🕒 將於 $UNBAN_HOURS 小時後自動解除 $ip 的封鎖"
}
# === 模組 1: 404 爆量偵測
grep " 404 " "$TMP_LOG" | awk -v pattern="$TIME_PATTERN" '$4 > "["pattern' | awk '{print $1}' | sort | uniq -c | while read count ip; do
[ "$count" -ge "$THRESHOLD_404" ] && ! sudo ufw status | grep -q "$ip" && ban_ip "$ip" "$count 404s"
done
# === 模組 2: 敏感路徑掃描
for pattern in "\.env" "\.git/config" "wp-login\.php"; do
grep -E "GET /.*$pattern " "$TMP_LOG" | awk '{print $1}' | sort | uniq | while read ip; do
! sudo ufw status | grep -q "$ip" && ban_ip "$ip" "Scanned $pattern"
done
done
# === 模組 3: .gif DoS 偵測
grep -E "GET /.*\.gif " "$TMP_LOG" | awk -v pattern="$TIME_PATTERN" '$4 > "["pattern' | awk '{print $1}' | sort | uniq -c | while read count ip; do
[ "$count" -ge 30 ] && ! sudo ufw status | grep -q "$ip" && ban_ip "$ip" "$count .gif requests"
done
rm -f "$TMP_LOG"
echo "✅ 防禦完成!封鎖與解封任務已啟動"
給予執行權限
chmod +x fail404ban.sh
手動或排程執行
./fail404ban.sh /opt/npm/logs
✅ 建議搭配 crontab 每 5 分鐘執行:
*/5 * * * * /path/to/fail404ban.sh /opt/npm/logs 50 10 >> /var/log/fail2ban-cron.log 2>&1
Loading stats...