Fail2ban + SSH 審計聯動:VPS 公網最佳防護方案

如果你的 VPS 直接暴露在公網上,大概在開機後 24 小時內,你就會看到 sshd 日誌裡充滿了來自世界各地的暴力掃描。

這不是「會不會」的問題,而是「何時」的問題。

伺服器安全防護——數位時代的城牆

在公網上,沒人在乎你是個人部落格還是企業後端——掃描機器人對所有人一視同仁


為什麼需要專用方案?

很多人以為「禁用密碼登入 + 使用金鑰」就夠了。但實際上:

威脅純金鑰能抵禦?Fail2ban 能加強?
字典掃描(密碼嘗試)✅ 是(已禁用密碼)🟡 減少日誌噪音
金鑰暴力枚舉❌ 否(sshd 照樣記錄)✅ 封禁此類連線
非標準端口命中❌ 否✅ 監控自定義端口
DoS 類連線泛洪❌ 部分✅ 自動封禁

即使你只使用金鑰登入,攻擊者仍會嘗試無效使用者無效金鑰,這些連線本身就會增加系統負擔和日誌大小。本文提供的方案會將這些行為即時封禁完整記錄到審計日誌中。

數據中心中的伺服器——硬體防護的視覺象徵

真正的安全不是單點防禦,而是多層聯動


方案設計理念

三個核心目標

  • 即時封禁 — 識別到惡意行為後自動加入黑名單
  • 可回溯審計 — 所有封禁行為記錄到 journald,方便事後調查
  • 零誤傷 — 正常使用金鑰登入的使用者不受影響

雙層防護架構

SSH 連線請求

    ├─▶ sshd 日誌 (journald)
    │       │
    │       ├─▶ [sshd] jail ──▶ 3 次失敗 ──▶ 封禁 24h
    │       │
    │       └─▶ [sshd-audit] jail ──▶ 2 次異常 ──▶ 封禁 48h

    └─▶ 正常金鑰登入 ──▶ 通過(不受影響)

部署腳本

以下是一鍵部署腳本,可直接在 Debian/Ubuntu 系統上執行:

#!/usr/bin/env bash
set -euo pipefail

echo "=== Fail2ban + SSH 審計聯動部署開始 ==="

# ---------- 1. 安裝 Fail2ban ----------
echo "[+] 安裝 Fail2ban"
apt update -qq
apt install -y fail2ban

systemctl enable fail2ban --now

# ---------- 2. Fail2ban 基礎配置 ----------
echo "[+] 寫入 Fail2ban 本機配置"

cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime  = 24h
findtime = 10m
maxretry = 3
backend  = systemd
usedns   = no
destemail = root
sender = fail2ban@localhost
action = %(action_mwl)s

[sshd]
enabled  = true
port     = 22
filter   = sshd
logpath  = %(systemd_journal)s
maxretry = 3
EOF

# ---------- 3. SSH 審計聯動過濾器 ----------
echo "[+] 配置 SSH 審計增強過濾器"

cat > /etc/fail2ban/filter.d/sshd-audit.conf <<'EOF'
[Definition]
failregex = ^
            ^.*sshd.*Failed publickey for .* from <HOST> port .*$
            ^.*sshd.*Invalid user .* from <HOST> port .*$
            ^.*sshd.*authentication failure; .* rhost=<HOST>.*$
ignoreregex =
EOF

# ---------- 4. 啟用審計過濾 jail ----------
cat >> /etc/fail2ban/jail.local <<'EOF'

[sshd-audit]
enabled  = true
filter   = sshd-audit
port     = 22
logpath  = /var/log/sshd-audit.log
maxretry = 2
bantime  = 48h
EOF

# ---------- 5. journald 封禁行為可審計 ----------
echo "[+] Fail2ban 封禁日誌進入 journald"

mkdir -p /etc/systemd/system/fail2ban.service.d

cat > /etc/systemd/system/fail2ban.service.d/override.conf <<'EOF'
[Service]
ExecStartPost=/usr/bin/logger -t fail2ban "Fail2ban service started"
EOF

systemctl daemon-reload

# ---------- 6. 重新啟動服務 ----------
echo "[+] 重新啟動 Fail2ban"
systemctl restart fail2ban

# ---------- 7. 狀態檢查 ----------
echo
echo "=== 狀態檢查 ==="
fail2ban-client status
echo
fail2ban-client status sshd
fail2ban-client status sshd-audit

伺服器機房中的網路設備

安全配置不只是防護,更是為未來的自己留下的操作紀錄


配置說明

jail.local — 主要防護規則

參數說明
bantime24h封禁持續時間,一天後自動解封
findtime10m監控時間窗口,10 分鐘內累計計算
maxretry3觸發封禁的失敗次數
backendsystemd從 journald 讀取日誌,而非檔案
port22你的自定義 SSH 端口(按實際修改)

sshd-audit — 增強審計規則

這個自定義過濾器專門捕捉三類事件:

  1. Failed publickey — 嘗試用無效金鑰登入 (最常見)
  2. Invalid user — 嘗試用不存在的使用者名稱登入
  3. Authentication failure — 一般的認證失敗

由於金鑰使用者幾乎不會觸發這些規則(只要金鑰匹配,sshd 不會記錄為 Failed),所以 maxretry = 2 是安全的。


常用管理指令

狀態查詢

# 查看所有監控的 jail
fail2ban-client status

# 查看 SSH 防護狀態
fail2ban-client status sshd

# 查看審計防護狀態
fail2ban-client status sshd-audit

手動操作

# 解封某個 IP
fail2ban-client set sshd unbanip 1.2.3.4

# 查看封禁日誌(journald)
journalctl -t fail2ban

# 即時監控審計日誌
tail -f /var/log/sshd-audit.log

查看已封禁 IP

# iptables 封禁列表
iptables -L -n | grep f2b

# fail2ban 客戶端
fail2ban-client status sshd | grep "Banned IP list"

命令列中的安全監控

真正的安全感來自於知道自己的系統正在被保護


常見問題

Q: 會誤封我自己的連線嗎?

不會。如果你使用金鑰登入且金鑰正確,sshd 不會觸發任何失敗記錄。只有當你打錯密碼或使用錯誤金鑰連續 3 次時才會觸發——而這種情況很少發生。

萬一被誤封,可透過另一個 IP 或 VNC 連入伺服器,執行:

fail2ban-client set sshd unbanip YOUR_IP

Q: 修改 SSH 端口後需要調整什麼?

jail.local 中的 port = 22 改為你的實際端口,然後重新啟動 fail2ban:

systemctl restart fail2ban

Q: 如何查看歷史封禁記錄?

journalctl -t fail2ban --since "7 days ago"

這會顯示過去一週內的所有封禁事件。


結語

安全不是一次性的配置,而是持續的習慣。

Fail2ban + SSH 審計聯動方案的核心價值在於:讓機器處理常規威脅,讓人類專注於例外事件。當你的 VPS 每天被掃描數百次時,一個自動化的封禁系統比任何手動監控都可靠。

配置好之後,它會安安靜靜地在背景運行——直到有需要的那一天,你會感謝自己提前做了這件事。

安全的本質不是建立一個無法攻破的堡壘,而是讓攻擊者覺得「不值得」