Skip to content

18.5 Fail2Ban(基于 IPFW、PF 与 IPF)

网络安全实践中,暴力破解(brute-force attack)是针对身份认证系统的常见威胁。

Fail2Ban 是一款基于日志的入侵防御系统(Intrusion Prevention System, IPS),通过动态更新防火墙规则实现自适应访问控制,为服务器提供实时防护。

根据 官方说明,Fail2Ban 通过更新系统防火墙规则,拒绝多次身份验证失败的 IP 地址发起的新连接(详见 Fail2Ban 工作原理)。Fail2Ban 几乎完全由 Python 实现(Python 代码占比约 96%)。本节适配了 FreeBSD 常见的三种防火墙(IPFW、PF 与 IPF),无需同时配置所有防火墙,只需选择其中一种即可。

18.5.1 安装 Fail2Ban

Fail2Ban 的安装过程如下,用户可选择 pkg 或 Ports 安装。

  • 使用 pkg 安装:
sh
# pkg install security/py-fail2ban
  • 或者使用 Ports 安装:
sh
# cd /usr/ports/security/py-fail2ban/
# make install clean

安装完成后,需启用服务使其开机自动启动。

  • 启用 fail2ban 服务:
sh
# service fail2ban enable

18.5.2 查看 Fail2Ban 安装后的说明

安装完成后,可通过以下命令查看软件包提供的配置说明。

sh
# pkg info -D security/py-fail2ban

18.5.3 Fail2Ban 配置解读

下文将详细解读 Fail2Ban 的配置。

注意

此处的 jail 并非 BSD 系统中的 jail(容器)。在 Fail2Ban 中,jail 是指对特定服务的监控和封禁配置单元,每个 jail 对应一个需要防护的服务(如 SSH、FTP 等)。

Fail2Ban 的工作流程分为两个核心部分:filter(过滤器)负责解析日志,识别失败的登录尝试;action(动作)负责调用防火墙规则执行封禁操作。

涉及的文件结构:

sh
/usr/local/etc/fail2ban/
├── jail.conf
├── filter.d/
   ├── bsd-sendmail.conf
   ├── bsd-sshd.conf
   ├── bsdftp.conf
   ├── courier-auth.conf
   ├── mssql-auth.conf
   ├── murmur.conf
   ├── mysqld-auth.conf
   ├── nginx-botsearch.conf
   ├── slapd.conf
   ├── softethervpn.conf
   ├── sogo-auth.conf
   └── sshd.conf
├── action.d/
   ├── bsd-ipfw.conf
   ├── ipfw.conf
   └── ipfilter.conf
└── jail.d/
    └── sshd.conf

配置文件示例为 /usr/local/etc/fail2ban/jail.conf 文件(请勿直接编辑,参见上文说明),下文仅列出本书所需内容:

ini
# DEFAULT 是全局定义的配置,之后每个 jail 都可以单独覆盖这些设置。

[DEFAULT]

# "ignoreip" 可以是单个 IP 地址、CIDR 子网或 DNS 主机名列表。Fail2Ban
# 不会封禁列表中匹配的主机。多个地址可以使用空格或逗号分隔
# "ignoreip" 即白名单
# ignoreip = 127.0.0.1/8 ::1

# "maxretry" 默认重试次数
maxretry = 5

# 如果主机在过去的 "findtime" 秒内产生了 "maxretry" 次失败,主机将被封禁。
# 即定义封禁频率。
findtime = 10m

# "bantime" 表示主机被封禁的时间,可用秒为单位的整数或时间缩写格式(m 表示分钟,h 表示小时,d 表示天,w 表示周,mo 表示月,y 表示年)
# 即多长时间后可重试。
bantime  = 10m

[sshd]
# enabled = true
#
# 参见 jail.conf(5)

# "filter" 定义了 jail 所使用的过滤器。 ①
# 在默认情况下,jail 的名称与其过滤器名称相匹配。
#
filter = %(__name__)s[mode=%(mode)s]
# 例如:
# filter = sshd[mode=aggressive]
#
# 操作快捷方式。用于定义 action 参数。

# Fail2Ban 还需要防火墙来执行封禁动作。
# 默认封禁操作(例如 iptables、iptables-new、iptables-multiport、shorewall 等)。 ②
# 它用于定义 action_* 变量,可以在 jail.local 文件的全局或特定部分中覆盖。
# banaction = iptables-multiport
# banaction_allports = iptables-allports
  • ① 列出 Fail2Ban 的过滤器选项:
sh
# ls /usr/local/etc/fail2ban/filter.d/
……省略一部分输出……
bsd-sendmail.conf		mssql-auth.conf			slapd.conf
bsd-sshd.conf			murmur.conf			softethervpn.conf
bsdftp.conf			mysqld-auth.conf		sogo-auth.conf
courier-auth.conf		nginx-botsearch.conf		sshd.conf

需要注意,以 bsd- 开头的文件(如 bsd-sshd.conf)是 FreeBSD Port 维护者为适配特定环境提供的变体,但本节应直接使用 sshd.conf,它与 Fail2Ban 标准配置的兼容性更好。

  • ② 查看 Fail2Ban 支持的防火墙:
sh
# ls /usr/local/etc/fail2ban/action.d/
bsd-ipfw.conf					ipfw.conf				ipfilter.conf				pf.conf
……省略其他防火墙……

18.5.4 Fail2Ban 封禁配置

创建并编辑文件 /usr/local/etc/fail2ban/jail.d/sshd.conf,写入如下内容:

ini
[DEFAULT]
ignoreip=192.168.0.0/24
maxretry = 3
findtime = 10m
bantime = 8h

[sshd]
enabled=true
filter=sshd
action=bsd-ipfw

配置解释:

  • 白名单,表示不会被封禁的 IP 段。192.168.0.0/24 表示从 192.168.0.0192.168.0.255
  • bsd-ipfw 是示例防火墙,可自行选择,参见下文。

在 FreeBSD 中,Fail2Ban 提供了两个 IPFW 相关的动作配置:ipfwbsd-ipfw。其中 bsd-ipfw 是专门为 FreeBSD 优化的版本,与系统的集成度更高。

警告

如果使用 IPFW 防火墙,必须选择 bsd-ipfw,而不能使用 ipfw,否则无法生效。

18.5.5 配置防火墙

完成 Fail2Ban 配置后,还需配置对应防火墙,然后启动服务。

启动 Fail2Ban 服务:

sh
# service fail2ban start

18.5.5.1 IPFW

IPFW 是 FreeBSD 内置的防火墙。Fail2Ban 配置同上。

18.5.5.1.1 配置开机启动服务

启用防火墙,实现开机自动启动:

sh
# sysrc firewall_enable="YES"

警告

请勿立即执行 start 命令,否则可能导致无法通过 SSH 连接。

18.5.5.1.2 修改 IPFW 默认规则

IPFW 规则的默认策略是“默认拒绝”,即规则 65535 会阻断所有未匹配的流量。为避免配置过程中访问被阻断,可先将其修改为“默认允许”:

sh
# echo 'net.inet.ip.fw.default_to_accept=1' >> /boot/loader.conf   # 设置防火墙默认策略为接受,开机生效
# reboot # 重启生效
  • 显示当前 IPFW 防火墙规则列表:
sh
# ipfw list
……省略一部分……
65535 allow ip from any to any

18.5.5.1.3 参考文献

18.5.5.2 PF

PF(Packet Filter,包过滤器)是源自 OpenBSD 的防火墙,其配置如下。

在 PF 中,table 用于存储需要封禁的 IP 地址列表,anchor 用于组织和管理特定的规则集。Fail2Ban 向 PF 的 table 中添加 IP 地址,再通过 anchor 应用相应规则来封禁。

18.5.5.2.1 Fail2Ban 配置文件

将上方配置文件 /usr/local/etc/fail2ban/jail.d/sshd.confaction=bsd-ipfw 改为 action=pf[port={22 23}, name=ssh],其他配置项无需修改。

18.5.5.2.2 修改 PF 配置文件

需要先准备 PF 的配置文件,涉及的目录结构:

sh
/
├── etc
   ├── pf.conf
   ├── ipf.rules
   └── ipnat.rules
├── usr
   └── share
       └── examples
           ├── pf
   └── pf.conf
           └── ipfilter
               ├── ipf.conf.sample
               └── ipnat.conf.sample
├── var
   └── log
       ├── auth.log
       └── fail2ban.log
└── boot
    └── loader.conf.local
  • 要让 PF 正常启动,需将示例 PF 配置文件复制到 /etc 目录以便修改和使用:
sh
# cp /usr/share/examples/pf/pf.conf /etc/
  • 编辑 /etc/pf.conf 文件,写入:
ini
table <f2b> persist   # 定义并持久化表 f2b
anchor "f2b/*"        # 创建并引用 f2b 相关的 anchor
block drop in log quick on em0 from <f2b> to any   # 在 em0 接口上快速阻止并记录来自 f2b 表的所有流量
  • em0:示例中的 em0 为网卡名称,需根据实际网卡修改,可使用命令 ifconfig 查看。

18.5.5.2.3 服务

PF 服务的启动和配置如下。

sh
# kldload pf # 加载内核模块,后续无需再手动加载
# service pf enable # 开机自启
# service pf start # 启动 PF 防火墙
18.5.5.2.3.1 参考文献

18.5.5.3 IPFILTER (IPF)

IPFILTER(IPF)是一款开源防火墙,其配置如下。

18.5.5.3.1 Fail2Ban 配置文件

将上方配置文件 /usr/local/etc/fail2ban/jail.d/sshd.confaction=bsd-ipfw 改为 action=ipfilter,其他配置项无需修改。ipfilter action 会调用 IPF 的命令来添加和删除封禁规则。

18.5.5.3.2 服务

IPF 服务的配置和启动如下。

  • 要让 IPF 正常启动并工作,需复制示例文件作为默认配置规则集文件(示例文件自带的规则不影响使用):
sh
# cp /usr/share/examples/ipfilter/ipf.conf.sample /etc/ipf.rules   # 将示例 ipfilter 配置文件复制为 /etc/ipf.rules 以便修改和使用
  • 配置守护进程:
sh
# service ipfilter enable   # 设置 ipfilter 服务开机自启动
# service ipfilter start    # 启动 ipfilter 防火墙服务

18.5.6 测试效果

配置完成后,可以测试 Fail2Ban 是否能正常封禁 IP。使用 Fail2Ban 客户端手动将一个 IP 加入封禁列表以验证功能。

  • 为了查看效果,使用 Fail2Ban 客户端将 IP 192.168.179.1 在 sshd 监控下加入封禁列表:
sh
# fail2ban-client set sshd banip 192.168.179.1
  • TTY 输出:此输出示例显示 SSH 服务检测到来自 192.168.179.1 的多次认证失败。
sh
Mar 25 15:27:38 gkla sshd[970]: error : maximum authentication attempts exceeded for ykla from 192.168.179.1 port 8652 ssh2 [ preauth ]

已建立的 SSH 连接也会被强制断开。

18.5.6.1 查看状态

可以通过以下命令查看 Fail2Ban 的运行状态。

查看 Fail2Ban 对 sshd 监控的状态,包括被封禁的 IP 列表:

sh
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	4
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	1
   |- Total banned:	1
   `- Banned IP list:	192.168.179.1

18.5.6.2 解禁 IP

如果需要解除对特定 IP 的封禁,可执行以下操作。

从 sshd 监控中解除对指定 IP 的封禁:

sh
# fail2ban-client set sshd unbanip 192.168.179.1
1
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	4
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	0
   |- Total banned:	1
   `- Banned IP list:

18.5.7 故障排除与未竟事宜

如果遇到问题,可查看日志排查。

  • Fail2Ban 的日志位于 /var/log/fail2ban.log 文件。