在 AI 工作站、個人 Homelab、NAS、PVE、Docker 乃至雲端主機之間,近年最大的共同點,就是只要你的機器「有對外的 port」,它就會被掃描,而且很快。
無論你是否對外暴露 IP,公共 IPv4/IPv6 空間每天都有大量殭屍網路設備和機器在掃描 SSH、HTTPS 管理介面、NAS API、Redis、PostgreSQL、WordPress、Nginx Proxy、甚至是 AI 推論介面(如 OpenWebUI、Ollama、ComfyUI、VLLM dashboard),近期思科 Cisco 就警告有大量AI 伺服器在網路上裸奔。
對於許多用戶來說,最怕的不是伺服器掛掉,而是伺服器被拿去「挖礦」、「跳板攻擊」、「代理流量濫用」、「透過容器逃逸入侵」等。因此,在防火牆之前加上一層 Fail2Ban 的自動封鎖機制,已成為中小企業、AI 開發者與家庭伺服器環境中最常見的第一道主動式防禦,想辦法避免自己的 AI 伺服器、NAS 伺服器、容器服務或虛擬機伺服器被惡意程式當作跳板來利用,是首要的資安防護要務。
為什麼老字號的 Fail2Ban 仍然是穩定、實用的基礎防線?
CyberQ 觀察,社群常會討論 Fail2Ban vs CrowdSec,兩者都能針對惡意請求進行自動封鎖,但定位完全不同:
CrowdSec 是強大但複雜的「雲端威脅聯防」
提供全世界即時黑名單(類似 CDN WAF 的 Threat Intel),有豐富的 parser、scenario、bouncer,可連動 Cloudflare、NGINX、Firewall,但學習成本高、配置多、資源消耗也較高。
在雲端主機上最常見問題是,parser 不符合 Linux 發行版的 log 格式,或者是bouncer 與 container 網路互動可能與 nftables 產生衝突,這比較適合專門的資安工程師、企業 SOC、人多的大型環境。
Fail2Ban 是 「一次設定,安靜工作」的輕量級防護
Fail2Ban 的最大優點是,部署難度低,資源用量非常小(RAM 通常 < 20MB),適合 CPU 小的 NAS、迷你機、雲端 VPS、大量 Docker 節點,不需要外部威脅情資也能有效擋掉 90% 惡意流量。
即使系統、Docker、Proxy 架構複雜,也能用簡單 Regex 與 iptables/nftables 封鎖,Fail2Ban 是能讓伺服器變得「安靜」的工具。你會在部署後幾小時,立刻看見大量惡意 IP 被自動清理。
實務觀察:為什麼辦公室機房環境、 Homelab 與雲端主機都需要 Fail2Ban?
實測資料(亞洲市場、日本、韓國、北美等地):
公開網路 IP 隨便放一個 SSH 端口,5 分鐘內就被爆擊
SSH 每日平均暴力破解次數:3000+
Nginx 反向代理探測:20000+
NAS / API 掃描:100+
Redis、PostgreSQL、MongoDB 未認證存取探測:持續存在
AI 推論連接埠(如 /v1/chat/completions)遭掃描:2024 年後急速上升
Docker 預設網路會「蓋掉」你的封鎖規則
若你的 Fail2Ban 只下在 INPUT 鏈,Docker 會蓋掉你加的規則:
透過 DOCKER 或 DOCKER-USER 鏈,外部流量可能直接繞過 Fail2Ban
Cloudflare/CDN 後面會看到 Proxy IP,而非真實來源
這是最多人「Ban 了卻還接得進來」的原因。
NAS / AI 伺服器的 Web UI 常被掃到破表
像是:
QNAP / Synology Web UI
Proxmox VE / TrueNAS
Portainer / Nginx Proxy Manager
ComfyUI
OpenWebUI / FastAPI 模型 API
這些 UI 頻繁遭駭客積極探測,但很少人會做自動封鎖,反而形成防禦弱點。
Fail2Ban 安裝方式
軟體安裝
1、使用套件管理器
大多數 Linux 發行版都已內建 Fail2Ban,這是最快的方式:
Bash
Debian/Ubuntu
sudo apt update && sudo apt install fail2ban
CentOS/RHEL/AlmaLinux
sudo yum install fail2ban
2、原始碼安裝
如果你需要最新功能或修復特定 Bug,可以選擇原始碼安裝。 前置需求:Python >= 3.5, python-setuptools
Bash
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban
sudo python3 setup.py install
驗證安裝
fail2ban-client version
基礎組態配置:jail.local
Fail2Ban 的核心邏輯在於 jail(監獄)。安裝後,請不要直接修改 /etc/fail2ban/jail.conf,因為軟體更新時會覆蓋此檔案。
請建立一個新檔案 /etc/fail2ban/jail.local,Fail2Ban 會優先讀取此處的設定來覆蓋預設值。
Ini, TOML
[DEFAULT]
白名單:永遠不會被 Ban 的 IP (建議加入公司或組織、家中固定 IP 或內網網段)
ignoreip = 127.0.0.1/8 192.168.1.0/24
Ban 執行動作:預設使用 iptables-multiport
banaction = iptables-multiport
被 Ban 的時間長度 (例如 24小時)
bantime = 24h
統計視窗時間:在此時間內累積錯誤次數
findtime = 10m
最大錯誤嘗試次數
maxretry = 3
SSH 防護 (必開)
[sshd]
enabled = true
backend = auto
port= ssh
設定完成後,重啟服務生效:
Bash
sudo systemctl restart fail2ban
典型參數建議(更符合真實攻擊情境)
比起預設值,CyberQ 建議:
bantime = 24h # 或 7d(建議在公網使用)
findtime = 10m
maxretry = 3
實戰:Docker + Nginx Proxy Manager(NPM)的 Fail2Ban 可用方案
CyberQ 彙整社群最常見的兩大雷
雷 1:NPM 日誌格式不是標準 Nginx
如果你直接套用 /etc/fail2ban/filter.d/nginx-*,
Fail2Ban 完全看不懂你的日誌,自然不會封鎖任何人。
雷 2:Fail2Ban 封鎖 INPUT 鏈 → Docker 直接繞過
Docker 預設 NAT 設計如下:
PREROUTING → DOCKER —→ 最後才到 INPUT
許多社群討論中最常見抱怨:
「我明明看到 Fail2Ban 已經 Ban 到爆,但攻擊者還是能一直掃!」
原因就是規則被 Docker NAT 先處理,Fail2Ban 根本攔不到。
正確方法:直接打 DOCKER-USER 鏈
實務現場建議:如果你架在雲端主機(Linode、Vultr、GCP、Oracle、AWS)
公網 VPS 建議加上:
Fail2Ban
雲端防火牆限縮來源(例如只允許台灣 or 公司 IP)
非 22 port SSH
關閉密碼登入,強制 SSH Key
限制 API / Dashboard 的來源 IP
若跑 AI 模型 API,務必搭認證層或 Token
實務 Tips:Fail2Ban 最常出現「誤判」與「沒攔到」的情況
CyberQ 彙整我們使用上常見的問題如下 :
情況 1:Fail2Ban 有偵測,但沒成功封鎖
請檢查:
你的防火牆是否是 nftables(Debian12/Ubuntu22.04 之後常見)
Fail2Ban 預設走 iptables,若你的系統已啟用 nftables,其管理的 iptables 其實是「compat 模式」,規則可能無效。
Docker 蓋掉 INPUT 鏈
必須打 DOCKER-USER。
情況 2:誤 ban
最常見的是:
Web 前端 404
CDN 調用網站資源(Cloudflare / QUIC)
靜態資源(*.css, *.js, *.ico)找不到時被視為攻擊
你的 filter 規則需要加上 ignoreregex
情況 3:Fail2Ban 對高頻掃描無效
通常原因是:
maxmatches 太低
findtime 太短
掃不到真正的來源 IP(被 Proxy 遮住)
解決方式:
maxmatches ≥ 100
findtime ≥ 5–10 分鐘
Forward 真實 IP(NPM / Traefik / HAProxy)
部署 Fail2Ban 後最明顯的效果,這是來自許多 Homelab 使用者與 VPS 經營者的共同心得,也就是 SSH 暴力破解幾乎消失。
NPM、Portainer、Grafana、PGAdmin 等面板從「一直被掃」變得乾淨,機器冷靜許多,CPU 爆滿、頻寬異常減少,日誌變得乾淨、可分析,而減少被垃圾流量洗版的情況,同時 AI 推論介面不再被大量探測。對於任何希望「不被利用、不被掃爆、不被暴力破解」的伺服器來說,Fail2Ban 是最低成本立即提升安全的解法。
QNAP NAS 版:突破容器限制,利用 SSH 橋接技術的實務防禦指南
這個方法適用於 QTS / QuTS hero + Container Station / Portainer,QNAP NAS 雖然是許多 Homelab、AI 儲存節點、家用伺服器的中心,但其保護機制與一般 Linux 略有不同。雖然 QNAP 內建 QuFirewall,但它屬於被動防禦(除非手動設定黑名單)。我們要做的,是讓 Fail2Ban 擔任「偵察兵」,一旦發現惡意 IP,就自動通知 QuFirewall 進行封鎖。
但在實作上,這裡有一個最大的技術挑戰:「容器隔離性」。
當 Fail2Ban 跑在 Container Station(Docker)內時,它是一個獨立的 Linux 環境,無法直接執行 QNAP 宿主機(Host)上的 /sbin/firewall_rule 指令。這也是為什麼網路上許多教學照著做卻失敗的原因。
正確解法:SSH Loopback 橋接模式
我們採用 DevOps 常見的自動化技巧:讓容器內的 Fail2Ban 透過 SSH 金鑰認證,自動連回 QNAP 宿主機執行防火牆指令。這樣既不用破解系統底層,也能整合 QuFirewall。
以下是 CyberQ 整理的標準三步驟:
步驟 1:在 QNAP 宿主機建立 SSH 信任金鑰
首先,我們需要產生一把「鑰匙」,讓容器可以免密碼登入宿主機。 請透過 SSH 終端機連入您的 QNAP(使用 admin 帳號),執行以下指令:
1. 建立存放金鑰的資料夾 (建議放在 Container 共用資料夾下以利掛載)
mkdir -p /share/Container/fail2ban/ssh_keys
2. 產生金鑰 (出現提示時一路按 Enter,不要設定密碼)
ssh-keygen -t rsa -b 4096 -f /share/Container/fail2ban/ssh_keys/id_rsa -N “”
3. 將公鑰加入 QNAP 自身的授權清單 (允許自己登入自己)
cat /share/Container/fail2ban/ssh_keys/id_rsa.pub >> /root/.ssh/authorized_keys
4. 修正權限,否則 SSH 安全機制會拒絕連線
chmod 600 /share/Container/fail2ban/ssh_keys/id_rsa
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
步驟 2:部署 Fail2Ban 容器 (掛載金鑰與日誌)
接著,在 Container Station 中部署 Fail2Ban。我們推薦使用 docker-compose 方式部署,因為需要掛載多個路徑。
重點在於:除了掛載 Log,還要將剛剛產生的 私鑰 (id_rsa) 掛載進容器。
docker-compose.yml 範例:
version: '3'
services:
fail2ban:
image: crazymax/fail2ban:latest
container_name: fail2ban
network_mode: host # 強烈建議:使用 Host 模式,網路單純且效能最佳
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ./data:/data
# --- 掛載 QNAP 的 Log 路徑 (請依您的機型實際路徑調整) ---
# QTS 系統 Log 通常在 /mnt/HDA_ROOT/.logs 或 /share/CACHEDEV1_DATA/.qnap_logs
- /share/CACHEDEV1_DATA/.qnap_logs:/qnap_logs:ro
- /share/CACHEDEV1_DATA/logs:/qnap_logs_sys:ro
# --- (關鍵) 掛載 SSH 私鑰,讓容器能連回宿主機 ---
- /share/Container/fail2ban/ssh_keys/id_rsa:/root/.ssh/id_rsa:ro
environment:
- TZ=Asia/Taipei
restart: always步驟 3:設定 Action 與 Jail (建立橋接)
最後,告訴 Fail2Ban 抓到壞人時該怎麼做。我們不直接下指令,而是透過 ssh 遠端執行。
1. 建立 QNAP 專用動作檔 在 data/action.d/ 目錄下新增檔案 qnap-qufirewall.conf:
[Definition]
# 說明:
# -o StrictHostKeyChecking=no : 略過首次連線指紋確認,更安全的做法是在容器啟動時預先將宿主機指紋寫入 /root/.ssh/known_hosts。
# -i /root/.ssh/id_rsa : 使用掛載進來的金鑰
# admin@127.0.0.1 : 連回宿主機 (因使用 host 網路模式)
actionban = ssh -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa admin@127.0.0.1 "/sbin/firewall_rule add deny <ip>"
actionunban = ssh -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa admin@127.0.0.1 "/sbin/firewall_rule del deny <ip>"/sbin/firewall_rule 的實際路徑可能因 QTS 版本而異,建議讀者先在宿主機執行 which firewall_rule 確認。
2. 設定 Jail 規則 修改 data/jail.local,啟用 SSH 防護並指定動作:
[sshd]
enabled = true
# 指向掛載進來的 QNAP SSH Log (通常是 auth.log 或 conn.log)
logpath = /qnap_logs_sys/auth.log
filter = sshd
# 使用剛剛建立的 SSH 橋接動作
action = qnap-qufirewall
maxretry = 5
bantime = 1d部署完成並重啟容器後,當 Fail2Ban 偵測到暴力破解時:
1、容器會透過 SSH 連回 NAS。
2、執行 firewall_rule add deny。
3、你可以打開 QuFirewall 防火牆介面,在「設定檔」或「黑名單」中,看到惡意 IP 被動態加入。
這是在 QNAP 環境下,兼顧 Docker 靈活性與 QuFirewall 防護的整合方案。
推薦參考資料 :











