<?php
$banlog = file("bans.txt");
foreach($banlog as $ip) {
exec("iptables -I INPUT -s $ip -j DROP");
}
$fp = fopen("bans.txt", "w");
fwrite($fp,"");
fclose($fp);
?>
使用.htaccess我不喜欢当用户“拒绝来自$ ip”时,用户只会获得拒绝访问权限
我喜欢使用iptables,但我不想每次都登录我的服务器来阻止某人连接。所以我上面的php脚本我想每3秒执行一次而不是有限的1分钟cron选项卡。为此,我需要创建一个受控循环,每3秒执行20次。
最好的方法是什么?我的脚本在几毫秒内运行。
答案 0 :(得分:3)
读取可能有数百或数千行的文件并在每个行上运行iptable命令每三秒 疯狂 - 它必然会给你带来无法忍受的压力您的服务器,如果三秒钟中的两个作业在读取文件时互相干扰,则会导致不可预测的行为。
为什么不在每次向iptables
文件添加内容时都调用bans.txt
一次?
答案 1 :(得分:3)
使用Apache的mod_rewrite(RewriteModule)中的RewriteMap指令来实现基于动态文件的IP黑名单/白名单。
这里的例子:
https://wiki.koumbit.net/ApacheBlacklisting
http://www.debian-administration.org/articles/283
使用您的cron,只需更新黑名单文本文件即可。无需拨打iptable。 (请注意,您不需要重新启动Apache以使用基于RewriteMap的黑/白名单)
答案 2 :(得分:3)
也许你应该从不同的方向来看待这个问题 - 他们为什么被禁止?你应该使用fail2ban吗?
然而,这也很糟糕 - 从公司防火墙后面访问您网站的所有人都将共享相同的IP,因此您将禁止整个公司而不仅仅是个人。
解决方案1; 您的代码具有竞争条件,其中两个线程可以同时读取和写入同一文件,这可能会很糟糕,因为它可能会破坏您的IPTABLES设置。如果您坚持这样做,请在处理条目之前独占锁定bans.txt文件。
$banlogFp = fopen("bans.txt","a+"); // open for r+w
$tnow = time();
//loop until have lock, or 2 seconds elapsed
//(since will be invoked again after 3 sec)
while (!flock("bans.txt") && (time() - $tnow < 2) {
$banlogTxt = fread($handle, filesize($filename));
$banlogTxt = preg_replace('/\.\\r\\n/m', '@\n', $s); //any CRLF to LF
$banlog = explode("\n", $banlogTxt); //Convert to array, splittng on LF
foreach($banlog as $ip) {
//validate $ip is numeric - don't want malicious hacker to break IPTABLES
if (preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$ip+)) {
exec("iptables -I INPUT -s $ip -j DROP");
}
}
ftruncate($banlogFp, 0);
fclose($banlogFp);
}
解决方案2; 您不需要在.htaccess中使用“拒绝来自aaa.bbb.ccc.ddd”命令,而是可以使用重写规则将它们指向您选择的任何页面。比修改IPTABLES更安全,但仍然存在禁止其他人共享IP地址的大问题。 E.g。
SetEnvIf REMOTE_ADDR 192.12.131.1 REDIR="redir"
SetEnvIf REMOTE_ADDR 192.12.131.2 REDIR="redir"
SetEnvIf REMOTE_ADDR 192.12.131.3 REDIR="redir"
RewriteCond %{REDIR} redir
RewriteRule ^/$ /you_are_banned.html
解决方案3(最好!); 除非他们注册了用户名+密码,否则不允许任何人发布到您的网站,然后只是禁用用户名,而不是IP地址。使用像MySQL这样的数据库来存储用户和密码,并使用一个标志来说明它们是否被禁止。