Fail2Ban 如何保护 Linux 服务器上的服务:深度解析其工作原理与配置

本文深入探讨了 Fail2Ban 这一 Linux 安全工具的工作原理、核心配置结构(Jail、Filter、Action)、以及其如何通过监控日志和动态修改防火墙规则来抵御暴力破解攻击,是提升服务器安全性的重要指南。

阅读时长: 8 分钟
共 3646字
作者: eimoon.com

Fail2Ban 是一款强大的守护进程(Daemon),专为 Linux 服务器设计,用于监控服务日志并自动封禁(Ban)那些重复进行身份验证失败的恶意客户端。它是抵御暴力破解(Brute-force)攻击和恶意用户尝试的有效工具,极大地增强了服务器的安全性。本文将深入探讨 Fail2Ban 的核心工作原理,以及如何利用其灵活的配置结构来修改或扩展其功能。

Fail2Ban 的基本原理

Fail2Ban 的主要目标是实时监控常见服务的日志文件,以识别并响应身份验证失败的模式。

当 Fail2Ban 监控特定服务(例如 SSH、Web 服务器等)的日志时,它会查找为该服务预先配置的“过滤器”(Filter)。这些过滤器通过复杂的正则表达式failregex)来精确识别特定服务的身份验证失败记录。

Fail2Ban 默认包含了针对许多常见服务的过滤文件。一旦任何服务的日志条目匹配其过滤器中定义的 failregex,就会执行预定义好的“动作”(action)。默认的动作是通过修改本地防火墙(如 iptables)规则来封禁违规的主机/IP 地址。此外,这些动作也可以扩展,例如,发送电子邮件通知系统管理员。

默认情况下,Fail2Ban 在检测到 10 分钟内有 3 次身份验证失败后会触发封禁操作,默认封禁时长为 10 分钟。这些关键参数都是完全可配置的。

当使用默认的 iptables 防火墙时,Fail2Ban 在服务启动时会创建一套新的防火墙规则链。它会在 INPUT 链中添加一条新规则,将所有指向特定端口(例如 SSH 的 22 端口)的 TCP 流量发送到这个新创建的链。在新链中,它会插入一条返回 INPUT 链的规则。当 Fail2Ban 服务停止时,该链及其所有相关规则都会被自动移除,以确保系统干净。

探索 Fail2Ban 服务设置

Fail2Ban 的核心配置集中在 /etc/fail2ban/ 目录下,该目录下包含多个重要的配置文件。

fail2ban.conf 文件主要用于配置守护进程自身的行为,例如日志记录方式、套接字(Socket)和 PID 文件位置等操作设置。然而,Fail2Ban 的主要功能和策略配置是在定义每个应用程序“监狱”(Jail)的文件中指定的。

默认情况下,Fail2Ban 附带 jail.conf 文件。但需要注意的是,直接修改此文件可能会在 Fail2Ban 更新时被覆盖。因此,最佳实践是将其复制一份到 jail.local 文件,并在 jail.local 中进行所有自定义调整。

# 如果 jail.local 文件不存在,则进行复制
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# 打开 jail.local 文件进行编辑
sudo nano /etc/fail2ban/jail.local

默认配置部分([DEFAULT]

jail.local 文件的第一个重要部分是 [DEFAULT],它定义了 Fail2Ban 策略的全局默认值。这些选项可以在后续针对每个独立服务的配置部分中被单独覆盖。

一个典型的 [DEFAULT] 部分示例(已移除注释以提高可读性):

[DEFAULT]

ignoreip = 127.0.0.1/8
bantime = 10m
findtime = 10m
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: 指定应被 Fail2Ban 忽略的 IP 地址列表,通常包括本地回环地址,以防止意外自我封锁。
  • bantime: IP 地址被封禁的时长。单位为秒,但也可以使用 m 表示分钟(例如 10m 表示 10 分钟),h 表示小时,d 表示天。
  • findtime: Fail2Ban 在此时间窗口内查找重复身份验证失败。如果在 findtime 内失败次数达到 maxretry,则触发封禁。
  • maxretry: 在 findtime 定义的时间窗口内,允许的最大失败尝试次数。超过此次数则触发封禁。
  • backend: 指定 Fail2Ban 监控日志文件的方式。auto 会尝试使用 pyinotifygamin 等效率更高的文件事件监控机制,如果不可用则退化为轮询(Polling)。
  • usedns: 定义是否使用反向 DNS 查询来辅助实施封禁。
  • destemail, sendername, mta: 用于配置邮件通知的相关参数,例如收件人邮箱、发件人名称和邮件传输代理(Mail Transfer Agent, MTA)。
  • banaction: 达到封禁阈值时将执行的动作。通常指向 /etc/fail2ban/action.d/ 目录下的一个配置文件,例如 iptables-multiport.conf
  • protocol, chain: 实施 IP 封禁时将被丢弃的流量类型(如 tcp)和 iptables 链(如 INPUT)。
  • action_, action_mw, action_mwl, action: 定义了不同的具体操作模板,其中使用了变量替换语法 %(var_name)s。默认的 actionaction_,表示仅执行封禁,不发送邮件通知。

服务特定配置部分

[DEFAULT] 部分之下,是针对特定服务的独立配置部分,用于覆盖默认设置。每个部分的标题格式为 [service_name]。任何包含 enabled = true 指令的部分都将被 Fail2Ban 读取并启用。

例如,针对 SSH 服务的配置可能如下所示:

[sshd]

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

此配置显式启用了对 SSH 服务的保护。port 设置为默认的 “ssh”(通常对应端口 22)。它指示 Fail2Ban 监控 /var/log/auth.log 文件,并使用 /etc/fail2ban/filter.d/sshd.conf 文件中定义的过滤机制来解析日志。其他未在此处明确定义的参数(如 bantimefindtime)将沿用 [DEFAULT] 部分的设置。

检查过滤器文件(filter.d

过滤器文件定义了 Fail2Ban 在日志文件中查找哪些行以识别违规特征。它们通常位于 /etc/fail2ban/filter.d/ 目录下。

以 SSH 服务的过滤器文件 sshd.conf 为例,我们可以使用 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*$
        # ... 其他 failregex 规则 ...
ignoreregex =
  • [INCLUDES]: 指定在当前文件之前或之后读取的其他过滤文件。例如,common.conf 通常定义了日志前缀 __prefix_line 等通用模式。
  • [Definition]: 定义了过滤器的实际规则。
    • _daemon: 正在监控的守护进程的名称(例如 sshd)。
    • failregex: 这是一个或多个正则表达式模式,用于匹配日志中指示身份验证失败的行。这些表达式被精心设计,旨在捕获各种可能导致身份验证失败的错误信息。Fail2Ban 通过<HOST>占位符自动识别并提取发起攻击的IP地址。
    • ignoreregex: 用于排除特定模式的正则表达式。即使这些模式通常会匹配失败条件,但如果它们匹配了 ignoreregex,则不会被计入失败次数。

检查动作文件(action.d

动作文件负责设置防火墙结构,并执行对恶意主机进行封禁、以及添加和移除这些主机等实际操作。它们通常位于 /etc/fail2ban/action.d/ 目录下。

以默认的 iptables-multiport.conf 文件为例,我们可以使用 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
  • [INCLUDES]: 引用其他动作文件。例如,iptables-blocktype.conf 通常定义了 blocktype 参数(默认是拒绝数据包并回复端口不可达)。
  • [Definition]: 定义了实际的 iptables 命令序列。
    • actionstart: 在 Fail2Ban 服务启动时,此部分定义的命令会设置 iptables 防火墙规则。它通常包括创建一个新的防火墙链(例如 fail2ban-<name>),并将所有匹配的流量重定向到该链。
    • actionstop: 在 Fail2Ban 服务停止时,此部分的命令会清除所有由 Fail2Ban 添加的防火墙规则,确保系统状态的干净。
    • actioncheck: 在尝试添加封禁规则之前,此命令用于验证所需的防火墙链是否已经正确创建。
    • actionban: 当检测到客户端达到 maxretry 限制时,此命令会在之前创建的链中添加一条规则,以阻止违规客户端的 IP 地址(<ip>)。
    • actionunban: 当 bantime 指定的封禁时间结束后,此命令会自动移除对应的封禁规则,解除对客户端的封禁。
  • [Init]: 提供默认值,以防调用此动作文件时未传入所有必需的参数。

Fail2Ban 服务如何处理配置文件以实施封禁

Fail2Ban 的工作流程可以概括为以下步骤:

  1. 加载初始配置文件:

    • Fail2Ban 首先读取并处理主配置文件 fail2ban.conf
    • 随后,它会按照字母顺序依次读取 jail.confjail.d/*.confjail.localjail.d/*.local 文件。这些文件中的新值会覆盖之前读取的旧值,形成最终的配置集合。
    • Fail2Ban 根据这些文件中的指令,在内存中构建一套完整的策略。
    • 它会遍历每个服务配置部分([service_name]),查找 enabled = true 指令。如果找到,则使用该部分定义的参数来构建针对特定服务的策略。未明确定义的参数会沿用 [DEFAULT] 部分的值。
  2. 解析动作文件以确定启动动作:

    • Fail2Ban 会查找 action 指令,以确定当触发封禁或解封事件时需要调用哪个动作脚本来实施策略。
    • 它会在 /etc/fail2ban/action.d/ 目录中查找相应的动作文件(优先使用 .local 文件,如果不存在则使用 .conf 文件)。
    • 接着,Fail2Ban 会解析这些动作文件,以确定需要执行的 actionstart 操作。这些操作通常包括创建必要的防火墙结构(如 iptables 链)。动作文件中定义的参数会动态地用于生成具体的防火墙规则。
  3. 解析过滤文件并实施监控与封禁:

    • 服务配置中包含了要监控的日志文件位置(logpath)以及用于检查文件的轮询机制(backend 参数)。
    • Fail2Ban 会在 /etc/fail2ban/filter.d/ 目录中查找与服务配置中 filter 参数匹配的过滤器文件(同样优先使用 .local 文件)。
    • 它使用这些过滤器文件中定义的正则表达式(failregex)来实时读取并解析服务日志文件。
    • 如果日志中的新行匹配 failregex 但不匹配 ignoreregex,则 Fail2Ban 会增加违规客户端的内部失败计数器,并记录事件发生的时间戳。
    • 当时间窗口(findtime)内的某个事件的“新鲜度”过期时,对应的计数器会自动递减。
    • 如果在配置的 findtime 时间窗口内,计数器达到或超过 maxretry 值,Fail2Ban 将判断该客户端为恶意尝试,并通过调用 actioncheckactionban 动作来实施封禁。
    • bantime 指定的封禁时间过去后,Fail2Ban 会自动调用 actionunban 动作来解除对该客户端的封禁。

结论

通过对 Fail2Ban 的内部运作方式进行深入了解,您不仅可以更清楚地理解它如何有效地保护您的 Linux 服务器上的服务,还能在需要时灵活修改其行为,以满足您特定的安全需求和运维场景。掌握 Fail2Ban 的配置与原理,是提升服务器安全性的关键一步。

关于

关注我获取更多资讯

公众号
📢 公众号
个人号
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计