Fail2ban 防暴力破解配置完全指南 | SSH 安全防護教程
如果你使用的是默認端口(22)和傳統的密碼登錄方式來連接你的 VPS,過不了幾天你去查看系統日誌,一定會發現大量的“失敗登錄嘗試”。這是因為互聯網上隨時有無數的掃描腳本和殭屍網絡在無差別地嘗試爆破所有服務器的 SSH 密碼。
這不僅佔用系統資源,萬一密碼設得比較簡單,服務器直接就淪陷成了“肉雞”。
為了解決這個問題,除了 改用 SSH 密鑰登錄 之外,安裝一款能自動識別“多次密碼輸入錯誤”並將其 IP 封禁的防火牆工具是非常有必要的。Fail2ban 就是其中的黃金標準。
什麼是 Fail2ban?
Fail2ban 是一款強大的防禦軟件。它的工作原理很簡單: 後臺默默掃描系統日誌(如 /var/log/auth.log),如果它發現某個 IP 地址在短時間內連續多次嘗試密碼失敗,它就會自動去修改防火牆(iptables/ufw/firewalld 等)規則,把這個來源 IP 給拉黑(封禁)一段時間。
一次配置,終身免疫。
Fail2ban vs 其他安全工具對比
| 特性 | Fail2ban | DenyHosts | iptables 手動規則 | 雲服務商 WAF |
|---|---|---|---|---|
| 自動化程度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ |
| 靈活性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 支持協議 | 多種(SSH, Web, Mail等) | 僅 SSH | 所有 | 取決於服務 |
| 配置難度 | 中等 | 簡單 | 困難 | 簡單 |
| 資源佔用 | 低 | 極低 | 無 | 無 |
| 免費開源 | ✅ | ✅ | ✅ | ❌ |
步驟一:安裝 Fail2ban
Fail2ban 在包括 Debian 和 Ubuntu 在內的絕大部分 Linux 發行版的官方軟件源裡都能直接找到。
Debian/Ubuntu 安裝
- 首先更新一下軟件包列表:bash
apt update - 執行安裝命令:bash
apt install fail2ban -y
CentOS/RHEL 安裝
# 啟用 EPEL 倉庫
yum install epel-release -y
# 安裝 Fail2ban
yum install fail2ban -y驗證安裝
# 檢查版本
fail2ban-client --version
# 檢查服務狀態
systemctl status fail2ban安裝完成後,Fail2ban 這個服務會自動啟動並在後臺默默運行。
步驟二:新建 Fail2ban 自定義配置(核心動作)
Fail2ban 所有的默認“封禁規則”和“監獄(Jail)”配置都存放在 /etc/fail2ban/jail.conf 這個文件裡。 但是,官方強烈建議:不要去修改原始的 jail.conf 文件! 因為一旦未來軟件升級,你的修改就有丟失的可能。
正確的做法是:新建一個 jail.local 文件,把屬於我們自己的改動寫在裡面。 它的優先級比原始文件高。
基礎配置
使用你最愛的編輯器打開(新建)這個文件:
bashnano /etc/fail2ban/jail.local將以下最基礎、最實用的防護規則配置項 複製並粘貼 進去:
ini[DEFAULT] # 這是默認設置 # 忽略你自己的本地 IP 不受封禁(相當於白名單),如果你有固定 IP,也可以加在這裡,用空格隔開。 ignoreip = 127.0.0.1/8 ::1 # 封禁時間:被拉黑後,多長秒數放出來。這裡填 86400 (秒) 相當於封禁一天。 bantime = 86400 # 找茬時間窗口:在這個時間跨度內計算失敗次數。這裡設為 600 秒(十分鐘)。 findtime = 600 # 最大容忍次數:10 分鐘內,一旦失敗次數大於等於 3 次,立刻封禁。 maxretry = 3 [sshd] # 開啟針對 SSH 的監控監獄 enabled = true # 如果你改過 SSH 服務用的端口,請在這裡寫上你的新端口,如果是默認的 22,可以不寫。 port = ssh粘貼完了以後,按下快捷鍵
Ctrl + X,再按一下字母Y,然後敲擊鍵盤迴車鍵保存退出。
高級配置示例
保護 Web 服務(Nginx/Apache):
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 86400保護 WordPress:
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600保護 Postfix/Dovecot(郵件服務):
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps
filter = dovecot
logpath = /var/log/mail.log配置參數詳解
| 參數 | 說明 | 推薦值 | 單位 |
|---|---|---|---|
bantime | 封禁時長 | 86400(1天)或 3600(1小時) | 秒 |
findtime | 檢測時間窗口 | 600(10分鐘) | 秒 |
maxretry | 最大失敗次數 | 3-5 次 | 次數 |
ignoreip | 白名單 IP | 127.0.0.1/8 和你的固定 IP | CIDR |
backend | 日誌監控後端 | auto(自動選擇) | - |
usedns | DNS 查詢 | warn(警告但不阻止) | - |
封禁時間策略建議:
- 首次違規:1 小時(3600 秒)
- 重複違規:1 天(86400 秒)
- 惡意攻擊:1 周(604800 秒)或永久
步驟三:重啟服務生效與日常查看
修改完了屬於咱們自己的安全配置文件之後,我們需要告訴 Fail2ban 這位門衛大爺重新看一遍工作手冊:
bashsystemctl restart fail2ban為了保證無論重啟服務器多少次它都在默默工作,隨手允許它開機自啟動:
bashsystemctl enable fail2ban
怎麼查看它有沒有在工作?抓到了幾個壞人?
咱們可以通過它的客戶端命令去查看目前有哪些因為爆破 SSH 被關進“小黑屋”的倒黴蛋。
fail2ban-client status sshd終端將會友好地輸出一份短小的報告:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0 # 當前正在數錯密碼的次數(因為還沒超過3次)
| |- Total failed: 21 # 從服務開始到現在,這幫人一共輸錯了多少次密碼
`- Actions
|- Currently banned: 3 # 此刻正待在小黑屋裡被封號的倒黴 IP 數量(被 ban 了!)
|- Total banned: 5 # 歷史總共拉黑過的倒黴蛋
`- Banned IP list: 192.168.1.100 203.0.113.45 198.51.100.22 # 這裡會列出被你封禁的詳細 IP 地址查看所有監獄狀態
# 列出所有啟用的監獄
fail2ban-client status
# 輸出示例:
# Status
# |- Number of jail: 3
# `- Jail list: sshd, nginx-http-auth, wordpressFail2ban 日誌管理
查看 Fail2ban 日誌
# 實時查看日誌
tail -f /var/log/fail2ban.log
# 查看最近的封禁記錄
grep "Ban" /var/log/fail2ban.log | tail -20
# 查看解封記錄
grep "Unban" /var/log/fail2ban.log | tail -20日誌輪轉配置
Fail2ban 自帶日誌輪轉配置,通常位於 /etc/logrotate.d/fail2ban:
cat /etc/logrotate.d/fail2ban典型配置:
/var/log/fail2ban.log {
weekly
rotate 4
compress
delaycompress
missingok
postrotate
fail2ban-client flushlogs >/dev/null || true
endscript
}常用管理命令
封禁/解封 IP
# 手動封禁 IP
fail2ban-client set sshd banip 192.168.1.100
# 手動解封 IP
fail2ban-client set sshd unbanip 192.168.1.100
# 解封所有 IP
fail2ban-client set sshd unbanip --all查看封禁列表
# 查看特定監獄的封禁 IP
fail2ban-client get sshd actionunbannedips
# 查看 iptables 規則
iptables -L f2b-sshd -n -v重載配置
# 重載所有監獄配置
fail2ban-client reload
# 重載特定監獄
fail2ban-client reload sshd停止/啟動服務
# 停止 Fail2ban
systemctl stop fail2ban
# 啟動 Fail2ban
systemctl start fail2ban
# 重啟 Fail2ban
systemctl restart fail2ban
# 查看狀態
systemctl status fail2ban自定義過濾器(Filter)
如果內置過濾器不滿足需求,可以創建自定義過濾器。
創建自定義過濾器
示例:保護自定義應用
- 創建過濾器文件:
nano /etc/fail2ban/filter.d/myapp.conf- 添加過濾規則:
[Definition]
# 匹配失敗登錄的正則表達式
failregex = ^.*Failed login from <HOST>.*$
^.*Authentication failure.*from <HOST>.*$
# 忽略的行(可選)
ignoreregex =- 在
jail.local中引用:
[myapp]
enabled = true
port = 8080
filter = myapp
logpath = /var/log/myapp/access.log
maxretry = 3
bantime = 3600- 重載配置:
fail2ban-client reload測試過濾器
# 測試過濾器是否能正確匹配日誌
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
# 輸出會顯示匹配的行數和示例常見問題排查
Q1: Fail2ban 沒有封禁任何 IP?
排查步驟:
- 檢查服務狀態
systemctl status fail2ban- 查看日誌是否有錯誤
tail -50 /var/log/fail2ban.log- 確認監獄已啟用
fail2ban-client status sshd- 檢查日誌路徑是否正確
# 查看 SSH 日誌
tail -20 /var/log/auth.log
# 確認有失敗登錄記錄
grep "Failed password" /var/log/auth.log- 測試過濾器
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.confQ2: 誤封了自己的 IP 怎麼辦?
解決方案:
# 方法 1:從 VNC 控制檯登錄解封
fail2ban-client set sshd unbanip 你的IP
# 方法 2:臨時停止 Fail2ban
systemctl stop fail2ban
# 方法 3:將自己的 IP 加入白名單
nano /etc/fail2ban/jail.local
# 在 ignoreip 中添加你的 IP
ignoreip = 127.0.0.1/8 ::1 你的IP/32
# 重載配置
fail2ban-client reload預防措施:
- 始終將自己的固定 IP 加入
ignoreip白名單 - 先測試配置,確認無誤後再啟用嚴格規則
- 保留 VNC 控制檯訪問權限作為應急通道
Q3: 封禁時間太短/太長如何調整?
動態調整(無需重啟):
# 修改 SSH 監獄的封禁時間為 1 周
fail2ban-client set sshd bantime 604800
# 修改最大重試次數為 5
fail2ban-client set sshd maxretry 5
# 修改檢測時間窗口為 20 分鐘
fail2ban-client set sshd findtime 1200永久修改: 編輯 /etc/fail2ban/jail.local,修改對應參數後重載。
Q4: 如何查看哪些 IP 正在嘗試爆破?
# 實時查看失敗登錄嘗試
tail -f /var/log/auth.log | grep "Failed password"
# 統計最常見的攻擊 IP
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -rn | head -20
# 查看今天的攻擊情況
grep "$(date +%b %e)" /var/log/auth.log | grep "Failed password"Q5: Fail2ban 佔用資源過高?
優化建議:
- 減少日誌掃描頻率
# 在 jail.local 的 [DEFAULT] 部分添加
backend = systemd # 使用 systemd journal 而非輪詢文件- 簡化過濾器正則
- 避免過於複雜的正則表達式
- 使用
fail2ban-regex測試效率
- 限制監獄數量
- 只啟用真正需要的監獄
- 禁用不必要的監控
- 檢查日誌文件大小
# 清理舊日誌
journalctl --vacuum-time=7d
# 輪轉大日誌文件
logrotate -f /etc/logrotate.confFail2ban 與其他安全工具配合
1. Fail2ban + SSH 密鑰登錄
最佳實踐組合:
# 1. 啟用 SSH 密鑰登錄
# 2. 禁用密碼登錄
# 3. 修改 SSH 端口
# 4. 啟用 Fail2ban 作為最後一道防線2. Fail2ban + UFW 防火牆
# UFW 負責基礎端口管理
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
# Fail2ban 負責動態封禁惡意 IP
# 兩者互補,提供多層防護3. Fail2ban + Cloudflare
如果使用 Cloudflare CDN,需要特殊配置:
# 在 jail.local 中添加
[DEFAULT]
# 信任 Cloudflare IP 段
ignoreip = 127.0.0.1/8 ::1 173.245.48.0/20 103.21.244.0/22 ...
# 使用 Cloudflare API 封禁 IP(需額外配置 action)
action = cloudflare監控與告警
設置郵件告警
# 在 jail.local 的 [DEFAULT] 部分添加
destemail = admin@example.com
sender = fail2ban@your-server.com
mta = sendmail
action = %(action_mwl)s # 封禁時發送郵件並附帶日誌使用 Telegram 機器人告警
創建自定義 action:
nano /etc/fail2ban/action.d/telegram.conf[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage \
-d chat_id=<CHAT_ID> \
-d text="🚨 Fail2ban: IP <ip> 已被封禁\n監獄: <name>\n原因: <failures> 次失敗"
actionunban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage \
-d chat_id=<CHAT_ID> \
-d text="✅ Fail2ban: IP <ip> 已解封\n監獄: <name>"最佳實踐總結
安全配置清單
✅ 基礎安全
✅ Fail2ban 配置
✅ 監控與維護
推薦配置方案
個人博客/小型網站:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
[sshd]
enabled = true企業級服務器:
[DEFAULT]
bantime = 86400
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 ::1 公司IP/32
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
[wordpress]
enabled = true有了 Fail2ban 坐鎮你的服務器,你可以在面對日誌裡亂飛的牛鬼蛇神時,喝杯茶會心一笑了。☕✨
延伸阅读
免责声明
本文仅供技术交流和学习参考。涉及第三方服务的链接可能包含 sponsored 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。