33.6. Blacklistd¶
Blacklistd 是一个监听套接字的守护进程,等待接收来自其他守护进程的关于连接尝试失败或成功的通知。它最广泛地用于阻止开放端口上的太多连接尝试。一个主要的例子是在互联网上运行的 SSH 从试图猜测密码并获得访问权限的机器人或脚本中获取大量请求。使用 Blacklistd,守护程序可以通知防火墙创建过滤规则,以阻止在多次尝试后从单点进行过多的连接尝试。Blacklistd 最初是在 NetBSD 上开发的,并在第 7 版中出现。FreeBSD 11 从 NetBSD 引入了 Blacklistd。
本章介绍如何设置和配置 Blacklistd,并提供如何使用 Blacklistd 的示例。读者应熟悉规则等基本防火墙概念。有关详细信息,请参阅防火墙章节。示例中使用了 PF,但 FreeBSD 上提供的其他防火墙也应该能够使用 Blacklistd。
33.6.1. Blacklistd¶
Blacklistd 的主要配置存储在 blacklistd.conf(5) 中。各种命令行选项也可用于更改 Blacklistd 的运行时行为。跨重新启动的持久配置应存储在 /etc/blacklistd.conf 中。要在系统引导期间启用守护程序,请在 /etc/rc.conf 中添加一行 blacklistd_enable
,如下所示:
# sysrc blacklistd_enable=yes
若要手动启动该服务,请运行以下命令:
# service blacklistd start
33.6.2.创建列入 Blacklistd 的规则集¶
Blacklistd 的规则在 blacklistd.conf(5) 中配置,每行一个条目。每个规则都包含一个由空格或制表符分隔的元组。规则属于local
或 remote
,分别适用于运行 Blacklistd 的计算机或外部源。
33.6.2.1.本地规则¶
本地规则的示例 blacklistd.conf 条目如下所示:
[local]
ssh stream * * * 3 24h
该部分后面的所有规则都被视为本地规则 [local]
(这是默认规则),并应用于本地计算机。当遇到 [remote]
节时,它后面的所有规则都被作为远程机器规则处理。
由制表符或空格分隔的七个字段定义了一个规则。前四个字段标识应列入 Blacklistd 的流量。后面的三个字段定义了 backlistd 的行为。通配符表示为星号(*
),匹配此字段中的任何内容。第一个字段定义位置。在本地规则中,这些是网络端口。位置字段的语法如下:
[address|interface][/mask][:port]
地址可以指定为数字格式的 IPv4 或方括号中的 IPv6。也可以使用接口名称 em0
。
套接字类型由第二个字段定义。TCP 套接字的类型为 stream
,而 UDP 表示为 dgram
。上面的示例使用 TCP,因为 SSH 使用该协议。
协议可用于列入 Blacklistd 的规则的第三个字段。可以使用以下协议:tcp
、udp
、tcp6
、udp6
或数字。通配符(如示例中所示)通常用于匹配所有协议,除非有理由通过某个协议来区分流量。
在第四个字段中,定义了报告事件的守护程序进程的有效用户或所有者。用户名或 UID 可以在此处使用,也可以使用通配符(请参阅上面的示例规则)。
数据包筛选器规则名称由第五个字段声明,该字段启动规则的行为部分。默认情况下,blacklistd 将所有块放在 pf.conf 中的一个名为 blacklistd
的 pf 锚点下,如下所示:
anchor "blacklistd/*" in on $ext_if
block in
pass out
对于单独的阻止列表,可以在此字段中使用锚点名称。在其他情况下,通配符就足够了。当名称以连字符(-
)开头时,表示应使用前面附加了默认规则名称的锚点。上面使用连字符的修改示例如下所示:
ssh stream * * -ssh 3 24h
使用这样的规则,任何新的阻止列表规则都将添加到名为 blacklistd-ssh
的锚点中。
为了阻止整个子网对单一规则的违反,可以在规则名称中使用一个 /
。这导致名称的其余部分被解释为应用于规则中指定的地址的掩码。例如,这条规则将阻止与 /24
相邻的每个地址。
22 stream tcp * */24 3 24h
注意
在这里指定适当的协议是很重要的。IPv4 和 IPv6 对 /24 的处理方式不同,这就是为什么不能在此规则的第三个字段使用
*
的原因。
此规则定义,如果该网络中的任何一台主机行为异常,则该网络上的其他所有内容也将被阻止。
第六个字段名为 nfail
,设置将相关远程 IP 列入 Blacklistd 所需的登录失败次数。当在此位置使用通配符时,这意味着块将永远不会发生。在上面的示例规则中,定义了三个限制,这意味着在一个连接上三次尝试登录 SSH 后,IP 将被阻止。
列入 Blacklistd 的规则定义中的最后一个字段指定主机被列入 Blacklistd 的时间长度。默认单位为秒,后缀也可以分别指定为分钟 m
、小时 h
和天 d
。
这个例子的规则整体上意味着,在三次验证 SSH 后,将导致该主机的新 PF 块规则。规则的匹配是通过首先一个接一个地检查本地规则,从最具体到最不具体。当匹配发生时,将应用 remote
规则,并由匹配的 remote
规则更改 name、nfail
和 disable 字段。
33.6.2.2.远程规则¶
远程规则用于指定 Blacklistd 如何根据当前正在评估的远程主机更改其行为。远程规则中的每个字段都与本地规则中的字段相同。唯一的区别在于 Blacklistd 使用它们的方式。为了解释它,使用了以下示例规则:
[remote]
203.0.113.128/25 * * * =/25 = 48h
地址字段可以是 IP 地址(v4 或 v6)、端口或两者。这允许为特定的远程地址范围设置特殊规则,如本例所示。套接字段的类型、协议和所有者的解释与本地规则中的相同。
但是,名称字段是不同的:远程规则中的等号(=
)告诉 blacklistd 使用匹配的本地规则中的值。这意味着将采用防火墙规则条目并添加前缀 /25
(的网络掩码255.255.255.128
)。当来自该地址范围的连接被列入阻止列表时,整个子网都会受到影响。此处也可以使用 PF 锚点名称,在这种情况下,Blacklistd 会将此地址块的规则添加到该名称的锚点。指定通配符时使用默认表。
在 nfail
列中可以为一个地址定义一个自定义的失败次数。这对特定规则的例外情况很有用,也许可以允许某人不那么严格地应用规则,或者在登录尝试中更宽松一点。当在这第六个字段中使用星号时,阻断功能将被禁用。
与来自本地网络(如办公室)的尝试相比,远程规则允许对登录尝试实施更严格的限制。
33.6.3.列入 Blacklistd 的客户端配置¶
FreeBSD 中有一些软件包可以利用 Blacklistd 的功能。两个最突出的是 ftpd(8) 和 sshd(8),用于阻止过多的连接尝试。要激活 SSH 守护程序中的 Blacklistd,请将以下行添加到 /etc/ssh/sshd_config:
UseBlacklist yes
之后重新启动 sshd 以使这些更改生效。
ftpd(8) 的 Blacklistd 使用 -B
来启用,或者在 /etc/inetd.conf 中,或者作为 /etc/rc.conf 中的一个参数,像这样:
ftpd_flags="-B"
这就是使这些程序与 Blacklistd 对话所需的全部内容。
33.6.4. Blacklistd 管理¶
Blacklistd 为用户提供了一个名为 blacklistctl(8) 的管理实用程序。它显示被阻止的地址和网络,这些地址和网络被 blacklistd.conf(5) 中定义的规则列入了阻止列表。要查看当前被阻止的主机列表,请像这样结合使用 dump
和 -b
。
# blacklistctl dump -b
address/ma:port id nfail last access
213.0.123.128/25:22 OK 6/3 2019/06/08 14:30:19
这个例子显示,在端口 22 上有 6 次允许的尝试,这些尝试来自地址范围213.0.123.128/25
。列出的尝试次数多于允许的次数,因为 SSH 允许客户端在一个 TCP 连接上尝试多次登录。目前正在进行的连接不会被 blacklistd 阻止。最后的连接尝试被列在输出的 last access
列中。
要查看此主机将在 Blacklistd 上的剩余时间,请添加 -r
到上一个命令中。
# blacklistctl dump -br
address/ma:port id nfail remaining time
213.0.123.128/25:22 OK 6/3 36s
在此示例中,还剩下 36 秒,直到此主机不再被阻止。
33.6.5.从阻止列表中删除主机¶
有时,有必要在剩余时间到期之前将一个主机从封锁名单中删除。不幸的是,blacklistd
中没有这样的功能。不过,可以用 pfctl
把地址从 PF 表中删除。对于每个被封锁的端口,在 /etc/pf.conf 中定义的 blacklistd 锚内都有一个子锚。例如,如果有一个封锁端口 22 的子锚,它就被称为 blacklistd/22
。在这个子锚里面有一个表,包含了被封的地址。这个表的名字是 port,后面是端口号。在这个例子中,它被称为 port22
。有了这些信息,现在就可以用 pfctl(8) 来显示所有列出的地址,如下所示:
# pfctl -a blacklistd/22 -t port22 -T show
...
213.0.123.128/25
...
从列表中确定要取消阻止的地址后,以下命令会将其从列表中删除:
# pfctl -a blacklistd/22 -t port22 -T delete 213.0.123.128/25
该地址现已从 PF 中删除,但仍将显示在 blacklistctl 列表中,因为它不知道在 PF 中所做的任何更改。Blacklistd 数据库中的条目最终将过期,并最终从其输出中删除。如果主机再次与列入 Blacklistd 的阻止规则之一匹配,则将再次添加该条目。