共享fail2ban禁止的IP

nde*_*mou 21 fail2ban

我在所有具有公开可见服务的服务器上使用 fail2ban,我想知道:

  1. 有没有一种简单的方法可以在我控制的主机之间共享被禁止的 IP?
  2. 是否有收集和发布这些数据的服务?

自设置此服务器的第一天起,我就进行了无数次登录尝试。

Tho*_*mBR 8

我曾经在这个站点上看到一个用于集中fail2ban数据的系统,并创建了一个修改版本。数据库是相同的,但我更改并创建了一些脚本。

我的系统有 4 个组件:

  1. fail2ban 数据库

    这是一个只包含一张表的 MySQL 数据库erp_core_fail2ban

    CREATE TABLE IF NOT EXISTS 'erp_core_fail2ban' (
      'id' bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      'hostname' varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      'created' datetime NOT NULL,
      'name' text COLLATE utf8_unicode_ci NOT NULL,
      'protocol' varchar(16) COLLATE utf8_unicode_ci NOT NULL,
      'port' varchar(32) COLLATE utf8_unicode_ci NOT NULL,
      'ip' varchar(64) COLLATE utf8_unicode_ci NOT NULL,
      PRIMARY KEY ('id'),
      KEY 'hostname' ('hostname','ip')
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 失败2ban.php

    每次主机被禁止时,它都会填充数据库:

    
    <?php
    require_once("/etc/fail2ban/phpconfig.php");
    
    $name = $_SERVER["argv"][1];
    $protocol = $_SERVER["argv"][2];
    $port = $_SERVER["argv"][3];
    if (!preg_match('/^\d{1,5}$/', $port))
        $port = getservbyname($_SERVER["argv"][3], $protocol);
    $ip = $_SERVER["argv"][4];
    
    $hostname = gethostname();
    
    $query = "INSERT INTO 'erp_core_fail2ban' set hostname='" . addslashes($hostname) . "', name='" . addslashes($name) ."', protocol='" . addslashes($protocol) . "', port='" . addslashes($port) . "', ip='" . addslashes($ip) . "', created=NOW()";
    $result = mysql_query($query) or die('Query failed: ' . mysql_error());
    mysql_close($link);
    exit;
    ?>
    
    Run Code Online (Sandbox Code Playgroud)
  3. cron2ban

    你把它每分钟都放在 crontab 上运行。它将检索最后添加的主机,并禁止它们。

    
    <?php
    // phpconfig.php will have database configuration settings
    require_once("/etc/fail2ban/phpconfig.php");
    
    // file with only a line, containing the last id banned
    $lastbanfile="/etc/fail2ban/lastban";
    
    $lastban = file_get_contents($lastbanfile);
    
    // select only hosts banned after last check
    $sql = "select id, ip from erp_core_fail2ban where id > $lastban";
    $result = mysql_query($sql) or die('Query failed: ' . mysql_error());
    mysql_close($link);
    
    while ($row = mysql_fetch_array($result)) {
            //
            $id = $row['id'];
            $ip = $row['ip'];
    
    
        exec("fail2ban-client set $jail banip $ip");
    
    Run Code Online (Sandbox Code Playgroud) } // $id contains the last banned host, add it to the config file file_put_contents($lastbanfile, $id); ?>
    Run Code Online (Sandbox Code Playgroud)
  4. 配置文件

    该文件转到 /etc/fail2ban 并具有数据库配置和监狱选择。

    
    <?php
    // jail to be used
    $jail = "ssh";
    
    // file to keep the last ban
    $lastbanfile="/etc/fail2ban/lastban";
    
    // database configuration
    $dbserver="localhost";
    $dbuser="root";
    $dbpass="root";
    $dbname="fail2ban";
    
    // connect to database
    $link = mysql_connect($dbserver, $dbuser, $dbpass) or die('Could not connect: ' . mysql_error());
    mysql_select_db($dbname) or die('Could not select database');
    
    ?>
    
    Run Code Online (Sandbox Code Playgroud)

创建这些文件并从 fail2ban 更改配置:

actionban = .....插入新行以调用 PHP 脚本的行之后:

/root/fail2ban.php <name> <protocol> <port> <ip>

在所有服务器上使用这种结构将确保每次在一台服务器上禁止一台主机时,所有其他服务器也会禁止它。


小智 5

因此,在看到相同的 IP 地址一个接一个地访问我的 Web 服务器集群后,我对如何执行此操作进行了大量研究。由于我使用的是 AWS,我认为可能有一种简单的方法,并且在我测试 5 台服务器的前两天内运行良好。

我建议的第一件事是暂时禁用 SELinux,我们会在最后处理它。我不是 SELinux 专家,但到目前为止我所做的都是有效的。

主要要求是共享文件源,我使用 AWS EFS。配置并安装新驱动器后,我将 /etc/fail2ban/fail2ban.conf 中的 logtarget 更改为 EFS 驱动器中的子文件夹。

logtarget = /efsmount/fail2ban/server1.log
Run Code Online (Sandbox Code Playgroud)

然后我写了一个简单的过滤器放在/etc/fail2ban/filter.d/fail2ban-log.conf

[Definition]

failregex = .* Ban <HOST>

ignoreregex =
Run Code Online (Sandbox Code Playgroud)

将过滤器添加到 /etc/fail2ban/jail.local

[fail2ban-log]
enabled = true
port = http,https
findtime = 86400 ; 1 day
logpath  = /efsmount/fail2ban/server1.log
        /efsmount/fail2ban/server2.log
        /efsmount/fail2ban/server3.log
        /efsmount/fail2ban/server4.log
maxretry = 1
Run Code Online (Sandbox Code Playgroud)

然后重启fail2ban

sudo fail2ban-client reload
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好!不,痛苦的部分是 SELinux。在让fail2ban 运行一段时间后,我运行了这个命令,允许fail2ban 通过过滤器。

sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -M fail2ban-nfs
Run Code Online (Sandbox Code Playgroud)

Audit2allow 会告诉你运行这个命令

sudo semodule -i fail2ban-nfs.pp
Run Code Online (Sandbox Code Playgroud)

我仍然在这里和那里检查我的 SELinux 日志,看看是否还有更多的拒绝。如果有人有关于如何使用另一种很棒的方法获得清晰的 SELinux 的提示。

sudo cat /var/log/audit/audit.log |grep fail2ban |grep denied
Run Code Online (Sandbox Code Playgroud)

在这一点上,我在重新启动 fail2ban 时仍然遇到错误。在 jail.local 中使用 action=action_mwl 时有一个错误。经过一番谷歌搜索后,我发现这是迄今为止有效的。由于指向多个文件的 logpath 指令中的换行符,我阅读了它。我尝试使用逗号、空格等,但没有其他与 action_mwl 一起使用的方法。

action_mwm = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             %(mta)s-whois-matches[name=%(__name__)s, dest="%(destemail)s", chain="%(chain)s"]

action = %(action_mwm)s
Run Code Online (Sandbox Code Playgroud)

不要忘记重新打开 SELinux!


Dre*_*ury 0

是的,是的。两者都可以做到。

您需要找到一种合适的机制来共享 IP 列表。例如,如果您使用 AWS,则可以利用 s3。您可以在 Linux 主机之间使用 rsync,或者使用所有主机共用的数据库。您可以使用您最喜欢的编程语言来构建一个服务,该语言提供一个安静的 API,您可以选择。

就如果公开共享列表而言,您可以创建一个网站并托管一个简单的文本文件,有些已经提供了此类列表(据我所知,不是众包)。如何创建自己的网站/服务超出了答案的范围,但是应该不会很难做到。