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

简介

SSH是连接到云服务器的实际方法。它是持久的,而且是可扩展的--随着新的加密标准的开发,它们可以用来生成新的SSH密钥,从而确保核心协议保持安全。然而,没有协议或软件堆栈是完全万无一失的,而SSH在整个互联网上如此广泛的部署意味着它代表了一个非常可预测的攻击面或攻击媒介,人们可以通过它试图获得访问权限。

任何向网络公开的服务都是这种方式的潜在目标。如果您查看在任何流量较大的服务器上运行的SSH服务的日志,您经常会看到重复的、系统的登录尝试,这代表了用户和僵尸程序的暴力攻击。尽管您可以对您的keys](https://andsky.com/tech/tutorials/how-to-set-up-ssh-keys-on-ubuntu-22-04),服务进行一些优化,以将这些攻击成功的几率降低到接近零的水平,例如[禁用密码身份验证以支持SSH SSH],但它们仍然可能造成轻微的、持续的风险。

这种责任对其来说是完全不可接受的大规模生产部署通常将在其SSH服务之前实现诸如WireGuard之类的虚拟专用网,因此不可能在没有额外的软件抽象或网关的情况下从外部互联网直接连接到默认的SSH端口22。这些VPN解决方案广受信任,但会增加复杂性,并可能打破一些自动化或其他小的软件挂钩。

在承诺完全设置VPN之前或在此之外,您可以实现一个名为Fail2ban 的工具。Fail2ban通过创建规则来自动更改您的防火墙配置,以在登录尝试失败一定次数后禁止特定IP,从而显著减少暴力攻击。这将允许您的服务器在无需您干预的情况下加强自身抵御这些访问尝试的能力。

在另一个教程中,我们讨论了如何使用Fail 2ban保护SSH。在本指南中,我们将更深入地讨论Fail 2ban实际上是如何工作的,以及如何使用这些知识来修改或扩展此服务的行为。

Fail2ban基础知识

Fail2ban的目的是监视常见服务的日志,以发现身份验证失败的模式。

当将ail2ban配置为监控服务的日志时,它会查看针对该服务配置的过滤器 。该筛选器旨在通过使用复杂的正则表达式来识别该特定服务的身份验证失败。正则表达式是一种用于模式matching](https://andsky.com/tech/tutorials/an-introduction-to-regular-expressions).的通用模板语言它将这些正则表达式模式定义为一个名为ailregex的内部变量。

默认情况下,Fail2ban包括常见服务的筛选器文件。当来自任何服务(如Web服务器)的日志与其过滤器中的ailregex匹配时,将为该服务执行预定义的操作。action是一个变量,可以配置它来执行许多不同的操作,具体取决于管理员的偏好。

默认操作是通过修改本地防火墙规则来禁止违规主机/IP地址。例如,您可以将此操作扩展为向系统管理员发送电子邮件。

默认情况下,当在10分钟内检测到三次身份验证失败时将采取操作,并且默认禁止时间为10分钟。这是可配置的。

当使用默认的ipables防火墙时,ail2ban会在服务启动时创建一组新的防火墙规则,也称为链。它向输入链添加一个新规则,将指向端口22的所有TCP流量发送到新链。在新的链中,它插入一个返回到输入链的规则。如果停止Fail2ban服务,链和关联规则将被删除。

探索Fail2ban服务设置

Fail2ban是通过位于/etc/ail2ban/目录下的层次结构中的多个文件进行配置的。

fail2ban.conf文件配置一些操作设置,如守护进程记录信息的方式,以及它将使用的套接字和pid文件。但是,主要配置是在定义每个应用程序的jail的文件中指定的。

默认情况下,ail2ban附带一个jail.conf文件。但是,这可能会在更新中被覆盖,所以您应该将此文件复制到一个jail.local文件中,并在那里进行调整。

如果您已经有jail.local文件,请使用nan或您最喜欢的文本编辑器打开它:

1sudo nano /etc/fail2ban/jail.local

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

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

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

默认分区

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

删除注释后,默认部分的整个内容如下所示:

 1[label /etc/fail2ban/jail.local]
 2[DEFAULT]
 3
 4ignoreip = 127.0.0.1/8
 5bantime = 10m
 6findtime = 10m
 7maxretry = 3
 8backend = auto
 9usedns = warn
10destemail = root@localhost
11sendername = Fail2Ban
12banaction = iptables-multiport
13mta = sendmail
14protocol = tcp
15chain = INPUT
16action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
17action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
18            %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
19action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
20            %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
21action = %(action_)s

让我们来看看这其中的一些含义:

  • Ignore reip :该参数标识禁止系统应该忽略的IP地址。默认情况下,这只是设置为忽略来自机器本身的流量,这样您就不会填满自己的日志或将自己锁在外面。
  • bantime :设置一条禁令的时长,单位为秒。默认为10分钟。
  • findtime :该参数设置Fail2ban在查找重复失败的身份验证尝试时注意的窗口。默认设置为10分钟,这意味着软件将统计最近10分钟内失败的尝试次数。
  • Maxretry :设置封禁前findtime窗口内允许的失败次数。
  • 后端 :该条目指定Fail2ban将如何监控日志文件。如果设置为auto,则表示ail2ban将尝试pyintify,然后是gamin,然后是基于可用的轮询算法。intify是一个内置的Linux内核功能,用于跟踪文件被访问的时间,而pyintifyintify的一个Python接口,由Fail2ban使用。
  • 已使用域名 :定义是否使用反向域名帮助实现封禁。将其设置为no将禁止IP本身,而不是它们的域名。`warn‘设置将尝试查找主机名并以此方式禁止,但会记录该活动以供审查。
  • 目标电子邮件 :如果将您的操作配置为发送警报,则这是将发送通知邮件的地址。
  • sendername :这将用于生成的通知电子邮件的电子邮件发件人字段
  • banaction :设置达到阈值后的动作。这实际上是位于/etc/ail2ban/action.d/中的文件的路径,该文件名为ipables-Multiport.conf。它处理实际的iptable防火墙操作,以禁止IP地址。我们将在稍后了解这一点。
  • MTA :用于发送通知邮件的邮件传输代理。
  • 协议 :IP封禁时丢弃的流量类型。这也是发送到新iptabLes链的流量类型。
  • :这是将配置跳转规则的链,用于将流量发送到ail2ban漏斗。

其余参数定义可以指定的不同操作。它们使用文本字符串中的变量替换传递我们在上面定义的一些参数,如下所示:

%(Var_Name)s

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

这又是通过使用执行BAN所需的参数列表(服务名称、端口、协议和链)调用ipables-Multiport操作来配置的。__name__被替换为下面的段头指定的服务名称。

服务专区

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

每个节标题如下所示:

帖子主题:Re:Колибри

将读取并启用行为Enable=true的任何部分。

在每个部分中配置参数,包括应该用于解析日志的筛选器文件(不包括文件扩展名)和日志文件本身的位置。

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

1[label /etc/fail2ban/jail.local]
2[SSH]
3
4enabled     = true
5port        = ssh
6filter      = sshd
7logpath     = /var/log/auth.log
8maxretry    = 6

这将启用此部分并将端口设置为默认的)。它告诉Fail 2ban查看位于/var/log/auth.log中的日志,并使用名为sshd.conf的文件中的/etc/fail 2ban/filters.d目录中定义的过滤机制来解析日志。

它需要的所有其他信息都取自[默认]部分中定义的参数。例如,该操作将被设置为Action_,这将使用ipables-MultiportBanaction来禁用违规的IP地址,它引用了/etc/ail2ban/action.d中的一个名为ipables-Multiport.conf的文件。

如您所见,[默认]部分的操作应该是通用的和灵活的。将参数替换与提供合理缺省值的参数一起使用,将使在必要时覆盖定义成为可能。

检查过滤文件

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

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

让我们看看我们的SSH服务在上面的配置中调用的筛选器文件:

1sudo nano /etc/fail2ban/filter.d/sshd.conf
 1[label /etc/fail2ban/sshd.conf]
 2[INCLUDES]
 3
 4before = common.conf
 5
 6[Definition]
 7
 8_daemon = sshd
 9failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
10        ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
11        ^%(__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*$
12        ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
13        ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
14        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
15        ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
16        ^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
17        ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
18        ^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
19        ^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
20ignoreregex =

[Includes]节头指定在该文件之前或之后读入的其他过滤文件。在我们的示例中,Common.conf文件被读入并放在该文件中其他行的前面。这将设置我们将在配置中使用的一些参数。

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

在此之后,我们将查看实际的ailregex定义,该定义设置在日志文件中找到匹配行时将触发的模式。这些是正则表达式,它们基于用户未正确进行身份验证时可能引发的不同错误和失败进行匹配。

%(__PREFIX_LINE)s这样的行的部分将被替换为我们获取的Common.conf文件中的参数设置的值。这用于匹配操作系统在使用标准方法时写入日志文件的不同前导信息。例如,/var/log/auth.log中的一些行可能如下所示:

1[label /var/log/auth.log]
2May 6 18:18:52 localhost sshd[3534]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=101.79.130.213 
3May 6 18:18:54 localhost sshd[3534]: Failed password for invalid user phil from 101.79.130.213 port 38354 ssh2
4May 6 18:18:54 localhost sshd[3534]: Received disconnect from 101.79.130.213: 11: Bye Bye [preauth]

突出显示的部分是操作系统插入以提供更多上下文的标准图案。在此之后,IPTABLES防火墙服务将失败尝试写入日志的方式有很多。

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

在底部,您可以看到一个neuceregex参数,该参数当前为空。这可以用来排除更具体的模式,这些模式通常与故障条件匹配,以防您想要在某些场景中否定故障2ban的故障触发器。我们不会调整这一点。

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

查看动作文件

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

我们的SSH服务调用的操作称为ipables-Multiport。立即打开关联文件:

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

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

 1[label /etc/fail2ban/action.d/iptables-multiport.conf]
 2[INCLUDES]
 3before = iptables-blocktype.conf
 4
 5[Definition]
 6actionstart = iptables -N fail2ban-<name>
 7                iptables -A fail2ban-<name> -j RETURN
 8                iptables -I <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
 9
10actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
11
12actioncheck = iptables -n -L <chain> | grep -a 'fail2ban-<name>[ \t]'
13
14actionban = iptables -I fail2ban-<name> 1 -s <ip> -j <blocktype>
15
16actionunban = iptables -D fail2ban-<name> -s <ip> -j <blocktype>
17
18[Init]
19name = default
20port = ssh
21protocol = tcp
22chain = INPUT

该文件首先寻找另一个名为ipables-locktype.conf的操作文件,该文件定义了block type参数,该参数配置了当客户端被禁止时将设置的限制。默认情况下,block type被设置为拒绝数据包,并使用端口无法到达的拒绝消息来回复被禁止的客户端发送的ping。我们将在下面的禁令规则中使用这一点。

接下来,我们来看看规则定义本身。在启动ail2ban服务时,actionstart操作设置iptabLes防火墙。它创建一个新链,向该链添加一个返回到调用链的规则,然后在输入链的开头插入一个规则,该规则将匹配正确协议和端口目的地的流量传递到新链。

它通过使用我们在jail.local文件中定义的action传递的值来实现这一点。name取自每个服务的段头。chainProtocolport取自该文件中的action行本身。

在这里,通过将参数名称包括在尖括号中来引用由另一个文件设置的所有参数:

\lt;参数名称&gt;‘

当我们向下移动到伴随的actionstop定义时,我们可以看到防火墙命令正在实现actionstart命令的反转。当Fail2ban服务停止时,它会干净利落地删除它添加的所有防火墙规则。

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

接下来,我们来看看实际的禁令规则,也就是所谓的行动禁令。此规则的工作方式是将新规则添加到我们创建的链中。规则与违规客户端的源IP地址匹配-当达到Maxretry限制时,将从授权日志中读取此参数。它创建由block type参数定义的块,该参数来源于文件顶部的[Include]部分。

actionunban规则删除此规则。当禁用时间已过时,这是由Fail2ban自动完成的。

最后,我们到达[Init]部分。这只是在没有传递所有适当的值的情况下调用操作文件时提供了一些缺省值。

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

现在我们已经看到了细节,让我们来回顾一下当Fail2ban启动时发生的过程。

加载初始配置文件

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

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

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

在我们的例子中,我们只有一个jail.conf文件和一个jail.local文件。在我们的jail.local文件中,我们只需要定义与jail.conf文件不同的值。现在,ail2ban进程将一组指令加载到内存中,这些指令表示它找到的所有文件的组合。

它检查每个部分并搜索enabled = true指令。如果它找到了一个,它将使用在该部分下定义的参数来构建策略并决定需要采取什么行动。在服务的部分中找不到的任何参数都使用在[DEFAULT]部分中定义的参数。

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

Fail2ban寻找一个‘action’指令,以确定要调用什么操作脚本来实现禁止/解禁策略。如果没有找到,它将使用上面确定的默认操作。

操作指令由将被读取的操作文件(S)的名称以及传递这些文件所需参数的键值字典组成。这些值通常采用参数替换的形式,引用服务部分中配置的设置。name键通常传递特殊的__name__变量的值,该变量将被设置为节的标题的值。

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

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

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

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

jare.* 文件中的服务参数还包括日志文件的位置以及用于检查文件的轮询机制(这由ackend参数定义)。它还包括一个筛选器,该筛选器应用于确定日志中的行是否表示故障。

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

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

如果正则表达式返回匹配项,它将根据由neuceregex定义的正则表达式检查该行。如果这也匹配,则ail2ban会忽略它。如果该行与Failregex中的某个表达式匹配,但与neuceregex中的某个表达式不匹配,则会为导致该行的客户端递增内部计数器,并为该事件创建关联的时间戳。

当到达由jare.* 文件中的findtime参数设置的时间窗口(由事件时间戳确定)时,内部计数器再次递减,并且该事件不再被认为与禁止策略相关。

如果在一段时间内记录了其他身份验证失败,则每次尝试都会递增计数器。如果计数器在配置的时间窗口内达到Maxretry参数设置的值,则Fail2ban通过调用服务的action.d/文件中定义的服务的actioncheck操作来发起禁令。这是为了确定actionstart‘操作是否设置了必要的结构。然后,它调用actionban`操作来禁止违规客户端。它还设置了该事件的时间戳。

当经过了由bantime参数指定的时间量时,ail2ban通过调用actionunban操作来解除对客户端的禁止。

结论

到目前为止,您已经相当深入地了解了Fail2ban是如何运行的。当您偏离标准配置时,了解ail2ban是如何工作的是很有帮助的,以便以可预测的方式操作其行为。

要了解如何使用Fail2ban保护其他服务,可以阅读如何在Ubuntu 22.04.上使用Fail2ban保护Nginx服务器

Published At
Categories with 技术
comments powered by Disqus