Fail2Ban高并发CPU飙升主因是默认配置未适配负载,需三步优化:改用pyinotify或systemd后端减少轮询;精简failregex避免回溯;收紧jail配置并移库至/dev/shm内存。

Fail2Ban 在高并发环境下 CPU 占用飙升,根本原因不是它“太重”,而是默认配置没适配真实负载。关键在于减少无效轮询、压缩匹配开销、控制状态存储——三者协同优化,通常可将 CPU 占用从 50%+ 降至 10% 以内。
选对日志监控后端,避开轮询陷阱
Fail2Ban 默认的 auto 后端在多数系统上会 fallback 到 polling,每秒多次扫描日志文件,是 CPU 持续飙高的主因之一。
- 本地日志(如
/var/log/auth.log):强制使用pyinotify,事件驱动,CPU 占用仅 5–10% - systemd 日志(
journald):明确指定backend = systemd,通过 journal API 接收日志事件,避免文件 I/O 唤醒 - 网络共享日志(NFS/Samba):只能用
polling,但应调大polling-interval(如设为 30 秒),降低扫描频次
配置位置:/etc/fail2ban/jail.local 中添加:
backend = pyinotify
精简正则表达式,砍掉回溯开销
一条低效的 failregex 可能让单核 CPU 满载。问题多出在贪婪匹配和捕获组滥用上,尤其在 SSH、Nginx 等高频日志中。
- 用
\S+替代.*,避免灾难性回溯 - 用非捕获组
(?:...)替代普通括号(...),减少内存分配与状态保存 - 删掉与封禁无关的字段(如端口号、SSH 协议版本),只保留
<host></host>和核心失败标识
例如优化 SSH 登录失败规则:
^Failed (?:password|publickey) for \S+ from收紧 jail 配置,减少内存与匹配压力
每个启用的 jail 都独立运行日志解析和状态管理,未使用的规则会白占资源。
- 禁用全部未运行服务的 jail,如服务器不跑 Apache,就关闭
[apache-badbots]、[php-url-fopen] - 调小
findtime(如从 600 秒改为 300 秒),缩短需缓存的失败记录时间窗口 - 限制单 jail 存储的匹配数:
dbmaxmatches = 3(默认 10),降低 SQLite 写入频率 - 缩短数据库清理周期:
dbpurgeage = 6h,防止历史数据堆积
把数据库搬到内存,消除磁盘 IO 拖累
Fail2Ban 默认使用 SQLite 数据库存储封禁状态和失败记录。在高并发下,频繁的随机写会导致 IO 等待,间接抬高 CPU 负载(因进程阻塞后重试)。
- 将数据库路径指向
/dev/shm/(tmpfs 内存文件系统):dbfile = /dev/shm/fail2ban.sqlite3 - 确保
/dev/shm有足够空间(建议 ≥ 64MB),并设置开机挂载参数size=128M - 配合
dbmaxmatches和dbpurgeage使用,避免内存无节制增长


















