我在所有具有公开可见服务的服务器上使用 fail2ban,我想知道:
- 有没有简单的在我控制的主机之间共享被禁止的 IP 的方法是什么?
- 是否有一种服务可以收集并发布这些数据?
自从设置该服务器的第一天起,我进行了无数次登录尝试。
答案1
我曾经见过一个用于集中fail2ban数据的系统在这个网站上,并创建了一个修改版本。数据库是一样的,但我修改并创建了一些脚本。
我的系统有 4 个组件:
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;
fail2ban.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; ?>
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'];
} // $id contains the last banned host, add it to the config file file_put_contents($lastbanfile, $id); ?>exec("fail2ban-client set $jail banip $ip");
php配置
该文件转到 /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'); ?>
创建这些文件并从 fail2ban 更改配置:
在该行后面actionban = .....
插入一个新行来调用 PHP 脚本:
/root/fail2ban.php <name> <protocol> <port> <ip>
在所有服务器上使用此结构将确保每次一台主机在一台服务器上被禁止时,所有其他服务器也会禁止该主机。
答案2
因此,在看到同一个 IP 地址接连访问我的 Web 服务器集群后,我做了大量研究,了解如何做到这一点。由于我使用的是 AWS,所以我想可能有一个简单的方法,而且在我测试 5 台服务器的前两天,它运行良好。
我建议的第一件事是暂时禁用 SELinux,我们将在最后处理它。我不是 SELinux 专家,但我所做的到目前为止是有效的。
主要要求是共享文件源,我使用 AWS EFS。配置并安装新驱动器后,我将 /etc/fail2ban/fail2ban.conf 中的 logtarget 更改为 EFS 驱动器中的子文件夹。
logtarget = /efsmount/fail2ban/server1.log
然后我编写了一个简单的过滤器并将其放在 /etc/fail2ban/filter.d/fail2ban-log.conf 中
[Definition]
failregex = .* Ban <HOST>
ignoreregex =
将过滤器添加到 /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
然后重新启动fail2ban
sudo fail2ban-client reload
到目前为止一切顺利!不,痛苦的部分是 SELinux。在我让 fail2ban 运行一段时间后,我运行了这个命令,该命令将允许 fail2ban 通过过滤器。
sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -M fail2ban-nfs
Audit2allow 将告诉您运行此命令
sudo semodule -i fail2ban-nfs.pp
我仍在检查我的 SELinux 日志,看看是否还有更多拒绝。如果有人能提供一些关于如何使用其他方法清除 SELinux 的提示,那就太好了。
sudo cat /var/log/audit/audit.log |grep fail2ban |grep denied
此时,重新启动 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
不要忘记重新打开 SELinux!
答案3
另一种选择fail2ban
是拒绝主机它带有同步功能。安装与 非常相似fail2ban
,请参阅Cyberciti 的教程提供了更多详细信息。
问题是同步服务是集中式的,并且服务器端的源代码似乎不可用,因此您无法轻松启动自己的 DenyHosts 服务,而必须依赖第三方(这对于某些用例来说可能没问题)。
答案4
是的,两者都可以。
您需要找到一种合适的机制来共享 IP 列表。例如,如果您使用 AWS,则可以利用 s3。您可以在 Linux 主机之间使用 rsync,或者使用所有主机共用的数据库。您可以使用您最喜欢的编程语言来开发一项提供 restful API 的服务,选择权在您手中。
如果要公开共享列表,您可以创建一个网站并托管一个简单的文本文件,有些网站已经提供了这样的列表(据我所知不是众包的)。如何创建自己的网站/服务超出了答案的范围,但做起来应该不会太难。