April 10Apr 10 Debian 13 原生防火牆 nftables、Fail2ban入侵防護/Fail2ban Part 1 ****************************************************** Fail2ban Part 1 等待LNMP服務都安裝設置完,再做 Part 2 ****************************************************** --------------- 前言 --------------- 為何選擇原生 nftables? 相較於 iptables、ufw 或 firewalld,nftables 具備以下優勢: 雙棧統一管理:使用 inet 位址族,一套規則同時覆蓋 IPv4 與 IPv6,不會有遺漏 原子性載入:規則集一次性套用,不會出現套用到一半的中間狀態 內建計量器:速率限制更精確,無需額外核心模組 語法預驗證:nft -c -f 可在套用前驗證語法,大幅降低鎖死SSH的風險 Fail2ban 整合:與 Fail2ban 1.1.0+ 完整整合,可動態封鎖攻擊IP IPv4 與 IPv6 雙棧的必要性 許多管理員只設定 IPv4 防火牆,卻忽略了 IPv6。若伺服器持有 IPv6 位址而未設定對應規則,IPv6 流量將完全不受保護,形同開了一扇隱形後門 本文使用 inet 位址族,同一套規則自動涵蓋 IPv4 與 IPv6,杜絕此類遺漏 為何採用自訂 firewall.service 而非 nftables.service? 本文採用自訂 firewall.service 驅動腳本,而非直接依賴 nftables.service 載入靜態設定檔,原因如下: 腳本在每次啟動時動態建構規則,可整合環境變數、條件判斷與 Shell 邏輯 Before=network-pre.target 確保規則在網路啟動前就位,不留空窗期 方便日後擴充:直接修改 Shell 腳本即可,語法直觀 ------------------ 整體流量架構 ------------------ 外部流量 │ ▼ nftables (inet filter) ├── INPUT chain │ ├── 黑名單 set (f2b-blacklist4/6、blacklist4/6) → DROP ← 最高優先 │ ├── lo 介面 → ACCEPT │ ├── 已建立連線 (established/related) → ACCEPT ← 效能優化 │ ├── 無效封包 (invalid state) → DROP │ ├── 管理員 IP 白名單 → ACCEPT ← 無任何限速 │ ├── 私有網段白名單 → ACCEPT ← VPC/監控/LB │ ├── 異常 TCP flags → DROP ← 防掃描/畸形封包 │ ├── ICMPv4 速率限制 → ACCEPT │ ├── ICMPv6 必要類型 → ACCEPT ← NDP,IPv6 必需 │ ├── SSH 速率限制 (10/min) → ACCEPT / DROP │ ├── Web (80/443) → ACCEPT ← 完全開放 │ ├── 管理後台 (888) → 僅限白名單 IP │ └── 其餘 → LOG + DROP ← 限速 2/min 避免日誌洪流 ├── FORWARD chain → DROP ← 此主機非路由器 └── OUTPUT chain → ACCEPT ← 主機主動對外連線 │ ▼ Fail2ban(持續掃描日誌,偵測暴力攻擊) └── 操作 nftables set,動態加入封鎖 IP(含 timeout 自動過期) --------------------------- 持久化黑名單生命週期 --------------------------- Fail2ban 啟動 └─> actionstart ├─ 建立 set(若不存在,冪等操作) ├─ flush set(清空避免重複累積) └─ 從 .ipset 檔案恢復黑名單(含 bantime timeout) 偵測到攻擊 └─> actionban ├─ nft add element(加入 set,設定 timeout) └─ 追加寫入 .ipset 持久化檔案 Ban 過期或手動解封 └─> actionunban ├─ nft delete element └─ sed 移除 .ipset 對應行 Fail2ban 正常停止 └─> actionstop ├─ 從 nft 讀取目前黑名單 └─ 原子性寫入 .ipset(.new 暫存 → 正式) Cron(每小時整點) └─> 從 nft 讀取目前 set → 覆寫 .ipset └─ 確保強制重啟時(reboot、核心 panic)也能保留最近 1 小時內的封鎖 為何需要 Cron 備份? Fail2ban 的 nftables set 是記憶體狀態。actionstop 只在 Fail2ban 正常停止時觸發 若發生強制重啟或電源中斷,actionstop 不會執行,若無 Cron 備份,黑名單將全部消失 -------------------- 操作前安全提醒 -------------------- 錯誤的防火牆規則會導致SSH連線立即中斷,操作前請務必閱讀 開啟帶外管理備援:在套用規則前,請先透過雲端主控台開啟 VNC / Serial Console / IPMI 等帶外管理通道,確保即使SSH中斷也能進行補救 記下所有管理IP(含 IPv6):務必將目前的管理IP(包含 IPv6 位址)加入允許清單,缺一不可。動態IP用戶每次操作前都應重新確認 善用測試模式:腳本提供 test 指令,規則套用後 120 秒自動復原,可安全驗證而不影響後續連線。務必先用 test,確認SSH正常後再用 start 正式套用 雲端內網IP需加入白名單:AWS、GCP、阿里雲、騰訊雲、Hetzner 等平台的內網 IP(如 10.x.x.x)若有負載平衡器或監控系統 需填入 PRIVATE_NETS_V4,否則健康檢查可能被誤封 修改前備份:重要資料請在操作前完成備份 -------------------------- 事前準備:收集必要資訊 -------------------------- 在開始前,請收集以下資訊並記錄備用 查看目前SSH連線的來源IP 確認你目前透過哪個IP 連入伺服器(包含 IPv6),此IP必須填入防火牆白名單 ss -tnp | grep :22 | grep ESTAB 查詢本機對外 IPv4 位址(必填) curl -4 ifconfig.me 查詢本機對外 IPv6 位址(若有則填) curl -6 ifconfig.me 請記下輸出結果,稍後需填入防火牆腳本的 ADMIN_IP4 與 ADMIN_IP6 確認 IPv6 是否已啟用(預期輸出為 0,代表已啟用) sysctl net.ipv6.conf.all.disable_ipv6 確認本機的 IPv6 位址 ip -6 addr show 查詢 VPS 私有IP 雲端平台的負載平衡器、監控系統會透過私有IP通訊,需加入白名單 ip addr show | grep 'inet ' | grep -v 127.0.0.1 --------------------------------- 安裝 nftables 並清除衝突工具 --------------------------------- 更新套件清單並升級 apt update -y && apt upgrade -y 安裝 nftables 防火牆主體、conntrack 用於連線追蹤統計(firewall.sh stats 指令會用到) apt install -y nftables conntrack 確認nftables版本,預期 nftables v1.1.3 以上 nft --version ------------------------- 停用衝突的防火牆工具 ------------------------- 同時啟用多套防火牆工具會造成規則衝突,請依實際安裝情況停用 2>/dev/null || true 的作用:若該服務本就不存在,指令不會報錯中止 停用 ufw(若有安裝) systemctl disable --now ufw 2>/dev/null || true 停用 firewalld(若有安裝) systemctl disable --now firewalld 2>/dev/null || true 停用 iptables / ip6tables(若有安裝) systemctl disable --now iptables 2>/dev/null || true systemctl disable --now ip6tables 2>/dev/null || true 確認無殘留規則,若有殘留 iptables 規則,執行以下清空 iptables -F 2>/dev/null || true ip6tables -F 2>/dev/null || true ------------------------------- 清空 nftables 預設設定檔 ------------------------------- nftables.service 預設在開機時載入 /etc/nftables.conf 後續我們將停用 nftables.service,但為了防止它被意外啟用時載入空規則而清掉防火牆,建議將此檔案改為僅執行 flush ruleset: 以下幾行一起貼上 cat > /etc/nftables.conf << 'EOF' #!/usr/sbin/nft -f # 此檔案由 firewall.service 接管,請勿直接編輯 # 若 nftables.service 意外被啟用,flush ruleset 可避免載入錯誤規則 flush ruleset EOF --------------------建立防火牆腳本--------------------建立目錄mkdir -p /usr/local/bin建立防火牆腳本vi /usr/local/bin/firewall.shfirewall.sh貼入以下完整內容,務必修改使用者配置區塊ADMIN_IP4="請改為您的IPv4"ADMIN_PORT="888"# 內網白名單(請根據 ip addr 查詢後填寫)PRIVATE_NETS_V4=""PRIVATE_NETS_V6=""儲存檔案並離開vi編輯器按 Esc,輸入 :wq,按 Enter---------------- 設定權限 ---------------- 設定腳本權限 (700 表示僅 root 可讀寫執行,防止其他使用者查看或修改) chmod 700 /usr/local/bin/firewall.sh chown root:root /usr/local/bin/firewall.sh -------------------------------- 測試防火牆 -------------------------------- 執行測試模式 /usr/local/bin/firewall.sh test 測試模式流程: 1. 產生規則至暫存檔 2. 語法預驗證(通過才繼續) 3. 原子性載入規則(無空窗期) 4. 啟動 120 秒緊急還原計時器 5. 若 SSH 正常 → 按 Enter 取消還原並永久保留規則 6. 若 SSH 異常中斷 → 120 秒後自動還原至套用前狀態 --------------------------------------- 另開終端機確認連線 (測試期間進行) --------------------------------------- 在測試期間,另開一個終端機視窗進行以下驗證 測試SSH連線 (應成功) ssh 你的伺服器IP 測試 IPv4 對外連線 (應成功) ping -c 3 8.8.8.8 測試 IPv6 對外連線(若有 IPv6) ping6 -c 3 2001:4860:4860::8888 -------------------------- 正式套用規則 -------------------------- 確認測試無誤後,正式套用規則 /usr/local/bin/firewall.sh start --------------------- 確認規則已套用 --------------------- 查看完整規則集 nft list ruleset 查看 input chain nft list chain inet filter input 查看統計資訊 /usr/local/bin/firewall.sh stats ---------------------------------------- 建立 systemd 服務(開機自動啟動) ---------------------------------------- 本文採用自訂 firewall.service 驅動腳本,而非直接依賴 nftables.service 載入靜態設定 建立 vi /etc/systemd/system/firewall.service 貼上以下內容 [Unit] Description=Custom nftables Firewall (IPv4 + IPv6 Dual Stack) After=network-pre.target Before=network.target network-online.target [Service] Type=oneshot ExecStart=/usr/local/bin/firewall.sh start ExecStop=/usr/local/bin/firewall.sh stop RemainAfterExit=yes StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target 儲存檔案並離開vi編輯器 按 Esc,輸入 :wq,按 Enter ------------------ 啟用並啟動服務 ------------------ 重新載入 systemd 設定(每次修改 .service 檔案後必須執行) systemctl daemon-reload 設定開機自動啟動 systemctl enable firewall.service 立即啟動 systemctl start firewall.service 確認狀態,(應顯示 active (exited),oneshot 類型服務執行完畢後正常顯示此狀態) systemctl status firewall.service 查看啟動日誌 journalctl -u firewall.service --no-pager --------------------------------------- 停用 nftables.service 避免衝突 --------------------------------------- 重要:nftables.service 預設在開機時載入 /etc/nftables.conf 若讓它與自訂 firewall.service 並存,可能發生規則衝突或重複載入,必須停用 停用 nftables.service systemctl disable nftables.service systemctl stop nftables.service 確認已停用,預期輸出 disabled systemctl is-enabled nftables.service -----------------------------------持久化核心參數 (sysctl)-----------------------------------防火牆腳本本身不含 sysctl 調整。sysctl -w 的臨時調整重開機後會恢復預設值,需建立設定檔以持久化建立vi /etc/sysctl.d/99-hardening.conf99-hardening.conf.txt貼上內容儲存檔案並離開vi編輯器按 Esc,輸入 :wq,按 Enter---------------------- 立即套用並驗證 ---------------------- 立即套用 sysctl --system 驗證,應顯示: = 1 sysctl net.ipv4.tcp_syncookies 驗證,應顯示: = 0 sysctl net.ipv4.conf.all.accept_redirects ----------------- 安裝Fail2ban ----------------- Fail2ban 持續掃描系統日誌,偵測到多次登入失敗時,自動將來源IP加入nftables封鎖規則,提供動態的入侵防護 同時安裝 whois 以便查詢被封鎖IP的WHOIS資訊,方便排查攻擊來源 apt update -y apt install -y fail2ban whois 確認版本,預期 Fail2Ban v1.1.0 以上 fail2ban-client --version ------------------------------------------------設定 Fail2ban × nftables 整合 Action------------------------------------------------此設定檔讓 Fail2ban 直接操作 nftables 的 f2b-blacklist4 / f2b-blacklist6 set,並在重啟時從磁碟恢復黑名單建立vi /etc/fail2ban/action.d/nftables-set.confnftables-set.conf.txt貼上以下內容(確認以下設置的內容,若你的VPS沒有IPv6,則設置 enable_ipv6 = false)# 是否啟用 IPv6 支援# 若伺服器確認無 IPv6 可設為 false,減少 nft 操作與潛在錯誤enable_ipv6 = false儲存檔案並離開vi編輯器按 Esc,輸入 :wq,按 Enter------------------ 設定 jail.local ------------------ 為何不直接修改 jail.conf? /etc/fail2ban/jail.conf 是套件提供的預設設定,套件更新時會被覆蓋 正確做法是建立 /etc/fail2ban/jail.local,Fail2ban啟動時 .local 的設定會覆蓋 .conf,這樣可以在套件更新後保留你的自訂設定 建立vi /etc/fail2ban/jail.localjail.local.txt貼上以下內容修改 ignoreip 中的佔位文字(你的管理員IPv4、你的管理員IPv6、你VPS的私有IP網段)請替換為實際IP不存在的項目直接刪除,不要留下佔位文字,否則 fail2ban-client -t 會報錯儲存檔案並離開vi編輯器按 Esc,輸入 :wq,按 Enter------------------------------- 確認 nftables Sets 已建立 ------------------------------- 在啟用 Fail2ban 之前,需確認 nftables 的 f2b-blacklist4 與 f2b-blacklist6 sets 已存在(由 firewall.sh start 建立) 若 sets 不存在,Fail2ban 啟動時 actioncheck 會失敗 確認 sets,應看到 f2b-blacklist4 與 f2b-blacklist6 nft list sets ------------------------------------- 設定 fail2ban.local(IPv6 選項) ------------------------------------- 簡單來說:加入 allowipv6 = auto 是為了讓 Fail2ban 能正確處理 IPv6 連線,避免 IPv6 的封鎖失效或產生錯誤 在較舊的 Fail2ban 版本中,如果沒有明確設定 allowipv6,當系統啟用 IPv6 時,可能會導致一些問題 auto 的意義:讓程式自己判斷 結論:加入 allowipv6 = auto 是最佳實務,讓 Fail2ban 自適應系統的網路設定,既能處理 IPv6 攻擊,又不會在無 IPv6 環境中出錯,確保封鎖規則完整生效 建立 vi /etc/fail2ban/fail2ban.local 貼入以下內容 [Definition] # 選項:allowipv6 # 說明:允許 Fail2ban 使用 IPv6 介面 # 可選值:auto | yes | no allowipv6 = auto 儲存檔案並離開vi編輯器 按 Esc,輸入 :wq,按 Enter -------------------------- Cron 定期備份封鎖清單 -------------------------- Fail2ban 的 nftables set 是記憶體狀態,actionstop 雖然會在 Fail2ban 正常停止時將黑名單寫入磁碟 但若發生強制重啟(reboot、核心 panic、電源中斷),actionstop 不會被觸發 搭配 Cron 定期備份,可確保最多只損失 1小時 內的新增封鎖記錄 建立目錄 mkdir -p /var/lib/fail2ban 設置權限 chmod 750 /var/lib/fail2ban chown root:root /var/lib/fail2ban 注意:/var/lib/fail2ban 應由 root 擁有並限制存取,避免非特權使用者竄改黑名單檔案 -----------------建立備份腳本-----------------使用獨立腳本比直接在 crontab 中塞長指令更容易維護與排查建立vi /usr/local/bin/backup-blacklist.shbackup-blacklist.sh貼上內容儲存檔案並離開vi編輯器按 Esc,輸入 :wq,按 Enter---------------------- 設定腳本權限 ---------------------- chmod 700 /usr/local/bin/backup-blacklist.sh chown root:root /usr/local/bin/backup-blacklist.sh ---------------------------------- 手動執行一次確認 ---------------------------------- 手動執行一次,確認無誤 /usr/local/bin/backup-blacklist.sh 確認備份結果已寫入,預期有兩個 .ipset 檔案 cd /var/lib/fail2ban/ ls -l 確認已有這 2個 備份檔 nftables-blacklist4.ipset nftables-blacklist6.ipset ----------------------- 啟用Cron ----------------------- 啟用 systemctl enable --now cron 檢查狀態,確認已運行 active (running) systemctl status cron 編輯 Cron 任務 crontab -e 在尾部 貼上以下內容 # ===================================== # 備份 Fail2ban 黑名單 相關動作 # ===================================== # 每小時整點備份 nftables Fail2ban 黑名單(IPv4 + IPv6) 0 * * * * /usr/local/bin/backup-blacklist.sh # 每日凌晨 2:00 清理超過 10000 行的持久化檔案(防止異常成長) # truncate 只截斷,不能移除過期IP;實務上 Fail2ban actionunban 會即時從檔案移除已解封IP # 此任務作為最後防線,確保檔案大小可控 0 2 * * * for f in /var/lib/fail2ban/*.ipset; do [ -f "$f" ] && [ "$(wc -l < "$f")" -gt 10000 ] && tail -n 10000 "$f" > "$f.tmp" && mv "$f.tmp" "$f"; done 儲存檔案並離開vi編輯器 按 Esc,輸入 :wq,按 Enter ------------------------- 驗證 ------------------------- 檢視目前所有的Cron任務 crontab -l ----------------------------- 設定 journald 持久化 ----------------------------- 預設情況下,systemd-journald 日誌儲存在記憶體中(/run/log/journal),重開機後消失 設定持久化後,日誌會寫入磁碟(/var/log/journal),有利於事後追查攻擊記錄 mkdir -p /var/log/journal systemd-tmpfiles --create --prefix /var/log/journal 編輯 vi /etc/systemd/journald.conf 找到並修改以下內容(位於 [Journal] 區塊內) [Journal] Storage=persistent # 限制日誌佔用磁碟空間(2GB VPS建議500M) SystemMaxUse=500M # 保留7天日誌(604800 秒) MaxRetentionSec=604800 儲存檔案並離開vi編輯器 按 Esc,輸入 :wq,按 Enter 說明: SystemMaxUse=500M 限制日誌佔用磁碟空間,避免在 2GB RAM 的小型 VPS 上因磁碟不足造成問題 MaxRetentionSec=604800 保留 7天 日誌 ----------------------------- 重啟 journald 使設定生效 ----------------------------- 重啟 systemctl restart systemd-journald 確認日誌目錄已建立 ls /var/log/journal/ ------------------------ 啟用 Fail2ban ------------------------ 測試設定檔語法,預期輸出:OK: configuration test is successful 若出現錯誤,請仔細檢查 jail.local 中是否有留下未替換的佔位文字(如 你的管理員IPv4) fail2ban-client -t 啟用 systemctl enable --now fail2ban 確認狀態,應顯示 active (running) systemctl status fail2ban ----------------------- 重開機驗證 ----------------------- 重開機 reboot 驗證所有服務是否正確自動啟動 確認防火牆服務狀態,應顯示 active (exited) systemctl status firewall.service 確認 nftables.service 已停用,應顯示 disabled systemctl is-enabled nftables.service 確認防火牆規則已自動載入 nft list ruleset nft list chain inet filter input nft list ruleset | grep -E "whitelist4|blacklist4|f2b" 確認 fail2ban 服務狀態,應顯示為 active (running) systemctl status fail2ban.service 查看所有啟用的監獄 fail2ban-client status 查看 SSH 監獄狀態 fail2ban-client status sshd 確認 Fail2ban 已整合 nftables(兩個 set 應存在) nft list set inet filter f2b-blacklist4 nft list set inet filter f2b-blacklist6 確認 Fail2ban 已整合 nftables,應顯示 f2b- 開頭的規則 nft list ruleset | grep f2b 確認白名單已正確載入(應顯示你的管理員IP 與 VPS 私有IP) fail2ban-client get sshd ignoreip 核心參數驗證 已啟用,應顯示 = 1 sysctl net.ipv4.tcp_syncookies 已禁用,應顯示 = 0 sysctl net.ipv4.conf.all.accept_redirects 確認 SSH 服務監聽狀態(IPv4 + IPv6 雙棧) ss -tlnp | grep :22 0.0.0.0:22 → IPv4 監聽 [::]:22 → IPv6 監聽 兩個都有才代表雙棧正常 備份腳本驗證 確認 Cron 每小時備份腳本正常運作 ls -lh /var/lib/fail2ban/*.ipset ------------------ 測試封鎖功能 ------------------ 使用 RFC 5737 / RFC 3849 保留的文件用 IP 進行測試,不影響任何真實主機 手動封鎖測試 IPv4 (RFC 5737 文件用IP) fail2ban-client set sshd banip 192.0.2.100 手動封鎖測試 IPv6 (RFC 3849 文件用IP) fail2ban-client set sshd banip 2001:db8::100 查看監獄狀態 (Banned IP 欄位應顯示上述被封鎖的IP) fail2ban-client status sshd 確認 nftables set 中已加入封鎖IP nft list set inet filter f2b-blacklist4 nft list set inet filter f2b-blacklist6 測試完畢後,解除封鎖 fail2ban-client set sshd unbanip 192.0.2.100 fail2ban-client set sshd unbanip 2001:db8::100 --------------------- 常見陷阱與排錯指南 --------------------- 陷阱 1:IPv6 防火牆未設定 症狀:IPv4 連線正常,IPv6 流量完全開放 說明:使用 inet 位址族已同時涵蓋 IPv4 與 IPv6,本教學不會有此問題。若自行修改規則只用 ip 族,則需額外建立 ip6 族規則 驗證: nft list ruleset | grep 'inet\|ip6' 應看到 table inet filter,代表雙棧皆受保護 陷阱 2:ICMPv6 被封鎖 症狀:IPv6 連線時通時不通,或無法取得 IPv6 位址 (SLAAC 失效) 解決:確認 IN_ICMPV6_ALLOWED 包含 133-136 (NDP 鄰居探索) 類型 nft list chain inet filter input | grep icmpv6 陷阱 3:雲端內網IP被封鎖 症狀:重開機後負載平衡器或監控系統無法連線 (常見於 AWS/GCP/Hetzner) 解決:在腳本的 PRIVATE_NETS_V4 填入對應的私有網段 (如 10.0.0.0/8) 查看VPS的私有IP ip addr show | grep 'inet ' 陷阱 4:忘記加入管理 IP 症狀:執行 firewall.sh start 後SSH立即斷線 解決:透過帶外管理 (VNC/Console) 執行: nft flush ruleset 然後修正腳本中的管理IP再重新測試 陷阱 5:服務只監聽 IPv4 症狀:nftables 規則正確,但 IPv6 用戶仍無法連線論壇 解決:確認 NGINX 監聽 ::80 而非 0.0.0.0:80 ss -tlnp | grep :80 # :::80 → 雙棧(正確) # 0.0.0.0:80 → 僅 IPv4(需修改 NGINX 設定) NGINX 設定應包含: listen 80; listen [::]:80; listen 443 ssl; listen [::]:443 ssl; 陷阱 6:sysctl 參數重開機後消失 症狀:重開機後 net.ipv4.tcp_syncookies 回到預設值 0 解決:確認已完成 持久化核心參數sysctl的設定,建立 /etc/sysctl.d/99-hardening.conf 陷阱 7:nftables.service 與 firewall.service 衝突 症狀:重開機後規則被 nftables.service 覆蓋或清空 解決:確認已停用 nftables.service: systemctl is-enabled nftables.service 若顯示 enabled,執行: systemctl disable nftables.service 陷阱 8:Fail2ban 白名單未加入 VPS私有IP 症狀:Fail2ban 誤封鎖雲端平台的健康檢查IP,導致服務中斷 解決:在 jail.local 的 ignoreip 加入VPS分配的私有IP 查看VPS的私有IP ip addr show | grep 'inet ' 確認白名單 fail2ban-client get sshd ignoreip 陷阱 9:論壇靜態資源或 API 被速率限制誤封 症狀:正常用戶在短時間內大量載入頁面(CDN 回源、搜尋爬蟲)被速率限制 解決:針對已知的 CDN / 爬蟲 IP 段加入 PRIVATE_NETS_V4 白名單 例如 Cloudflare 最新 IP 段:https://www.cloudflare.com/ips/(需定期更新) 陷阱 10:網卡名稱不是 eth0 症狀:NAT 規則套用後,SNAT 功能無效 解決:Debian 13 在部分主機商的網卡名稱可能為 ens3、ens18、enp1s0 等,需先確認 ip route | grep default 腳本中 IFACE 變數已使用 ip route 自動偵測,若仍有問題請手動設定 陷阱 11:bantime 單位問題(nftables timeout) 症狀:Fail2ban 封鎖後封鎖時間不符預期,IP提早或延遲解封 說明:nftables timeout 接受帶單位的字串(如 3600s、1h) nftables-set.conf 中 actionban 的 <bantime> 變數由 Fail2ban 傳入的是秒數整數,需在 action 中手動加上 s 後綴: nft add element inet filter f2b-blacklist4 { <ip> timeout <bantime>s } 陷阱 12:Fail2ban 重啟後黑名單消失 說明:Fail2ban 的 nftables set 為記憶體狀態,actionstop 只在 Fail2ban 正常停止時觸發 若遇到強制重啟(reboot、電源中斷、核心 panic),actionstop 不會被執行,黑名單無法寫入磁碟 解決:確認已完成 Cron 備份腳本設定。Cron 每小時備份一次,最多只損失 1小時內的新增封鎖 陷阱 13:Debian 13 無 /var/log/auth.log 症狀:Fail2ban 啟動後 sshd jail 無法偵測到任何登入失敗 說明:Debian 13 預設使用 systemd-journald,SSH登入失敗記錄在 journal 而非傳統的 /var/log/auth.log 解決:確認 jail.local 中設定 backend = systemd 驗證SSH登入失敗是否有被 journald 記錄 journalctl -u ssh --since "10 minutes ago" | grep -i fail 陷阱 14:Cron 備份腳本寫入中途被讀取(競態條件) 說明:若不使用原子性寫入,Cron 腳本寫入 .ipset 檔案的過程中若 Fail2ban 重啟,可能讀到寫到一半的不完整內容 解決:本文的備份腳本已使用 mktemp + mv -f 的原子性寫入方式,先寫暫存檔,完成後再搬移,確保讀取到的永遠是完整的備份 陷阱 15:fail2ban-client -t 失敗,顯示 ignoreip 解析錯誤 症狀:執行 fail2ban-client -t 時出現 "IP" is not a valid IP 或類似錯誤 原因:ignoreip 中仍保留了佔位文字(如 你的管理員IPv4),或填入了無效格式的IP 解決:重新檢查 /etc/fail2ban/jail.local,確認所有佔位文字已替換為實際IP或完全刪除 ------------------------ 日常維護指令速查 ------------------------ ---------------- 管理防火牆 ---------------- 手動啟動防火牆 /usr/local/bin/firewall.sh start 手動停止防火牆 (清除所有規則) /usr/local/bin/firewall.sh stop 測試模式 (修改規則後先測試) /usr/local/bin/firewall.sh test 查看統計 /usr/local/bin/firewall.sh stats 透過 systemd systemctl start firewall.service systemctl stop firewall.service systemctl restart firewall.service systemctl status firewall.service ---------------------- 查看 nftables 規則 ---------------------- 查看完整規則集 nft list ruleset 查看 input chain nft list chain inet filter input 即時監控被丟棄的封包 journalctl -k -f | grep "FW_DROP" 查看核心日誌 dmesg -w | grep "FW_DROP" -------------------- 管理 Fail2ban -------------------- 查看所有監獄 fail2ban-client status 查看特定監獄 (如 sshd) fail2ban-client status sshd 手動封鎖 IP fail2ban-client set sshd banip 1.2.3.4 解除封鎖 IP fail2ban-client set sshd unbanip 1.2.3.4 重新載入設定 fail2ban-client reload 查看日誌(最近 50 筆) journalctl -u fail2ban.service --no-pager -n 50 ------------------ 查看服務日誌 ------------------ 防火牆服務日誌 (本次開機) journalctl -u firewall.service --boot Fail2ban 服務日誌 (本次開機) journalctl -u fail2ban.service --boot 即時監控所有相關日誌 journalctl -f | grep -E "fail2ban|nftables|FW_DROP" ----------------- 管理封鎖清單 ----------------- 查看目前 IPv4 黑名單 nft list set inet filter f2b-blacklist4 查看目前 IPv6 黑名單 nft list set inet filter f2b-blacklist6 手動觸發備份 /usr/local/bin/backup-blacklist.sh 查看備份檔案 ls -lh /var/lib/fail2ban/*.ipset wc -l /var/lib/fail2ban/nftables-blacklist4.ipset ----------------------- Part 2 ----------------------- 等待LNMP服務都安裝配置完畢 再來做 Fail2ban Part 2 Edited June 3Jun 3 by Jack
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.