是否必须在由fail2ban读取的日志文件上设置一组特殊的权限?

是否必须在由fail2ban读取的日志文件上设置一组特殊的权限?

我最近在我的 Minecraft 服务器上遇到了一些垃圾邮件,我怀疑这些垃圾邮件来自某种端口扫描程序或其他机器人。到目前为止,无论它是什么,都没有构成任何真正的威胁,但我认为安全总比后悔好。我一直在尝试设置fail2ban禁止发起 3 次或更多失败连接尝试的任何 IP。我在 Reddit 上看到其他人使用相同的工具取得了一些成功,所以我想尝试一下。

然而,我有点卡住了。每当我尝试启动fail2ban服务时,它都会失败并出现以下错误:

ERROR   Failed during configuration: Have not found any log file for minecraft jail
ERROR   Async configuration of server failed

logpath谷歌搜索显示,这通常是因为此“minecraft”相应文件中的配置选项引用的路径jail.conf无效或指向不存在的文件。我检查了一遍又一遍,可以确认我指定的路径确实存在,所以我认为这是其他原因。

如果我通过其配置文件禁用“minecraft”单元,启动fail2ban systemd服务,重新启用“minecraft”单元,并使用命令重新加载fail2ban服务器fail2ban-client,我会收到以下错误:

[root@fedora ~]# fail2ban-client reload
2023-06-30 21:37:28,314 fail2ban                [4565]: ERROR   NOK: (13, 'Permission denied')
[Errno 13] Permission denied: '/path/omitted.log'

嗯,好吧...也许权限不好?只是为了确保权限不会造成妨碍,我创建了一个临时测试文件以在/tmp具有以下权限的目录中使用:

[root@fedora ~]# ll -d /tmp
drwxrwxrwt. 29 root root 640 Jun 30 22:10 /tmp
[root@fedora ~]# ll /tmp/testing.log 
-rwxrwxrwx. 1 root root 0 Jun 30 21:29 /tmp/testing.log

从上面重复重新加载过程显示没有骰子......我错过了什么?有人有什么想法可以让我尝试一下吗?任何帮助深表感谢!如果我需要提供更多详细信息,请告诉我。

以下是执行上述重新加载过程后,fail2ban 服务器的日志输出(启用了 DEBUG 日志记录):

[root@fedora ~]# tail -n 50 /var/log/fail2ban.log 
<output removed for brevity>
2023-06-30 21:37:28,186 fail2ban.server         [4553]: INFO    Start Fail2ban v1.0.2
2023-06-30 21:37:28,187 fail2ban.server         [4553]: INFO    Changed logging target to /var/log/fail2ban.log for Fail2ban v1.0.2
2023-06-30 21:37:28,187 fail2ban.ipdns          [4553]: DEBUG   IPv6 is auto
2023-06-30 21:37:28,187 fail2ban.jail           [4553]: INFO    Creating new jail 'minecraft'
2023-06-30 21:37:28,311 fail2ban.jail           [4553]: DEBUG   Backend 'pyinotify' failed to initialize due to No module named 'pyinotify'
2023-06-30 21:37:28,312 fail2ban.jail           [4553]: DEBUG   Backend 'gamin' failed to initialize due to No module named 'gamin'
2023-06-30 21:37:28,312 fail2ban.jail           [4553]: INFO    Jail 'minecraft' uses poller {}
2023-06-30 21:37:28,312 fail2ban.filter         [4553]: DEBUG   Setting usedns = warn for FilterPoll(Jail('minecraft'))
2023-06-30 21:37:28,312 fail2ban.filter         [4553]: DEBUG   Created FilterPoll(Jail('minecraft'))
2023-06-30 21:37:28,312 fail2ban.filterpoll     [4553]: DEBUG   Created FilterPoll
2023-06-30 21:37:28,312 fail2ban.jail           [4553]: INFO    Initiated 'polling' backend
2023-06-30 21:37:28,312 fail2ban.filter         [4553]: DEBUG   Setting usedns = warn for FilterPoll(Jail('minecraft'))
2023-06-30 21:37:28,312 fail2ban.server         [4553]: DEBUG     failregex: '\\(\\/<HOST>\\:'
2023-06-30 21:37:28,313 fail2ban.filter         [4553]: INFO      maxRetry: 3
2023-06-30 21:37:28,313 fail2ban.filter         [4553]: INFO      findtime: 86400
2023-06-30 21:37:28,313 fail2ban.actions        [4553]: INFO      banTime: 2592000
2023-06-30 21:37:28,313 fail2ban.filter         [4553]: INFO      encoding: UTF-8
2023-06-30 21:37:28,313 fail2ban.server         [4553]: INFO    Reload finished.
2023-06-30 21:37:28,313 fail2ban.transmitter    [4553]: ERROR   Command ['reload', '--all', [], [['set', 'syslogsocket', 'auto'], ['set', 'loglevel', 'DEBUG'], ['set', 'logtarget', '/var/log/fail2ban.log'], ['set', 'allowipv6', 'auto'], ['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3'], ['set', 'dbmaxmatches', 10], ['set', 'dbpurgeage', '1d'], ['add', 'minecraft', 'auto'], ['set', 'minecraft', 'usedns', 'warn'], ['set', 'minecraft', 'addfailregex', '\\(\\/<HOST>\\:'], ['set', 'minecraft', 'maxretry', 3], ['set', 'minecraft', 'maxmatches', 3], ['set', 'minecraft', 'findtime', '1d'], ['set', 'minecraft', 'bantime', '30d'], ['set', 'minecraft', 'ignorecommand', ''], ['set', 'minecraft', 'logencoding', 'auto'], ['set', 'minecraft', 'addlogpath', '/tmp/testing.log', 'head'], ['set', 'minecraft', 'addaction', 'firewallcmd-rich-rules'], ['multi-set', 'minecraft', 'action', 'firewallcmd-rich-rules', [['actionstart', ''], ['actionstop', ''], ['actioncheck', ''], ['actionban', 'ports="0:65535"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family=\'<family>\' source address=\'<ip>\' port port=\'$p\' protocol=\'tcp\' reject type=\'<rejecttype>\'"; done'], ['actionunban', 'ports="0:65535"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family=\'<family>\' source address=\'<ip>\' port port=\'$p\' protocol=\'tcp\' reject type=\'<rejecttype>\'"; done'], ['port', '0:65535'], ['protocol', 'tcp'], ['chain', '<known/chain>'], ['name', 'minecraft'], ['actname', 'firewallcmd-rich-rules'], ['family', 'ipv4'], ['zone', 'public'], ['service', 'ssh'], ['rejecttype', 'icmp-port-unreachable'], ['blocktype', 'REJECT --reject-with <rejecttype>'], ['rich-blocktype', "reject type='<rejecttype>'"], ['family?family=inet6', 'ipv6'], ['rejecttype?family=inet6', 'icmp6-port-unreachable']]], ['start', 'minecraft']]] has failed. Received PermissionError(13, 'Permission denied')
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/fail2ban/server/transmitter.py", line 58, in proceed
    ret = self.__commandHandler(command)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/fail2ban/server/transmitter.py", line 109, in __commandHandler
    self.__commandHandler(cmd)
  File "/usr/lib/python3.11/site-packages/fail2ban/server/transmitter.py", line 89, in __commandHandler
    return self.__commandSet(command[1:])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/fail2ban/server/transmitter.py", line 258, in __commandSet
    self.__server.addLogPath(name, value, tail)
  File "/usr/lib/python3.11/site-packages/fail2ban/server/server.py", line 382, in addLogPath
    filter_.addLogPath(fileName, tail)
  File "/usr/lib/python3.11/site-packages/fail2ban/server/filter.py", line 1006, in addLogPath
    log = FileContainer(path, self.getLogEncoding(), tail)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/fail2ban/server/filter.py", line 1327, in __init__
    handler = open(filename, 'rb')
              ^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: '/tmp/testing.log'

答案1

感谢 @roaima 分享链接在 CentOS 7 上安装fail2ban,这引导我走上解决这个问题的道路。

长话短说:

问题出在 SELinux 上。禁用它、更改其访问控制策略或更改存储日志文件的位置是(我发现)解决此问题的唯一方法。

解决方案:

一个快速而肮脏的修复和/或验证 SELinux 的问题是将 SELinux 的强制策略设置为“宽容”而不是“强制”。根据提供的解释这篇红帽帮助文章,将 SELinux 的执行策略设置为“许可”可以有效地禁用任何访问控制策略的执行。因此,如果 SELinux 访问策略是进程无法访问日志文件的原因fail2ban-server,禁用它应该可以让您了解 SELinux 是否是问题所在。这可以通过执行类似于以下操作的操作来完成:

[root@kaleb-desktop ~]# sestatus | grep "Current mode"
Current mode:                   enforcing
[root@kaleb-desktop ~]# setenforce 0
[root@kaleb-desktop ~]# sestatus | grep "Current mode"
Current mode:                   permissive
[root@kaleb-desktop ~]#

现在,如果您发现自己处于与我类似的情况,并且执行上述操作突然可以fail2ban访问您想要的日志文件,那么您很幸运。如果不是,那么不幸的是,您的问题可能是其他问题。如果您不喜欢保留 SELinux,我想上述方法已经足够了。然而,我并不一定想完全摆脱 SELinux。

如果您深入研究系统审核日志,您会发现 SELinux 实际上为您提供了更永久的问题解决方案。运行sealert -l "*"(我必须在 Fedora 38 系统上手动安装)将输出类似以下内容的内容:

SELinux is preventing fail2ban-server from open access on the file /tmp/testing.log.

*****  Plugin catchall (100. confidence) suggests   **************************

If you believe that fail2ban-server should be allowed open access on the testing.log file by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'fail2ban-server' --raw | audit2allow -M my-fail2banserver
# semodule -X 300 -i my-fail2banserver.pp

如输出中所述,建议的解决方案是创建一个可以应用于现有策略之上的本地策略模块。但是,正如 @roaima 共享链接的接受解决方案中所指出的,该策略可能会被未来的软件包更新覆盖selinux-policy

因此,最终、最永久的解决方案是将日志移动到现有 SELinux 访问控制策略满意的目录。就我而言,我能够将日志移动到/var/logSELinux 似乎满意的子目录中。 YMMV。

我还想提一下,journalctl -lfu fail2ban我的系统上的输出并未反映@roaima 共享链接的输出。这个问题是 8 年前提出的,所以显然在记录方式方面可能发生了很多变化,所以请注意这一点。

很抱歉啰嗦,但我很高兴有这个机会深入研究我以前不理解的东西,并从另一方面得到更好的理解。我希望这个解释可以帮助处于类似情况的其他人!

相关内容