【问题标题】:How can I invoke a shell or Perl script from iptables?如何从 iptables 调用 shell 或 Perl 脚本?
【发布时间】:2015-03-29 04:14:44
【问题描述】:

我们正在使用 CentOS,并希望禁止几个亚洲国家访问整个服务器。我们检查的几乎每个试图入侵我们服务器的 IP 都分配给了一个亚洲国家(俄罗斯、中国、巴基斯坦等)

我们有一个国家 MySQL 数据库的 IP,我们可以有效地查询,并想尝试类似的东西:

-A INPUT -p tcp -m tcp --dport 80 -j /path/to/perlscript.pl

脚本需要将 IP 作为参数传入,然后它会返回 ACCEPT 或 DROP 目标?

感谢您的回答,这是我的跟进。

你知道这是否可能吗?有一个规则指向一个返回目标的脚本? (接受/放弃)

不完全确定 ipset 是如何工作的,我猜需要进行实验,但看起来它创建了一个规则。例如,它如何处理分配给它的 6000 多个射程的俄罗斯?我们希望总共添加大概 20 到 40 个国家/地区,因此我们最终可能需要添加超过 100,000 个范围。单个 MySQL 查询的开销不会少一些吗?

SELECT country FROM ip_countries WHERE $VAR{ip} >= range1 && $VAR{ip} <= range2

我们使用的数据库在这里免费提供:http://software77.net/geo-ip/

它通过使用以下公式将 IP 转换为数字来表示数据库中的 IP:

$VAR{numberedIP} = $octs[3] + ($octs[2] * 256) + ($octs[1] * 256 * 256) + ($octs[0] * 256 * 256 * 256); 

它将范围的开始存储在“range1”列中,将范围的结束存储在“range2”列中。

因此,您可以看到我们如何使用上述查询查找 IP。从字面上看,得到结果不到百分之一秒,而且非常准确。我们在专用服务器上有一个网站,流量非常低。但与我检查过的所有服务器一样,这台服务器每天都会受到黑客机器人的攻击,检查电子邮件帐户、FTP 帐户等。而且我曾经使用过的几乎每台 Web 服务器迟早都会受到攻击。在我们的案例中,来自亚洲国家的 99.99% 的流量都带有犯罪意图。

我们希望它通过 iptables 运行,以便覆盖所有端口,而不仅仅是 HTTP,例如使用 .htaccess 中的指令。

您认为 ipset 仍然会更快更高效吗?

【问题讨论】:

  • 在每个 tcp 数据包调用单独进程的情况下考虑网络性能。
  • 为工作使用正确的工具。在这种情况下,它是ipset。您的 Perl 脚本可以从 MySQL 数据库中提取所有 IP 范围,并在对 ipset 的调用中使用它们。然后使用iptables 阻止整个集合。

标签: mysql perl centos iptables


【解决方案1】:

为每个匹配的数据包启动perl 太慢了。此类事情的正确工具是ipsetipsetman page 上提供了更多信息和文档。

在 CentOS 中,您可以使用 yum 安装它。当然,所有这些命令和脚本都需要以 root 身份运行:

# yum install ipset

接下来安装内核模块(您也希望在启动时也这样):

# modprobe -v ipset ip_set_hash_netport

然后使用如下脚本填充ipset 并使用iptables 阻止其范围内的IP:

#!/usr/bin/env perl
use strict;
use warnings; 
use DBI; 

my $dbh = DBI->connect('... your DSN ...',...);
# I have no knowledge of your schema, but if you can pull the 
# address range in the form: AA.BB.CC.DD/NN
my $ranges = $dbh->selectcol_arrayref(
   q{SELECT cidr FROM your_table WHERE country_code IN ('CN',...)});

`ipset create geoblock hash:netport`;
for (@$ranges) { 
    # to match on port 80:
    `ipset add geoblock $_,80`; 
}
`iptables -I INPUT -m set --set geoblock src -j DROP`;

如果您想阻止所有端口而不仅仅是 80,请使用 ip_set_hash_net 模块而不是 ip_set_hash_netport,将 hash:netport 更改为 hash:net,并从 ipset 命令中删除 ,80

【讨论】:

  • 感谢您的信息。你知道这是否可能吗?有一个规则指向一个返回目标的脚本? (接受/放弃)
  • 不,据我所知不可能。但是,如果您愿意,可以编写一个netfilter 内核模块。