fail2ban 1.1 常用 CLI 命令与工具详解
fail2ban 1.1.1 命令行实战:fail2ban-client 全子命令(服务控制/状态查询/封禁管理/动态 jail)、fail2ban-server 与 systemd、fail2ban-regex 过滤器调试、日志轮转与 flushlogs、常见报错速查,全程实测。
fail2ban 1.1 常用 CLI 命令与工具详解
目标:以 fail2ban 1.1.1 为准,详解日常运维最常用的命令行工具——
fail2ban-client(全功能管理入口)、fail2ban-server(服务端本体)、fail2ban-regex(过滤器调试器)——覆盖服务控制、状态查询、参数在线读写、动态 jail 管理、封禁管理、日志轮转与常见报错排查。全部命令与回显在 Ubuntu 22.04 实测(安装见《Ubuntu 22.04 安装 fail2ban 1.1.1 指南》,配置背景见《fail2ban 1.1 配置参数详解》)。
一、环境信息
- 操作系统:Ubuntu Server 22.04 LTS(x86_64),systemd 249;
- fail2ban 1.1.1(源码安装于 /usr/local),sshd jail(systemd journal 后端)+ nftables 默认动作;
- 版本实测:
fail2ban-client -V
fail2ban-server -V
fail2ban-regex -V
1.1.1
1.1.1
1.1.1
💡 说明:三个工具同源同版本。注意
python3 -c 'import fail2ban; print(fail2ban.version)'会报 AttributeError(顶层包没有 version 属性),查库版本应使用python3 -c "import fail2ban.version as v; print(v.version)"。
二、命令总览
| 命令 | 角色 | 典型用途 |
|---|---|---|
fail2ban-client | 客户端/管理入口(本篇主体) | 服务控制、jail 管理、封禁管理、参数热调 |
fail2ban-server | 服务端本体 | 一般不直接运行,由 systemd 托管;-xf 可前台调试 |
fail2ban-regex | 过滤器调试器 | 离线验证日志行/文件对 failregex 的命中率 |
fail2ban-testcases | 自带测试套件运行器 | 上游回归测试(维护者向) |
fail2ban-client 的命令清单(fail2ban-client -h 实测节选,按用途分组):
start starts the server and the jails
restart restarts the server
restart [--unban] [--if-exists] <JAIL> restarts the jail <JAIL> (alias
for 'reload --restart ... <JAIL>')
reload [--restart] [--unban] [--all] reloads the configuration without
restarting of the server
reload [--restart] [--if-exists] <JAIL> reloads the jail <JAIL>
stop stops all jails and terminate
the server
stop <JAIL> stops the jail <JAIL>. The jail is removed
unban --all unbans all IP addresses (in all
jails and database)
unban <IP> ... <IP> unbans <IP> (in all jails and database)
banned return jails with banned IPs as dict
banned <IP> ... <IP>] return list(s) of jails where
given IP(s) are banned
status gets the current status of the server
status --all [FLAVOR] gets the current status of all
jails and the server, optional
flavors: basic, cymru, short, stats
status <JAIL> [FLAVOR] gets the current status of <JAIL>
ping tests if the server is alive
flushlogs flushes the logtarget if a file
and reopens it
add <JAIL> <BACKEND> creates a new jail <JAIL> with
the given backend
三、fail2ban-client:服务控制
3.1 启动、停止与重启
日常由 systemd 托管(推荐入口):
systemctl enable --now fail2ban
systemctl restart fail2ban
配置变更后的三种生效方式(实测均正常):
fail2ban-client reload # 全部 jail 热重载
fail2ban-client reload sshd # 单 jail 热重载
实测回显:
OK
⚠️ 注意:
stop <JAIL>的帮助原文是 "stops the jail <JAIL>. The jail is removed"——停止动态 jail 的同时即从服务端移除该 jail(实测Jail stopped后再次操作报NOK: ('f2btest',)不存在)。不存在remove/delete子命令(实测Command ['remove', 'f2btest'] has failed. Received Exception('Invalid command')),老教程写法已失效。
3.2 存活探测与配置自检
fail2ban-client ping
fail2ban-client -t
实测回显:
Server replied: pong
OK: configuration test is successful
监控类脚本建议用 ping 做存活探测(退出码 0/非 0),改动配置前用 -t 做预检。
四、fail2ban-client:状态查询
4.1 status 与 status <JAIL>
$ fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd
封禁触发后的 status sshd 实测(127.0.0.1 爆破 3 次被封):
$ fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 3
| |- Total failed: 3
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 127.0.0.1
Filter 段是「当前计数窗口内的失败统计」,Actions 段是「封禁统计与封禁列表」,巡检盯这两段即可。
4.2 status --all 与 statistics
$ fail2ban-client status --all
Status
|- Number of jail: 1
|- Jail list: sshd
`- Status for the jails:
`- Jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
statistics 输出全景计数表(1.1.x 新版式,实测):
$ fail2ban-client statistics
║ ║ Filter ║ Actions
Jail ║ Backend ╟───────────╫───────────
║ ║ cur │ tot ║ cur │ tot
══════════╬══════════╬═══════════╬═══════════
sshd ║ systemd ║ 0 │ 0 ║ 0 │ 0
══════════╩══════════╩═══════════╩═══════════
4.3 get:单参数读取
$ fail2ban-client get sshd bantime
600
$ fail2ban-client get sshd findtime
600
$ fail2ban-client get sshd maxretry
5
$ fail2ban-client get sshd actions
The jail sshd has the following actions:
nftables
$ fail2ban-client get sshd journalmatch
Current match filter:
_SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
$ fail2ban-client get sshd logpath
No file is currently monitored
logpath 显示 No file is currently monitored 不代表异常:Debian/Ubuntu 系 sshd jail 默认 backend=systemd,读 journal 不读文件。动作级参数可两级下钻:
$ fail2ban-client get sshd action nftables actionban
nft add element inet f2b-table <addr_set> \{ <ip> \}
数据库路径与白名单:
$ fail2ban-client get dbfile
/var/lib/fail2ban/fail2ban.sqlite3
$ fail2ban-client get sshd ignoreip
No IP address/network is ignored
$ fail2ban-client get sshd ignoreself
False
💡 说明:
ignoreip显示为空、ignoreself为 False 是因为实验 jail.local 显式覆盖(默认为127.0.0.1/8 ::1与true,见《fail2ban 1.1 配置参数详解》)。
4.4 banned:封禁反查
$ fail2ban-client set sshd banip 192.0.2.99
1
$ fail2ban-client banned
[{'sshd': ['192.0.2.99']}]
$ fail2ban-client banned 192.0.2.99
[['sshd']]
$ fail2ban-client banned 192.0.2.100
[[]]
三种形态分别是「全部 jail 的封禁字典」「指定 IP 在哪些 jail 被封」「未被封时返回空列表」,适合做告警脚本的取数口。
五、fail2ban-client:封禁与白名单管理
5.1 手动封禁与解封
$ fail2ban-client set sshd banip 203.0.113.66
1
$ fail2ban-client status sshd | tail -4
|- Currently banned: 1
|- Total banned: 3
`- Banned IP list: 203.0.113.66
$ fail2ban-client set sshd unbanip 203.0.113.66
1
返回值 1 表示操作生效(0 通常意味着该 IP 已在封禁中)。封禁立即可在防火墙侧验证(nftables 集合注入,实测 nft list ruleset 出现 elements = { 203.0.113.66 })。带剩余时间的封禁列表:
$ fail2ban-client get sshd banip --with-time
203.0.113.66 2026-10-23 20:42:19 + 175 = 2026-10-23 20:45:15
全量解封(跨 jail 并清数据库记录):
$ fail2ban-client unban --all
1
5.2 白名单热维护
fail2ban-client set sshd addignoreip 10.0.0.0/8
fail2ban-client set sshd delignoreip 10.0.0.0/8
⚠️ 注意:
set addignoreip的修改保存在服务端内存里,重启即失效;持久化请写入 jail.local 的ignoreip行后reload。另外 1.1.x 默认ignoreself = true,本机 127.0.0.1 永远不会被封(实测日志Ignore 127.0.0.1 by ignoreself rule),本机联调需临时关闭。
六、fail2ban-client:动态 jail 管理(运行期建删 jail)
不写配置文件、纯命令行搭一个监控自定义日志的 jail,全流程实测:
$ : > /var/log/f2btest.log
$ fail2ban-client add f2btest4
Added jail f2btest4
$ fail2ban-client set f2btest4 addlogpath /var/log/f2btest.log
Current monitored log file(s):
`- /var/log/f2btest.log
$ fail2ban-client set f2btest4 addfailregex '.*sshd\[\d+\]: Failed password for .* from <HOST> port \d+ ssh2$'
The following regular expression are defined:
`- [0]: .*sshd\[\d+\]: Failed password for .* from (?:\[?(?:(?:::f{4,6}:)?(?P<ip4>(?:\d{1,3}\.){3}\d{1,3})|(?P<ip6>(?:[0-9a-fA-F]{1,4}::?|:){1,7}(?:[0-9a-fA-F]{1,4}|(?<=:):)))\]?|(?P<dns>[\w\-.^_]*\w)) port \d+ ssh2$
$ fail2ban-client set f2btest4 addaction dummy
dummy
$ fail2ban-client set f2btest4 bantime 600
600
$ fail2ban-client start f2btest4
Jail started
写入 3 条攻击行后立刻验证:
$ fail2ban-client status f2btest4
Status for the jail: f2btest4
|- Filter
| |- Currently failed: 0
| |- Total failed: 3
| `- File list: /var/log/f2btest.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 198.51.100.5
$ fail2ban-client status
Status
|- Number of jail: 2
`- Jail list: f2btest4, sshd
拆除(停止即移除):
$ fail2ban-client stop f2btest4
Jail stopped
四条实测教训(每条都真实踩过):
- 先建日志再启动,启动后追加的行才会被处理——jail 启动时从文件末尾开始读,预写入的行全部跳过(实测预写 3 行的 jail
Total failed: 0,改为空文件起步 + 启动后追加后立即 3 次命中并封禁)。 - 动态 jail 无 filter.d 的 prefregex 前缀剥离机制——
addfailregex必须自己消化主机名 进程[pid]:前缀(上面的正则带.*sshd\[\d+\]:才命中)。 - backend 不能事后 set——
set <jail> backend polling报Invalid command 'backend' (no set action or not yet implemented),后端在add <JAIL> <BACKEND>创建时指定。 - 动态 jail 不写盘,重启即消失——
systemctl restart fail2ban后status只剩 sshd(实测)。需要持久化的 jail 一律走 jail.d/*.local。
七、fail2ban-server 与 systemd 单元
服务端本体一般不手工启动,单元内实测执行行为:
$ grep ExecStart /lib/systemd/system/fail2ban.service
ExecStart=/usr/local/bin/fail2ban-server -xf start
-xf 即前台模式并跟随日志,排障时可临时 fail2ban-server -xf 观察启动全输出(Ctrl+C 退出)。生产环境统一走 systemctl;启动失败的报错以 journalctl -u fail2ban -n 50 为准(典型案例:源码安装后单元路径指错导致 203/EXEC,处理见安装篇 5.5 节)。
八、fail2ban-regex:过滤器调试器
8.1 用法形态
Usage: /usr/local/bin/fail2ban-regex [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]
三个位置参数的取值形态(帮助实测):LOG 可以是日志行字符串、日志文件路径(如 /var/log/auth.log)、或 systemd-journal;REGEX 可以是正则字符串、jail/过滤器名(可带参数,如 sshd[mode=aggressive])、过滤器文件路径;IGNOREREGEX 同理。常用选项:-d 自定义日期模式、-L 多行上限、-m 覆盖 journalmatch、-v 提升输出详度、-D 生成 debuggex.com 调试链接。
8.2 文件级测试(实测)
用真实爆破日志验证 sshd 过滤器:
fail2ban-regex /var/log/auth.log.1 /etc/fail2ban/filter.d/sshd.conf
实测输出(原文):
Running tests
=============
Use filter file : sshd, basedir: /etc/fail2ban
Use maxlines : 1
Use datepattern : {^LN-BEG} : Default Detectors
Use log file : /var/log/auth.log.1
Use encoding : UTF-8
Results
=======
Prefregex: 23 total
| ^(?P<mlfid>(?:\[\])?\s*(?:<[^.]+\.[^.]+>\s+)?(?:\S+\s+)?(?:kernel:\s?\[ *\d+\.\d+\]:?\s+)?(?:@vserver_\S+\s+)?(?:(?:(?:\[\d+\])?:\s+[\[\(]?sshd(?:-session)?(?:\(\S+\))?[\]\)]?:?|[\[\(]?sshd(?:-session)?(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:?)\s+)?(?:\[ID \d+ \S+\]\s+)?)(?:(?:error|fatal): (?:PAM: )?)?(?P<content>.+)$
`-
Failregex: 21 total
|- #) [# of hits] regular expression
| 4) [7] ^Failed (?:<F-NOFAIL>publickey</F-NOFAIL>|\S+) for (?P<cond_inv>invalid user )?<F-USER>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)</F-USER> from <HOST>(?: (?:port \d+|on \S+)){0,2}(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
| 14) [7] ^<F-NOFAIL>pam_[a-z]+\(sshd:auth\):\s+authentication failure;</F-NOFAIL>(?:\s+(?:(?:logname|e?uid|tty)=\S*)){0,4}\s+ruser=<F-ALT_USER>\S*</F-ALT_USER>\s+rhost=<HOST>(?:\s+user=<F-USER>\S*</F-USER>)?(?: (?:port \d+|on \S+|\[preauth\])){0,3}\s*$
| 20) [7] ^<F-NOFAIL><F-MLFFORGET>(?:Connection (?:closed|reset)|Disconnect(?:ed|ing))</F-MLFFORGET></F-NOFAIL>(?: (?:by|from))?(?: (?:invalid|authenticating) user <F-USER>\S+|.*?</F-USER>)?(?: from)? <ADDR>(?: (?:port \d+|on \S+)){0,2}(?:: (?!Too many authentication failures)[^\[]+)?(?: \[preauth\])?\s*$
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
| [23] {^LN-BEG}(?:DAY )?MON Day %k:Minute:Second(?:\.Microseconds)?(?: ExYear)?
`-
Lines: 23 lines, 14 ignored, 7 matched, 2 missed
[processed in 0.00 sec]
解读:23 行日志里 14 行被过滤忽略(成功登录等无关行)、7 行命中 failregex(#4 密码失败 3 次 + #14 PAM 失败 + #20 连接关闭类各按次数计)、2 行 missed(sshd 启动横幅无 IP 可提取,属预期)。-v 可展开每条命中行的详情。
8.3 单行测试(实测)
调试自定义正则最快的方式,直接喂一行日志 + 一条正则:
fail2ban-regex 'Oct 23 20:41:01 web01 sshd[4670]: Failed password for admin from 203.0.113.9 port 41848 ssh2' 'sshd(?:\[\d+\])?: Failed password for .* from <HOST> port \d+ ssh2'
实测结果摘要:
Date template hits:
|- [# of hits] date format
...
Lines: 1 lines, 0 ignored, 1 matched, 0 missed
⚠️ 注意:直接对
/var/log/auth.log测试前先确认文件非空——logrotate 刚轮转过时 auth.log 为新空文件,实测输出Lines: 0 lines, 0 ignored, 0 matched, 0 missed,应改测auth.log.1。
8.4 journal 模式测试
sshd jail 实际读 journal,等价调试命令(需 python3-systemd):
fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf
fail2ban-regex 'systemd-journal[_COMM=sshd]' /etc/fail2ban/filter.d/sshd.conf
第一种扫描全 journal,第二种用 journalctl 语法收敛范围,输出结构与文件模式一致。
九、日志轮转与日常运维
9.1 fail2ban 自身日志的轮转
包自带的 /etc/logrotate.d/fail2ban 实测全文:
/var/log/fail2ban.log {
weekly
rotate 4
compress
# Do not rotate if empty
notifempty
delaycompress
missingok
postrotate
fail2ban-client flushlogs 1>/dev/null
endscript
# If fail2ban runs as non-root it still needs to have write access
# to logfiles.
# create 640 fail2ban adm
create 640 root adm
}
关键在 postrotate 调用 fail2ban-client flushlogs:轮转后通知服务端关闭旧文件句柄并打开新日志,无需重启。实测执行 logrotate -f /etc/logrotate.conf 后:
-rw-r----- 1 root adm 14420 Oct 23 20:45 /var/log/fail2ban.log.1
-rw-r----- 1 root adm 108 Oct 23 20:45 /var/log/fail2ban.log
$ tail -1 /var/log/fail2ban.log
2026-10-23 20:45:37,411 fail2ban [4399]: INFO rollover performed on /var/log/fail2ban.log
rollover performed 即 flushlogs 成功重开日志的凭证。
⚠️ 注意:绕过 /etc/logrotate.conf、直接
logrotate -f /etc/logrotate.d/fail2ban会因父目录属组触发报错(实测:error: skipping "/var/log/fail2ban.log" because parent directory has insecure permissions ... Set "su" directive)。常规随系统的 weekly 轮转走 logrotate.conf 全局策略不受影响;若必须单测,往单元里加一行su root adm。
9.2 被监控日志(logpath)的轮转
文件后端 jail 的 logpath 被外部轮转(mv 重命名 + 新建同名文件)时,fail2ban 靠 backend 事件感知并跟随新文件,被移走的旧文件剩余内容可继续消化——这是官方设计行为;本文实测环境 sshd jail 走 journal 后端(无文件轮转问题),文件后端轮转场景未单独复测,上线前建议用 8.2 的方法对轮转后的 .1 文件做一次补测,确认历史窗口可回溯。set <JAIL> addlogpath <FILE> 'tail' 的 'tail' 参数控制是否只从文件尾部开始(帮助实测存在该选项)。
9.3 数据库维护
ls -la /var/lib/fail2ban/fail2ban.sqlite3
sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 'select ip,jail,bancount,bantime from bips;'
sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 'select count(*) from bans;'
bips 是当前/最近封禁与复犯计数(递增禁时的依据),bans 是历史封禁流水;dbpurgeage(默认 1d)控制清理节奏。改参数调优见《fail2ban 1.1 配置参数详解》。
十、常见报错速查表(全部实测复现)
| 报错(实测原文) | 原因 | 处置 |
|---|---|---|
Command ['remove', 'f2btest'] has failed. Received Exception('Invalid command') | 无 remove/delete 子命令 | stop <JAIL> 停止即移除 |
NOK: ('f2btest',) / The jail 'f2btest' already exists | jail 不存在 / 重名添加 | 先 status 核对;重复 add 前先 stop |
Received ValueError('Action dummy already exists') | 同一 jail 重复 addaction | 每个动作名只挂一次 |
Invalid command 'backend' (no set action or not yet implemented) | backend 不能事后修改 | add <JAIL> <BACKEND> 创建时指定 |
Received DuplicateJailException('f2btest') | 动态 jail 重名 | stop 后重建或换名 |
Detected a log entry 1m 57s after the current time ... Line with odd timestamp: ... | 测试日志时间戳超前/时区错 | 用系统实时时间造测试行 |
Ignore 127.0.0.1 by ignoreself rule | 1.1.x 默认 ignoreself=true | 本机联调临时 ignoreself = false |
logrotate: parent directory has insecure permissions ... Set "su" directive | 直接调用单元文件轮转 | 加 su root adm 或走 logrotate.conf |
封禁期间 ssh: connect to host ... port 22: Connection refused | 封禁生效的正常表现(nftables reject) | unbanip 或等 bantime 到期 |
ERROR Failed to access socket path: /var/run/fail2ban/fail2ban.sock | 服务未运行 | systemctl enable --now fail2ban |
十一、参考链接
- 官方 man 手册 fail2ban-client:https://manpages.ubuntu.com/manpages/jammy/en/man1/fail2ban-client.1.html
- 官方 man 手册 fail2ban-regex:https://manpages.ubuntu.com/manpages/jammy/en/man1/fail2ban-regex.1.html
- 官方 man 手册 fail2ban-server:https://manpages.ubuntu.com/manpages/jammy/en/man1/fail2ban-server.1.html
- GitHub 官方仓库(源码 bin/ 目录含三工具实现):https://github.com/fail2ban/fail2ban
- 官方 Wiki(FAQ 与最佳实践):https://github.com/fail2ban/fail2ban/wiki