Fail2Ban如何保护Linux服务器上的服务

来自菜鸟教程
跳转至:导航、​搜索

介绍

任何暴露在互联网上的服务都容易受到恶意方的攻击。 如果您的服务需要身份验证,非法用户和机器人将通过反复尝试使用不同的凭据进行身份验证来尝试闯入您的系统。

一个常见的例子是 SSH,它将成为试图暴力破解通用帐户名称的机器人攻击的主题。 幸运的是,创建了 fail2ban 之类的服务来帮助我们减轻这些攻击。

Fail2ban 通过动态更改防火墙规则来禁止尝试登录一定次数未成功的地址。 在之前的指南中,我们讨论了 如何在 Ubuntu 14.04 上启动和运行 fail2ban。

在本指南中,我们将更深入地讨论 fail2ban 的实际工作原理以及如何使用这些知识来修改或扩展此服务的行为。

基本概念

fail2ban 背后的基本思想是监视公共服务的日志以发现身份验证失败的模式。

当 fail2ban 配置为监视服务的日志时,它会查看已针对该服务配置的 filter。 该过滤器旨在通过使用复杂的正则表达式来识别该特定服务的身份验证失败。 它将这些正则表达式模式定义为一个名为 failregex 的变量。

幸运的是,fail2ban 包含通用服务的过滤器文件。 当服务日志文件中的一行与其过滤器中的 failregex 匹配时,将为该服务执行定义的 actionaction 是一个变量,可以根据管理员的偏好进行配置以执行许多不同的操作。

默认操作是通过修改 iptables 防火墙规则来禁止违规主机/IP 地址。 您可以扩展此操作以向管理员发送一封电子邮件,其中包含攻击者的 whois 报告或触发该操作的日志行。

您还可以将动作目标修改为不同于通常的 iptables 的内容。 这可以像您所做的那样复杂或简单,并且可以使用许多不同的防火墙配置文件和通知选项。

默认情况下,10 分钟内检测到 3 次身份验证失败时执行,默认禁止时间为 10 分钟。 在默认配置文件的 SSH 部分中覆盖了触发禁令所需的身份验证失败次数的默认值,以便在禁令发生之前允许 6 次失败。 这完全由管理员配置。

当对 SSH 流量使用默认的 iptables 目标时,fail2ban 会在服务启动时创建一个新链。 它向 INPUT 链添加了一条新规则,该规则将指向端口 22 的所有 TCP 流量发送到新链。 在新链中,它插入一个返回到 INPUT 链的规则。

这只会使流量跳转到新链,然后立即跳回。 这对一开始的交通没有影响。 但是,当 IP 达到身份验证失败的阈值时,会在新链的顶部添加一条规则,以丢弃来自违规 IP 的流量。 这照顾了实际的禁令。 禁止期限到期后,将删除 iptables 规则。 当 fail2ban 服务退出时,链和相关规则将被删除。

探索 Fail2ban 服务设置

Fail2ban 通过位于 /etc/fail2ban/ 目录下的层次结构中的各种文件进行配置。

fail2ban.conf 文件配置了一些基本的操作设置,例如守护进程记录信息的方式,以及它将使用的套接字和 pid 文件。 然而,主要配置发生在定义“监狱”的文件中。

默认情况下,fail2ban 附带一个 jail.conf 文件。 但是,这可以在更新中被覆盖,因此鼓励用户将此文件复制到 jail.local 文件并在那里进行调整。

如果您已经有一个 jail.local 文件,请立即打开它以继续操作:

sudo nano /etc/fail2ban/jail.local

如果您还没有 jail.local 文件,或者您打开的文件是空白的,请复制 jail.conf 文件,然后打开新文件:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

我们将查看此处可用的选项,并了解此文件如何与系统上的其他配置文件交互。

默认部分

文件的第一部分将定义 fail2ban 策略的默认值。 这些选项可以在每个单独服务的配置部分中覆盖。

删除注释后,整个默认部分看起来像这样:

[DEFAULT]

ignoreip = 127.0.0.1/8
bantime = 600
findtime = 600
maxretry = 3
backend = auto
usedns = warn
destemail = root@localhost
sendername = Fail2Ban
banaction = iptables-multiport
mta = sendmail
protocol = tcp
chain = INPUT
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
          %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
           %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
action = %(action_)s

让我们回顾一下其中的一些实际含义:

  • ignoreip:该参数标识应该被禁止系统忽略的IP地址。 默认情况下,这只是设置为忽略来自机器本身的流量,这是一个非常好的设置。
  • bantime:此参数设置禁令的长度,以秒为单位。 默认值为 600 秒或 10 分钟。
  • findtime:该参数设置fail2ban在寻找重复失败的认证尝试时将注意的窗口。 默认设置为 600 秒(再次为 10 分钟),这意味着软件将统计最近 10 分钟内的失败尝试次数。
  • maxretry:这将设置在禁止之前在 findtime 窗口内允许的失败尝试次数。
  • backend:此条目指定fail2ban 将如何监控日志文件。 auto 的设置意味着 fail2ban 将尝试 pyinotify,然后是 gamin,然后是基于可用的轮询算法。
  • usedns:这定义了是否使用反向 DNS 来帮助实施禁令。 将此设置为“否”将禁止 IP 本身而不是主机名。 “警告”设置将尝试使用反向 DNS 来查找主机名并禁止这种方式,但会记录活动以供审查。
  • destemail:如果将您的操作配置为邮件警报,这是将发送通知邮件的地址。
  • sendername:这将用于生成通知电子邮件的电子邮件发件人字段
  • banaction:设置达到阈值时将使用的操作。 实际上有一个位于 /etc/fail2ban/action.d/ 中的文件的名称,称为 iptables-multiport.conf。 这会处理实际的 iptables 操作以禁止 IP 地址。 我们稍后会看这个。
  • mta:这是用于发送通知电子邮件的邮件传输代理。
  • protocol:这是实施 IP 禁令时将丢弃的流量类型。 这也是发送到新 iptables 链的流量类型。
  • chain:这是将配置有跳转规则以将流量发送到 fail2ban 漏斗的链。

其余参数定义可以指定的不同操作。 它们传入我们在上面使用字符串插值定义的一些参数,如下所示:

%(var_name)s

上面的行将替换为 var_name 的内容。 使用它,我们可以看出 action 变量默认设置为 action_ 定义(仅禁止,无邮件警报)。

反过来,这通过调用 iptables-multiport 操作来配置,其中包含执行禁令所需的参数列表(服务名称、端口、协议和链)。 __name__ 被替换为以下部分标题中指定的服务名称。

服务特定部分

在默认部分下,有一些特定服务的部分可用于覆盖默认设置。 这遵循仅修改偏离正常值的参数的约定(约定优于配置)。

每个部分的标题是这样指定的:

[服务名称]

任何包含此行的部分都将被读取并启用:

enabled = true

在每个部分中,都配置了参数,包括用于解析日志的过滤器文件(减去文件扩展名)和日志文件本身的位置。

记住这一点,为 SSH 服务指定操作的部分如下所示:

[SSH]

enabled     = true
port        = ssh
filter      = sshd
logpath     = /var/log/auth.log
maxretry    = 6

这将启用此部分并将端口设置为“ssh”端口(端口 22)。 它告诉 fail2ban 查看位于 /var/log/auth.log 的日志,并使用在 /etc/fail2ban/filters.d 目录中定义的过滤机制在名为 sshd.conf 的文件中解析日志。

它需要的所有其他信息都取自 [DEFAULT] 部分中定义的参数。 例如,该操作将设置为 action_,这将使用 iptables-multiport 禁令禁止违规 IP 地址,该禁令引用 [X175X 中的 iptables-multiport.conf 文件]。

如您所见,[DEFAULT] 部分中的操作应该是通用且灵活的。 大量使用参数替换以及提供合理默认值的参数将使定义在必要时易于覆盖。

检查过滤器文件

为了了解我们的配置中发生了什么,我们需要了解完成大部分工作的过滤器和操作文件。

过滤器文件将确定 fail2ban 将在日志文件中查找的行以识别违规特征。 动作文件实现了所有需要的动作,从在服务启动时建立防火墙结构,到添加和删除规则,以及在服务停止时拆除防火墙结构。

让我们看一下我们的 SSH 服务在上面的配置中调用的过滤器文件:

sudo nano /etc/fail2ban/filter.d/sshd.conf

[INCLUDES]

before = common.conf

[Definition]

_daemon = sshd
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
        ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
        ^%(__prefix_line)sFailed \S+ for .*? from <HOST>(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user ".*", client host ".*")?))?\s*$
        ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
        ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
        ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
        ^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
ignoreregex =

这看起来很复杂。 那是因为它相当复杂。 让我们分解一下。

[INCLUDES] 部分标题指定在此文件之前或之后读入的其他过滤器文件。 在我们的示例中,common.conf 文件被读入并放置在该文件的其他行之前。 这设置了我们将在配置中使用的一些参数。

接下来,我们有一个 [Definition] 部分,它定义了过滤器匹配的实际规则。 首先,我们使用 _daemon 参数设置我们正在监视的守护程序的名称。

之后,我们通过实际的 failregex 定义,它设置在日志文件中找到匹配行时将触发的模式。 这些是根据用户未正确验证时可能引发的不同错误和失败匹配的正则表达式。

%(__prefix_line)s 等行的部分将替换为我们提供的 common.conf 文件中的参数设置值。 这用于匹配操作系统在使用标准方法时写入日志文件的不同前导信息。 例如,/var/log/auth.log 中的某些行可能看起来像这样:

 5 月 6 日 18:18:52 localhost sshd[3534]: pam_unix(sshd:auth): 认证失败;  logname=uid=0 euid=0 tty=ssh ruser=rhost=101.79.130.213 5 月 6 日 18:18:54 localhost sshd[3534]:来自 101.79.130.213 端口 38354 ssh2 的无效用户 phil 的密码失败5 月 6 日 18:18: 54 localhost sshd [3534]:收到与 101.79.130.213 的断开连接:11:再见 [preauth]

红色部分是操作系统插入以提供更多上下文的标准模式。 之后,iptables 服务有很多不同的方式将失败尝试写入日志。

我们在上面的前两行中看到了两个单独的失败(PAM 身份验证错误和密码错误)。 过滤器中定义的正则表达式旨在匹配任何可能的失败行。 您不必调整任何这些行,但您应该知道,如果您必须自己创建过滤器文件,则需要捕获所有表示您尝试保护的应用程序未经授权使用错误的日志条目.

在底部,您可以看到一个 ignoreregex 参数,该参数当前为空白。 这可用于排除通常与故障条件匹配的更具体的模式,以防您想在某些情况下否定 fail2ban 的故障触发器。 我们不会对此进行调整。

完成检查后保存并关闭文件。

检查动作文件

现在,让我们看一下动作文件。 该文件负责设置防火墙,其结构允许轻松修改以禁止恶意主机,并根据需要添加和删除这些主机。

您还记得,我们的 SSH 服务调用的操作称为 iptables-multiport。 现在打开相关文件:

sudo nano /etc/fail2ban/action.d/iptables-multiport.conf

删除注释后,此文件如下所示:

[INCLUDES]
before = iptables-blocktype.conf

[Definition]
actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>

actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>

actioncheck = iptables -n -L <chain> | grep -a 'fail2ban-<name>[ \t]'

actionban = iptables -I fail2ban-<name> 1 -s <ip> -j <blocktype>

actionunban = iptables -D fail2ban-<name> -s <ip> -j <blocktype>

[Init]
name = default
port = ssh
protocol = tcp
chain = INPUT

该文件通过获取另一个名为 iptables-blocktype.conf 的操作文件开始,该文件简单地定义了 blocktype 参数,该参数配置将在客户端被禁止时设置的限制。 默认情况下,blocktype 设置为拒绝数据包并回复被禁止客户端发送的 ping,并带有拒绝消息,表明端口无法访问。 我们将在下面的禁令规则中使用它。

接下来,我们了解规则定义本身。 行动相当直接。 当 fail2ban 服务启动时,actionstart 操作设置 iptables 防火墙。 它创建一个新链,向该链添加一条规则以返回调用链,然后在 INPUT 链的开头插入一条规则,将匹配正确协议和端口目标的流量传递到新链。

它通过使用我们在 jail.local 文件中定义的 action 传入的值来做到这一点。 name 取自每个服务的节标题,chainprotocolport 取自 action 行本身在该文件中。

您可能还记得,这些反过来是通过在该文件中的 other 位置中插入 other 参数集而添加到操作行的。 此时您可能已经意识到,fail2ban 在其配置文件的各个部分之间传递和转换许多参数。

在这里,通过在尖括号中包含参数名称来引用其他文件设置的所有参数:

<参数名称>

当我们向下移动到伴随的 actionstop 定义时,我们可以看到防火墙命令只是实现了 actionstart 命令的反转。 当我们停止 fail2ban 服务时,我们拆除了我们创建的防火墙结构。

另一个名为 actioncheck 的操作确保在尝试添加禁止规则之前已创建正确的链。

接下来,我们进入实际的禁止规则,称为 actionban。 该规则通过向我们创建的链添加新规则来工作。 该规则匹配违规客户端的源 IP 地址(当达到 maxretry 限制时,从授权日志中读取此参数)并建立由我们来源的 blocktype 参数定义的块在文件顶部的 [INCLUDE] 部分中。

actionunban 规则只是删除了这个规则。 禁用时间过后,fail2ban 会自动完成此操作。

最后,我们进入 [Init] 部分。 这只是提供了一些默认值,以防调用动作文件而不传递所有适当的值。

Fail2ban 服务如何处理配置文件以实施禁令

现在我们已经了解了细节,让我们回顾一下 fail2ban 启动时发生的过程。

加载初始配置文件

首先,读取主fail2ban.conf文件以确定主进程应该在什么条件下运行。 如有必要,它会创建套接字、pid 和日志文件并开始使用它们。

接下来,fail2ban 读取 jail.conf 文件以获取配置详细信息。 它通过按字母顺序读取在 jail.d 目录中找到的以 .conf 结尾的所有文件来执行此操作。 它将在这些文件中找到的设置添加到其内部配置中,使新值优先于 jail.conf 文件中描述的值。

然后它搜索 jail.local 文件并重复此过程,调整新值。 最后,它再次搜索 jail.d 目录,按字母顺序读取以 .local 结尾的文件。

这样,我们可以看到fail2ban有大量的文件可以用来操纵进程的最终行为。 在我们的例子中,我们只有一个 jail.conf 文件和一个 jail.local 文件。 在我们的 jail.local 文件中,我们只需要定义与 jail.conf 文件不同的值。

fail2ban 进程现在有一组指令加载到内存中,代表它找到的所有文件的组合。

它检查每个部分并搜索 enabled = true 指令。 如果找到,它会使用该部分下定义的参数来构建策略并决定需要哪些操作。 在服务部分中找不到的任何参数都使用在 [DEFAULT] 部分中定义的参数。

解析动作文件以确定启动动作

Fail2ban 寻找一个 action 指令来确定调用什么动作脚本来实现禁止/取消禁止策略。 如果没有找到,它会退回到上面确定的默认操作。

action 指令包含将要读取的动作文件的名称,以及传递这些文件所需参数的键值字典。 这些值通常采用参数替换的形式,通过引用服务部分中配置的设置。 “name”键通常传递特殊的 __name__ 变量的值,该变量将设置为节标题的值。

Fail2ban 然后使用此信息在 action.d 目录中查找相关文件。 它首先查找以 .conf 结尾的关联操作文件,然后使用 action.d 目录中的随附 .local 文件中包含的任何设置修改在那里找到的信息。

它解析这些文件以确定它现在需要采取的行动。 它读取 actionstart 值以查看设置环境应采取的操作。 这通常包括创建防火墙结构以适应未来的禁止规则。

此文件中定义的操作使用从 action 指令传递给它的参数。 它将使用这些值来动态创建适当的规则。 如果某个变量没有设置,它可以查看动作文件中设置的默认值来填补空白。

解析过滤文件以确定过滤规则

jail.* 文件中服务的参数还包括日志文件的位置以及应该用于检查文件的轮询机制(这由 backend 参数定义) . 它还包括一个过滤器,用于确定日志中的一行是否代表失败。

Fail2ban 在 filter.d 目录中查找以 .conf 结尾的匹配过滤器文件。 它读取此文件以定义可用于匹配违规行的模式。 然后它会搜索以 .local 结尾的匹配过滤器文件,以查看是否有任何默认参数被覆盖。

它在读取服务的日志文件时使用这些文件中定义的正则表达式。 它针对写入服务日志文件的每个新行尝试在 filter.d 文件中定义的每个 failregex 行。

如果正则表达式返回匹配项,它会根据 ignoreregex 定义的正则表达式检查该行。 如果这也匹配,fail2ban 将忽略它。 如果该行与 failregex 中的表达式匹配,但 notignoreregex 中的表达式匹配,则为导致该行的客户端增加一个内部计数器和一个关联的为事件创建时间戳。

当到达由 jail.* 文件中的 findtime 参数设置的时间窗口(由事件时间戳确定)时,内部计数器再次递减,事件不再被视为与禁令政策。

如果随着时间的推移记录了额外的身份验证失败,则每次尝试都会增加计数器。 如果计数器在配置的时间窗口内达到 maxretry 参数设置的值,fail2ban 通过调用 actioncheck 操作为 action.d/ 中定义的服务发起禁令服务的文件。 这是为了判断actionstart动作是否设置了必要的结构。 然后它调用 actionban 操作来禁止违规客户端。 它也为此事件设置了时间戳。

当经过 bantime 参数指定的时间量后,fail2ban 通过调用 actionunban 操作解除对客户端的禁令。

当 fail2ban 服务停止时,它会尝试通过调用 actionstop 操作来拆除它创建的任何防火墙规则。 这通常会删除包含 fail2ban 规则的链,并从 INPUT 链中删除导致流量跳转到该链的规则。

结论

希望到目前为止,您对 fail2ban 的运作方式有了相当深入的了解。 对于大多数用户而言,该服务本身非常容易,因为大多数困难的配置都已为您解决。

但是,当您偏离标准配置时,了解 fail2ban 的功能有助于以可预测的方式操纵其行为。

要了解如何使用 fail2ban 保护其他服务,请查看以下链接: