fail2ban 1.1 常用 CLI 命令与工具详解

fail2ban 1.1.1 命令行实战:fail2ban-client 全子命令(服务控制/状态查询/封禁管理/动态 jail)、fail2ban-server 与 systemd、fail2ban-regex 过滤器调试、日志轮转与 flushlogs、常见报错速查,全程实测。

fail2ban安全测试2026/10/24

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

四条实测教训(每条都真实踩过):

  1. 先建日志再启动,启动后追加的行才会被处理——jail 启动时从文件末尾开始读,预写入的行全部跳过(实测预写 3 行的 jail Total failed: 0,改为空文件起步 + 启动后追加后立即 3 次命中并封禁)。
  2. 动态 jail 无 filter.d 的 prefregex 前缀剥离机制——addfailregex 必须自己消化 主机名 进程[pid]: 前缀(上面的正则带 .*sshd\[\d+\]: 才命中)。
  3. backend 不能事后 set——set <jail> backend polling 报 Invalid command 'backend' (no set action or not yet implemented),后端在 add <JAIL> <BACKEND> 创建时指定。
  4. 动态 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 existsjail 不存在 / 重名添加先 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 rule1.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

十一、参考链接