在 Web 服务器上实现 AI 主动防火墙 #
我们构建了一套系统:由本地 LLM 分析 Fail2Ban 固定阈值无法检测到的未知 Bot 模式和垃圾请求,每 15 分钟自动执行拦截。我们在现有的 nginx + Fail2Ban 架构之上新增了一层 AI 分析层,形成了三层防御结构。
Fail2Ban 很出色,但对”未知”威胁较弱 #
nginx UA 映射 + 速率限制 + Fail2Ban 的组合是 Web 服务器 Bot 防护的标准做法。将一小时内每分钟触发 10 次 403 错误的 IP 予以封禁。简单可靠。
然而,这种方式存在结构性弱点。
BASTION 让本地 LLM 对这些”人类能察觉、但固定规则捕捉不到的模式”作出判断。
三层防御结构 #
我们在现有的 nginx + Fail2Ban 架构之上新增了 BASTION 的 AI 分析层,形成了三层结构。
| 层级 | 职责 | 判断方式 | 响应速度 |
|---|---|---|---|
| 第一层 | nginx(UA 映射/速率限制/deny.conf) | 静态规则 | 即时(按请求) |
| 第二层 | Fail2Ban(与 firewalld 联动) | 固定阈值(每分钟 10 次 403 错误) | 1 分钟内 |
| 第三层 | BASTION(LLM 分析 → 通过 SSH 操作 firewalld) | 由 LLM 判断日志上下文 | 15 分钟内 |
各层独立运行。若 Fail2Ban 先行封禁了某 IP,BASTION 会执行去重检查以避免重复拦截。BASTION 的优势在于其”检测未知模式的能力”。
监控项目 #
BASTION 的 Web 服务器监控模板每 15 分钟分析以下 6 大类。
| 类别 | 数据来源 | 检测内容 |
|---|---|---|
| HTTP 状态分布 | 访问日志 | 403/429/5xx 集中的 IP。偏离正常状态的情况 |
| Bot User-Agent 检测 | 访问日志 | 未知 Bot User-Agent × 高频请求 |
| 垃圾请求 | 访问日志 | 语言切换轰炸等特定参数的垃圾请求 |
| 恶意软件检测 | ClamAV 日志 | 上传文件中检测到病毒 |
| SSH 认证失败 | sshd 日志 | Failed password / Invalid user |
| 应用程序错误 | PHP-FPM 日志 | FATAL/ERROR 级别 |
拦截机制 #
为何选择在 Web 服务器而非 WAN 边界防火墙上拦截 #
BASTION 的响应式防御通常在 WAN 边界防火墙 API(如 OPNsense)上封禁攻击源 IP(参见前一篇文章)。但在 Web 服务器通过 DNAT 对外暴露的配置下,WAN 边界防火墙的封禁列表可能无法拦截目标为 Web 服务器的流量。
因此,我们准备了一条独立的防御路径,直接在 Web 服务器的 firewalld + nginx deny.conf 中设置拦截规则。
BASTION (Analysis Server) → SSH connection (dedicated service account, public key authentication, minimum privilege sudo) → firewall-cmd drops IP (L3/L4 level) → nginx deny.conf appends IP + reload (L7 level)
SSH 连接安全 #
从分析服务器到 Web 服务器的 SSH 连接使用专用服务账户,sudo 权限仅限于必要的命令。
# sudoers authorized commands (nothing else can execute) svc-monitor ALL=(root) NOPASSWD: /usr/bin/firewall-cmd svc-monitor ALL=(root) NOPASSWD: /usr/sbin/nginx svc-monitor ALL=(root) NOPASSWD: /usr/bin/tee -a /etc/nginx/deny.d/* svc-monitor ALL=(root) NOPASSWD: /usr/bin/sed -i * /etc/nginx/deny.d/*
我们没有使用 root 登录,而是创建了专用服务账户,采用能够经受 ISMS 审计的最小权限设计。
与 Fail2Ban 的区别 #
| Fail2Ban | BASTION | |
|---|---|---|
| 判断方式 | 固定阈值(”每分钟 N 次 403″) | LLM 读取日志上下文并作出判断 |
| 未知模式 | 无法检测(需要更新规则) | 自动检测日志中的异常模式 |
| User-Agent 伪装 | 若不返回 403 则无法检测 | 根据请求频率 × 路径 × 时间段进行判断 |
| ClamAV 联动 | 无 | 检测到 FOUND → 追溯上传源 IP → 拦截 |
| 通知 | 邮件(依赖 MTA) | Slack(即时通知,可交互操作) |
| 解除拦截 | 由 bantime 固定决定 | 24 小时后自动解除 + 可从 Slack 即时解除 |
| 审计 | fail2ban.log | 结构化审计日志([HB_BLOCK]/[HB_UNBLOCK] 标签) |
BASTION 并非取代 Fail2Ban,而是与其共存。Fail2Ban 在 1 分钟内检测并封禁”403 洪水攻击”。BASTION 通过每 15 分钟一次的定期 LLM 分析,检测”未产生 403 但明显不自然的模式”。由于两者覆盖的领域不同,同时运行可以减少盲区。
实际运行情况 #
分析报告 #
通过每 15 分钟的定期分析,会自动输出 Web 服务器相关的部分。
Web 服务器详细分析
请求数:1,847
状态:200=1,650 / 403=112 / 429=45 / 5xx=0
403 集中 IP:xxx.xxx.156.12(40 次)— User-Agent:GPTBot/1.0
疑似 Bot User-Agent:”SomeNewBot/2.0″(180 次/15 分钟)— 未注册的 User-Agent
ClamAV:未检测到
SSH 失败:0 / PHP-FPM ERROR:0
自动执行拦截 #
🛡️ Web 服务器拦截执行
IP:xx.xxx.156.12
原因:bot_spam
firewalld:已添加 drop 规则
nginx deny:已应用
手动解除拦截:@OpenClaw-Monitor unblock xx.xxx.156.12
对 ClamAV FOUND 检测的自动响应 #
当 ClamAV 在上传文件中检测到恶意软件时,BASTION 会立即输出 CRITICAL 判定。ClamAV 本身只会隔离文件,而 BASTION 更进一步,从访问日志中识别出上传源 IP,并通过 firewalld 自动拦截。这是一种双重机制:文件隔离(ClamAV)+ 网络隔离(BASTION)。
nginx deny.conf 采用”尽力而为”设计 #
我们设计了 firewalld 拦截与 nginx deny.conf 的双重防御,但同时也设计成即使在未配置 nginx deny.conf 目录的环境下,仅靠 firewalld 也能提供防护。若 deny.conf 无法使用,会被记录为”已跳过”,firewalld 会单独继续运行。之后一旦添加了 nginx include 配置,nginx deny 将无需修改代码即可自动生效。这种设计可以根据环境的就绪程度逐步加强防护。
总结 #
我们为 Web 服务器新增了 BASTION 的 AI 分析层,构建了 nginx(第一层)→ Fail2Ban(第二层)→ BASTION(第三层)的三层防御体系。固定阈值无法捕捉的未知 Bot 模式和垃圾请求,会由本地 LLM 每 15 分钟自动检测并立即由 firewalld 拦截。
SSH 连接使用专用账户、最小权限 sudo 和公钥认证。nginx deny.conf 采用尽力而为设计,可根据环境就绪程度逐步启用。BASTION 与 Fail2Ban 共存,各自覆盖不同的领域。
BASTION 是一项可在封闭环境中实现 AI 安全监控的服务。