.. _blacklistd-1: 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``\ ,如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # sysrc blacklistd_enable=yes 若要手动启动该服务,请运行以下命令: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # service blacklistd start 33.6.2.创建列入 Blacklistd 的规则集 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Blacklistd 的规则在 `blacklistd.conf(5) `__ 中配置,每行一个条目。每个规则都包含一个由空格或制表符分隔的元组。规则属于\ ``local`` 或 ``remote``\ ,分别适用于运行 Blacklistd 的计算机或外部源。 33.6.2.1.本地规则 ~~~~~~~~~~~~~~~~~ 本地规则的示例 blacklistd.conf 条目如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session [local] ssh stream * * * 3 24h 该部分后面的所有规则都被视为本地规则 ``[local]``\ (这是默认规则),并应用于本地计算机。当遇到 ``[remote]`` 节时,它后面的所有规则都被作为远程机器规则处理。 由制表符或空格分隔的七个字段定义了一个规则。前四个字段标识应列入 Blacklistd 的流量。后面的三个字段定义了 backlistd 的行为。通配符表示为星号(\ ``*``\ ),匹配此字段中的任何内容。第一个字段定义位置。在本地规则中,这些是网络端口。位置字段的语法如下: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session [address|interface][/mask][:port] 地址可以指定为数字格式的 IPv4 或方括号中的 IPv6。也可以使用接口名称 ``em0``\ 。 套接字类型由第二个字段定义。TCP 套接字的类型为 ``stream``\ ,而 UDP 表示为 ``dgram``\ 。上面的示例使用 TCP,因为 SSH 使用该协议。 协议可用于列入 Blacklistd 的规则的第三个字段。可以使用以下协议:\ ``tcp``\ 、\ ``udp``\ 、\ ``tcp6``\ 、\ ``udp6`` 或数字。通配符(如示例中所示)通常用于匹配所有协议,除非有理由通过某个协议来区分流量。 在第四个字段中,定义了报告事件的守护程序进程的有效用户或所有者。用户名或 UID 可以在此处使用,也可以使用通配符(请参阅上面的示例规则)。 数据包筛选器规则名称由第五个字段声明,该字段启动规则的行为部分。默认情况下,blacklistd 将所有块放在 **pf.conf** 中的一个名为 ``blacklistd`` 的 pf 锚点下,如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session anchor "blacklistd/*" in on $ext_if block in pass out 对于单独的阻止列表,可以在此字段中使用锚点名称。在其他情况下,通配符就足够了。当名称以连字符(\ ``-``\ )开头时,表示应使用前面附加了默认规则名称的锚点。上面使用连字符的修改示例如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session ssh stream * * -ssh 3 24h 使用这样的规则,任何新的阻止列表规则都将添加到名为 ``blacklistd-ssh`` 的锚点中。 为了阻止整个子网对单一规则的违反,可以在规则名称中使用一个 ``/``\ 。这导致名称的其余部分被解释为应用于规则中指定的地址的掩码。例如,这条规则将阻止与 ``/24`` 相邻的每个地址。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session 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 使用它们的方式。为了解释它,使用了以下示例规则: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session [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**\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session UseBlacklist yes 之后重新启动 sshd 以使这些更改生效。 `ftpd(8) `__ 的 Blacklistd 使用 ``-B`` 来启用,或者在 /**etc/inetd.conf** 中,或者作为 **/etc/rc.conf** 中的一个参数,像这样: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session ftpd_flags="-B" 这就是使这些程序与 Blacklistd 对话所需的全部内容。 33.6.4. Blacklistd 管理 ----------------------- Blacklistd 为用户提供了一个名为 `blacklistctl(8) `__ 的管理实用程序。它显示被阻止的地址和网络,这些地址和网络被 `blacklistd.conf(5) `__ 中定义的规则列入了阻止列表。要查看当前被阻止的主机列表,请像这样结合使用 ``dump`` 和 ``-b``\ 。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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`` 到上一个命令中。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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) `__ 来显示所有列出的地址,如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # pfctl -a blacklistd/22 -t port22 -T show ... 213.0.123.128/25 ... 从列表中确定要取消阻止的地址后,以下命令会将其从列表中删除: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # pfctl -a blacklistd/22 -t port22 -T delete 213.0.123.128/25 该地址现已从 PF 中删除,但仍将显示在 blacklistctl 列表中,因为它不知道在 PF 中所做的任何更改。Blacklistd 数据库中的条目最终将过期,并最终从其输出中删除。如果主机再次与列入 Blacklistd 的阻止规则之一匹配,则将再次添加该条目。