開了一台 VPS,跑 sudo tail -f /var/log/auth.log 就會看到成千上萬的 SSH 暴力登入嘗試,來自全世界各地的殭屍網路整天在敲你家的門。這時候最標準的解法就是裝 fail2ban,讓它自動把那些試錯的 IP 關進小黑屋。
問題是,現在網路上九成九的 fail2ban 教學都是七、八年前寫的,照著那些步驟在 Ubuntu 22.04、24.04 或 Debian 12 上操作,你很可能會遇到一個詭異現象:systemctl status fail2ban 顯示服務是 active,/etc/fail2ban/jail.local 也設好了 [sshd],但就是沒擋任何人,或是直接啟動失敗。這篇 fail2ban 教學會從這個坑開始講起,一次把新版 Linux 上的正確設定方式和除錯流程講清楚。
fail2ban 在做什麼,以及它不能做什麼
fail2ban 的運作原理不複雜:它盯著日誌檔(或 systemd journal),用正規表示式比對登入失敗的訊息,超過閾值就呼叫 iptables 或 nftables 把對方 IP 封掉一段時間。
釐清幾個常見誤解:
- 它不是防火牆。 它是個 log 監控工具,真正擋人的是防火牆(iptables / nftables / firewalld / ufw)。
- 它擋不了 DDoS。 封 IP 這種機制面對殭屍網路的分散式攻擊完全無效。
- 如果你已經關掉密碼登入、只開 SSH Key,fail2ban 對 SSH 的防護價值會大幅下降——因為沒有密碼可以試錯了。但它對 Web 應用(WordPress 登入頁、API 等)仍然有用。
結論是:fail2ban 是縱深防禦的一環,不是銀彈。如果你還沒把 SSH Key 設好,建議先看我們另一篇 SSH Key 設定教學,再回頭看這篇。
安裝 fail2ban
以 Ubuntu / Debian 為例(這是台灣 VPS 最常見的系統):
1 | sudo apt update |
RHEL / Rocky / AlmaLinux 系:
1 | sudo dnf install epel-release -y |
裝完後確認版本:
1 | fail2ban-client --version |
現在 Ubuntu 22.04 倉庫的版本是 0.11.2,24.04 是 1.0.2,Debian 12 也是 1.0.2。接下來的設定以 1.0+ 為準。
第一個坑:backend = auto 在新版 Ubuntu 會直接失敗
這是最多人踩的坑,也是多數中文教學沒寫的:Ubuntu 22.04 開始,預設安裝不含 rsyslog,系統日誌全部走 systemd journal,/var/log/auth.log 這個檔案根本不存在。
而 fail2ban 在 Debian/Ubuntu 的套件包裡,sshd jail 的 backend 預設是 auto——它會先去找 /var/log/auth.log,找不到就放棄,不會自動切到 systemd。這導致的結果是:
1 | fail2ban ERROR Failed during configuration: Have not found any log file for sshd jail |
或更陰險的狀況:服務看起來正常啟動了,但 fail2ban-client status sshd 告訴你 File list: 是空的,封鎖永遠不會觸發。
解決方法有兩種。推薦第二種:
方法一:安裝 rsyslog(不推薦)
1 | sudo apt install rsyslog -y |
這會讓 /var/log/auth.log 出現,相容舊教學。但多一個 daemon、多一份日誌重複寫入,在小 VPS 上純屬浪費資源。
方法二:明確把 backend 指定為 systemd(推薦)
建立 /etc/fail2ban/jail.local,從零開始寫(不要整份複製 jail.conf,那份檔案 600 多行,改起來地雷一堆):
1 | [DEFAULT] |
然後重啟:
1 | sudo systemctl restart fail2ban |
驗證有沒有真的跑起來
照教學敲完指令不代表有效,驗證是獨立的一步。
檢查服務狀態:
1 | sudo systemctl status fail2ban |
看到 active (running) 只是最低標準,不代表 jail 有真的在跑。
檢查 jail 狀態:
1 | sudo fail2ban-client status |
應該看到:
1 | Status |
檢查 sshd jail 細節:
1 | sudo fail2ban-client status sshd |
關鍵要看 Journal matches: 有沒有內容(用 systemd backend 時)或 File list: 有沒有檔案(用 auto/polling backend 時)。如果兩個都空的,代表沒在監控任何東西,設定沒生效。
做一次實戰測試:
最直接的驗證是故意讓自己被鎖(當然要先把你的主要 IP 加到 ignoreip)。從另一個不在白名單的 IP(比如手機熱點)連 SSH,故意打錯密碼幾次,然後在伺服器上:
1 | sudo fail2ban-client status sshd |
你會看到 Banned IP list: 出現那個 IP。要解除封鎖:
1 | sudo fail2ban-client set sshd unbanip 1.2.3.4 |
第二個坑:filter 正則沒匹配到日誌
有時候 jail 跑起來了、日誌也有失敗訊息,但就是不封鎖。這代表 filter 的正規表示式沒比對到你的日誌格式。原因可能是:
- 你用的 SSH daemon 版本太新或太舊
- 你改過 sshd 的 log format
- 某些雲端商的 image 把 log 格式客製化了
這時候拿出 fail2ban 最強的除錯工具 fail2ban-regex:
1 | # 用 systemd journal 測試 |
輸出會告訴你總共掃了幾行、匹配到幾行、哪些規則被觸發。如果匹配數是 0 但你明明看得到登入失敗,那就是 filter 的問題,可以考慮切換 mode:
1 | [sshd] |
aggressive 模式會匹配更多種失敗樣態(包含無效使用者、協議錯誤等),代價是誤判率稍高。
調整封鎖策略,反制慣犯
預設 1 小時封鎖對殭屍網路沒什麼嚇阻力——它會換 IP 繼續試,或等你解封後回來。fail2ban 有個好用的機制叫 recidive jail(慣犯監獄),專門盯已經被封過的 IP,累犯就重罰:
在 jail.local 加上:
1 | [recidive] |
意思是:一天內被任何 jail 封鎖超過 3 次的 IP,直接封一週。
另外可以開啟 遞增封鎖時間,讓每次累犯的封鎖時間翻倍:
1 | [DEFAULT] |
白名單的正確用法
ignoreip 千萬要設好,尤其是:
- 你自己常用的 IP(家裡 + 公司 + 手機熱點常見網段)
- 監控系統的來源 IP(如果你有 uptime 監控服務)
- CDN 的 IP 段(如果 Web jail 開了而且網站在 CDN 後面)
如果你是從動態 IP 環境連線(台灣的家用寬頻常見),與其把 IP 寫死,更好的做法是改用 SSH Key + 關閉密碼登入,讓 fail2ban 變成備援,而不是主要防線。
常用指令速查
整理一份實務上最常用的指令:
| 指令 | 用途 |
|---|---|
fail2ban-client status |
列出所有啟用中的 jail |
fail2ban-client status sshd |
看 sshd jail 細節(失敗次數、被封 IP) |
fail2ban-client set sshd unbanip 1.2.3.4 |
手動解封 IP |
fail2ban-client set sshd banip 1.2.3.4 |
手動封鎖 IP |
fail2ban-client reload |
重新載入設定(不中斷現有封鎖) |
fail2ban-regex <log> <filter> |
測試 filter 是否匹配 |
tail -f /var/log/fail2ban.log |
即時觀察封鎖動作 |
結語:fail2ban 是低成本但容易誤設的工具
fail2ban 的價值在於它幾乎零成本——裝完、設好、就在背景默默工作,能擋掉絕大多數腳本小子的嘗試。但也正因為它的「看起來有效」很容易偽裝成真的有效,驗證這一步絕對不能省。
這篇文章列的三個重點——backend 要指定 systemd、要用 fail2ban-client status 驗證、要用 fail2ban-regex 除錯——是在 Ubuntu 22.04 之後架 VPS 務必掌握的。
如果你正在找一台可以穩定跑這套安全設定的台灣 VPS,NCSE Network 提供位於台北是方電訊機房的 VPS 服務,採用 Intel Xeon Gold CPU 與 NVMe SSD,網路延遲低、穩定度高,適合需要長時間運行伺服器服務的開發者與中小企業。歡迎到 NCSE Network 官網 了解方案細節,或到我們的 Discord 社群 交流伺服器架設經驗。