本教程专为使用 --network host 模式运行 Nginx 容器的场景设计。在此模式下,Fail2Ban 的配置比 Bridge 模式更简单、更高效,因为我们直接在宿主机上处理日志和封禁,无需干预 Docker 的 NAT 转发链。
📌 环境与前提
💡 Host 模式的限制提示
在 Host 模式下,Nginx 容器将直接使用宿主机的网络堆栈。这意味着容器使用的端口(如 80/443)会占用宿主机的端口,不能再被宿主机上的其他服务使用。
第一步:确认容器以 Host 模式运行
请确保您已使用 Host Network 模式启动容器,并正确挂载了日志卷,以便 Fail2Ban 能够读取宿主机上的日志文件。
Bash
# 停止并删除旧容器
docker rm -f nginx01
# 启动新容器( Host 模式)
docker run -d \
--name nginx01 \
--restart always \
--network host \
-v "/root/nginx/conf/nginx.conf:/etc/nginx/nginx.conf" \
-v "/root/nginx/html:/usr/share/nginx/html" \
-v "/root/nginx/cert:/etc/nginx/cert" \
-v "/root/nginx/log:/var/log/nginx" \
--add-host=host.docker.internal:host-gateway \
nginx
第二步:配置 Fail2Ban 过滤器 (filter.d)
我们需要创建规则来定义何种行为属于恶意攻击。
1. 防恶意扫描( Bad Request )
拦截扫描敏感文件(如 .env, wp-login.php)的攻击者,通常伴随 400/404 等错误响应码。
Bash
sudo nano /etc/fail2ban/filter.d/nginx-bad-request.conf
Ini, TOML
[Definition]
# 优化后的 failregex 匹配标准 Nginx 日志格式
failregex = ^<HOST> - \S+ \[.*\] "(GET|POST|HEAD) .*\.(php|asp|aspx|jsp|cgi|env|git|yml|sql|bak|tar|gz|zip|rar|sh) HTTP.*" (400|401|403|404) .*$
^<HOST> - \S+ \[.*\] "(GET|POST|HEAD) .*/(phpmyadmin|admin|setup|manager|dashboard|wp-login|xmlrpc).* HTTP.*" (400|401|403|404) .*$
ignoregex =
2. 防高频 CC 攻击( Anti-Flood )
拦截请求频率过高的 IP。我们使用 ignoregex 来排除静态资源(图片、CSS 等),以避免误封。
Bash
sudo nano /etc/fail2ban/filter.d/nginx-cc.conf
Ini, TOML
[Definition]
# 优化后的 failregex 匹配任何非忽略的请求
failregex = ^<HOST> - \S+ \[.*\] "(GET|POST|HEAD).*HTTP.*" .*$
# 忽略图片、CSS、JS 等静态资源,防止正常用户的请求被计入
ignoregex = \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|mp4|webm|webp) HTTP
第三步:配置监狱文件(jail.local)
这是 Host 模式配置的重点。由于流量直接经过宿主机网络,我们不需要指定 chain = DOCKER-USER。Fail2Ban 将直接作用于宿主机的标准 INPUT 链。
Bash
sudo nano /etc/fail2ban/jail.local
Ini, TOML
[DEFAULT]
# 白名单 IP:即使这些 IP 触发规则也不会被封
# 建议加上 localhost、内网 IP 段、以及您常用设备的 IP
ignoreip = 127.0.0.1/8 192.168.0.0/16 10.0.0.0/8
# 默认封禁时间:1 小时
bantime = 1h
# 查找时间窗口:10 分钟内
findtime = 10m
# 最大尝试次数:5 次
maxretry = 5
# Host 模式动作配置:直接使用标准的 iptables-multiport 即可
banaction = iptables-multiport
# ==========================================
# 规则 1:防止恶意扫描 (nginx-bad-request)
# ==========================================
[nginx-bad-request]
enabled = true
logpath = /root/nginx/log/access.log
filter = nginx-bad-request
port = 80,443
maxretry = 3 # 3 次扫描即封禁
bantime = 24h # 封禁时间较长
action = %(banaction)s[name=NGINX-BAD-REQUEST]
# ==========================================
# 规则 2:防止 CC 攻击 (nginx-cc)
# ==========================================
[nginx-cc]
enabled = true
logpath = /root/nginx/log/access.log
filter = nginx-cc
port = 80,443
findtime = 60 # 查找时间窗口:60 秒 (1 分钟)
# 允许每分钟 120 次非静态资源请求,超过即视为 CC 攻击
maxretry = 120
bantime = 2h # 封禁 2 小时
action = %(banaction)s[name=NGINX-CC]
第四步:重启与验证
1. 重启 Fail2Ban
应用新的配置。
Bash
sudo systemctl restart fail2ban
2. 验证状态
确认您的两个监狱(Jail)已正确加载并处于活动状态。
Bash
sudo fail2ban-client status
您应该看到:
nginx-bad-requestnginx-cc
3. 验证防火墙规则
检查宿主机的 INPUT 链,确认 Fail2Ban 已创建用于封禁的 Jump Target。
Bash
sudo iptables -L INPUT -n
如果您的系统内网卡(如 docker0 或 br-xxx)出现在 INPUT 链之前,则封禁生效。当有 IP 被封禁时,再次查看 iptables -L 应该会在 Fail2Ban 相关的 Target 下看到针对目标 IP 的 DROP 或 REJECT 记录。
✅ 您的 Nginx 容器已在 Host 模式下成功集成 Fail2Ban,具备抵御恶意扫描与 CC 攻击的能力!
评论区