跳轉到內容

Fail2ban 防暴力破解配置完全指南 | SSH 安全防護教程

Fail2ban Security Protection

如果你使用的是默認端口(22)和傳統的密碼登錄方式來連接你的 VPS,過不了幾天你去查看系統日誌,一定會發現大量的“失敗登錄嘗試”。這是因為互聯網上隨時有無數的掃描腳本和殭屍網絡在無差別地嘗試爆破所有服務器的 SSH 密碼。

這不僅佔用系統資源,萬一密碼設得比較簡單,服務器直接就淪陷成了“肉雞”。

為了解決這個問題,除了 改用 SSH 密鑰登錄 之外,安裝一款能自動識別“多次密碼輸入錯誤”並將其 IP 封禁的防火牆工具是非常有必要的。Fail2ban 就是其中的黃金標準。

什麼是 Fail2ban?

Fail2ban 是一款強大的防禦軟件。它的工作原理很簡單: 後臺默默掃描系統日誌(如 /var/log/auth.log),如果它發現某個 IP 地址在短時間內連續多次嘗試密碼失敗,它就會自動去修改防火牆(iptables/ufw/firewalld 等)規則,把這個來源 IP 給拉黑(封禁)一段時間。

一次配置,終身免疫。

Fail2ban vs 其他安全工具對比

特性Fail2banDenyHostsiptables 手動規則雲服務商 WAF
自動化程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
靈活性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
支持協議多種(SSH, Web, Mail等)僅 SSH所有取決於服務
配置難度中等簡單困難簡單
資源佔用極低
免費開源

步驟一:安裝 Fail2ban

Fail2ban 在包括 Debian 和 Ubuntu 在內的絕大部分 Linux 發行版的官方軟件源裡都能直接找到。

Debian/Ubuntu 安裝

  1. 首先更新一下軟件包列表:
    bash
    apt update
  2. 執行安裝命令:
    bash
    apt install fail2ban -y

CentOS/RHEL 安裝

bash
# 啟用 EPEL 倉庫
yum install epel-release -y

# 安裝 Fail2ban
yum install fail2ban -y

驗證安裝

bash
# 檢查版本
fail2ban-client --version

# 檢查服務狀態
systemctl status fail2ban

安裝完成後,Fail2ban 這個服務會自動啟動並在後臺默默運行。


步驟二:新建 Fail2ban 自定義配置(核心動作)

Fail2ban 所有的默認“封禁規則”和“監獄(Jail)”配置都存放在 /etc/fail2ban/jail.conf 這個文件裡。 但是,官方強烈建議:不要去修改原始的 jail.conf 文件! 因為一旦未來軟件升級,你的修改就有丟失的可能。

正確的做法是:新建一個 jail.local 文件,把屬於我們自己的改動寫在裡面。 它的優先級比原始文件高。

基礎配置

  1. 使用你最愛的編輯器打開(新建)這個文件:

    bash
    nano /etc/fail2ban/jail.local
  2. 將以下最基礎、最實用的防護規則配置項 複製並粘貼 進去:

    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
  3. 粘貼完了以後,按下快捷鍵 Ctrl + X,再按一下字母 Y,然後敲擊鍵盤迴車鍵保存退出。

高級配置示例

保護 Web 服務(Nginx/Apache):

ini
[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:

ini
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600

保護 Postfix/Dovecot(郵件服務):

ini
[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白名單 IP127.0.0.1/8 和你的固定 IPCIDR
backend日誌監控後端auto(自動選擇)-
usednsDNS 查詢warn(警告但不阻止)-

封禁時間策略建議:

  • 首次違規:1 小時(3600 秒)
  • 重複違規:1 天(86400 秒)
  • 惡意攻擊:1 周(604800 秒)或永久

步驟三:重啟服務生效與日常查看

  1. 修改完了屬於咱們自己的安全配置文件之後,我們需要告訴 Fail2ban 這位門衛大爺重新看一遍工作手冊:

    bash
    systemctl restart fail2ban
  2. 為了保證無論重啟服務器多少次它都在默默工作,隨手允許它開機自啟動:

    bash
    systemctl enable fail2ban

怎麼查看它有沒有在工作?抓到了幾個壞人?

咱們可以通過它的客戶端命令去查看目前有哪些因為爆破 SSH 被關進“小黑屋”的倒黴蛋。

bash
fail2ban-client status sshd

終端將會友好地輸出一份短小的報告:

text
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 地址

查看所有監獄狀態

bash
# 列出所有啟用的監獄
fail2ban-client status

# 輸出示例:
# Status
# |- Number of jail:	3
# `- Jail list:	sshd, nginx-http-auth, wordpress

Fail2ban 日誌管理

查看 Fail2ban 日誌

bash
# 實時查看日誌
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

bash
cat /etc/logrotate.d/fail2ban

典型配置:

/var/log/fail2ban.log {
    weekly
    rotate 4
    compress
    delaycompress
    missingok
    postrotate
        fail2ban-client flushlogs >/dev/null || true
    endscript
}

常用管理命令

封禁/解封 IP

bash
# 手動封禁 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

查看封禁列表

bash
# 查看特定監獄的封禁 IP
fail2ban-client get sshd actionunbannedips

# 查看 iptables 規則
iptables -L f2b-sshd -n -v

重載配置

bash
# 重載所有監獄配置
fail2ban-client reload

# 重載特定監獄
fail2ban-client reload sshd

停止/啟動服務

bash
# 停止 Fail2ban
systemctl stop fail2ban

# 啟動 Fail2ban
systemctl start fail2ban

# 重啟 Fail2ban
systemctl restart fail2ban

# 查看狀態
systemctl status fail2ban

自定義過濾器(Filter)

如果內置過濾器不滿足需求,可以創建自定義過濾器。

創建自定義過濾器

示例:保護自定義應用

  1. 創建過濾器文件:
bash
nano /etc/fail2ban/filter.d/myapp.conf
  1. 添加過濾規則:
ini
[Definition]
# 匹配失敗登錄的正則表達式
failregex = ^.*Failed login from <HOST>.*$
            ^.*Authentication failure.*from <HOST>.*$

# 忽略的行(可選)
ignoreregex =
  1. jail.local 中引用:
ini
[myapp]
enabled = true
port = 8080
filter = myapp
logpath = /var/log/myapp/access.log
maxretry = 3
bantime = 3600
  1. 重載配置:
bash
fail2ban-client reload

測試過濾器

bash
# 測試過濾器是否能正確匹配日誌
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

# 輸出會顯示匹配的行數和示例

常見問題排查

Q1: Fail2ban 沒有封禁任何 IP?

排查步驟:

  1. 檢查服務狀態
bash
systemctl status fail2ban
  1. 查看日誌是否有錯誤
bash
tail -50 /var/log/fail2ban.log
  1. 確認監獄已啟用
bash
fail2ban-client status sshd
  1. 檢查日誌路徑是否正確
bash
# 查看 SSH 日誌
tail -20 /var/log/auth.log

# 確認有失敗登錄記錄
grep "Failed password" /var/log/auth.log
  1. 測試過濾器
bash
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

Q2: 誤封了自己的 IP 怎麼辦?

解決方案:

bash
# 方法 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: 封禁時間太短/太長如何調整?

動態調整(無需重啟):

bash
# 修改 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 正在嘗試爆破?

bash
# 實時查看失敗登錄嘗試
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 佔用資源過高?

優化建議:

  1. 減少日誌掃描頻率
ini
# 在 jail.local 的 [DEFAULT] 部分添加
backend = systemd  # 使用 systemd journal 而非輪詢文件
  1. 簡化過濾器正則
  • 避免過於複雜的正則表達式
  • 使用 fail2ban-regex 測試效率
  1. 限制監獄數量
  • 只啟用真正需要的監獄
  • 禁用不必要的監控
  1. 檢查日誌文件大小
bash
# 清理舊日誌
journalctl --vacuum-time=7d

# 輪轉大日誌文件
logrotate -f /etc/logrotate.conf

Fail2ban 與其他安全工具配合

1. Fail2ban + SSH 密鑰登錄

最佳實踐組合:

bash
# 1. 啟用 SSH 密鑰登錄
# 2. 禁用密碼登錄
# 3. 修改 SSH 端口
# 4. 啟用 Fail2ban 作為最後一道防線

2. Fail2ban + UFW 防火牆

bash
# UFW 負責基礎端口管理
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

# Fail2ban 負責動態封禁惡意 IP
# 兩者互補,提供多層防護

3. Fail2ban + Cloudflare

如果使用 Cloudflare CDN,需要特殊配置:

ini
# 在 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

監控與告警

設置郵件告警

ini
# 在 jail.local 的 [DEFAULT] 部分添加
destemail = admin@example.com
sender = fail2ban@your-server.com
mta = sendmail
action = %(action_mwl)s  # 封禁時發送郵件並附帶日誌

使用 Telegram 機器人告警

創建自定義 action:

bash
nano /etc/fail2ban/action.d/telegram.conf
ini
[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 配置

監控與維護

推薦配置方案

個人博客/小型網站:

ini
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true

企業級服務器:

ini
[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 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。

最後更新於: