最近,我连续快速连续一次IP呼叫15,000次,这耗尽了大量的服务器资源(从主机服务产生了警告电子邮件)。我在共享主机上,因此无法加载新模块,因此无法真正限制IP的带宽。
所以,我正在试图找出如何使用最少的资源来发现违规的IP并将其重定向到403 Forbidden页面。我已经在检查常见的黑客攻击并使用Project HoneyPot了,但是为15,000个页面点击中的每一个执行此操作都效率不高(而且,就像这个一样,它并不能完全捕获它们。)
我目前将每个页面的访问权限记录到名为visitors
的mysql表中。我可以想象几种方法:
选项1:使用MySql:
1)查询visitors
表,查看过去10秒内IP的命中数。
2)如果大于某个数字(15?),则将visitors
中的最后一个条目标记为已阻止此IP。
3)对于每个后续页面请求,visitors
表上的查询将显示ip被阻止,然后我可以重定向到403 Forbidden页面。
选项2:动态修改包含列入黑名单的IP的包含文件:
1)Include
一个文件,它返回一组列入黑名单的IP
2)如果当前IP不在列表中,请按照选项1查询visitors
表,以查看过去10秒内IP的命中数是否大于某个数字。
3)如果IP有问题,请修改include
文件以包含此IP地址,如下所示。
本质上,我的问题是:哪个使用更多资源(x 15,000):对数据库的查询,或者下面的代码使用include
来读取文件然后是array_search(),或者是更好的方法吗?
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$filename='__blacklist.php';
if (file_exists($filename)){
// get array of excluded ip addresses
$array = (include $filename);
// if current address is in list, send to 403 forbidden page
var_dump($array);
if (is_array($array) && array_search($ip, $array) !== false){
blockAccess("Stop Bugging Me!");
}
} else {
echo "$filename does not exist";
}
// evaluate some condition which if true will cause IP to be added to blacklist - this will be a query to a MySql table determining number of hits to the site over a period of time like the last 10 seconds.
if (TRUE){
blockip($ip);
}
// debug - let's see what is blocked
// $array = (include $filename);
// var_dump($array);
// add the ip to the blacklist
function blockip($ip){
$filename='__blacklist.php';
if (! file_exists($filename)){
// create the include file
$handle = fopen($filename, "w+");
// write beginning of file - 111.111.111.111 is a placeholder so all new ips can be added
fwrite($handle, '<?php return array("111.111.111.111"');
} else {
// let's block the current IP
$handle = fopen($filename, 'r+');
// Don't use filesize() on files that may be accessed and updated by parallel processes or threads
// (as the filesize() return value is maintained in a cache).
// use fseek & ftell instead
fseek($handle, 0 ,SEEK_END);
$filesize = ftell($handle);
if ($filesize > 20){
// remove ); from end of file so new ip can be added
ftruncate($handle, $filesize-2);
// go to end of file
fseek($handle, 0 ,SEEK_END);
} else {
// invalid file size - truncate file
$handle = fopen($filename, "w+");
// write beginning of file with a placeholder so a new ip can be added
fwrite($handle, '<?php return array("111.111.111.111"');
}
}
//add new ip and closing of array
fwrite($handle, "," . PHP_EOL . '"' . $ip . '");');
fclose($handle);
}
function blockAccess($message) {
header("HTTP/1.1 403 Forbidden");
echo "<!DOCTYPE html>\n<html>\n<head>\n<meta charset='UTF-8' />\n<title>403 Forbidden</title>\n</head>\n<body>\n" .
"<h1>Forbidden</h1><p>You don't have access to this page.</p>" .
"\n</body>\n</html>";
die();
}
?>
答案 0 :(得分:0)
这里有很多要点。
这基本上归结为它托管的服务器。共享主机并不以良好的IO而闻名,您必须对此进行测试。这还取决于您将被列入黑名单的IP数量。
理想情况下,一旦确定恶意用户是恶意用户,就不希望恶意用户访问PHP。在apache的共享环境中执行此操作的唯一真正方法是阻止它们进入htaccess。它不推荐,但可以从PHP修改htaccess。
Order Deny,Allow
Deny from xxx.xxx.xxx.xxx
我在阅读你的问题时主要担心的是你似乎不明白这个问题。如果您在几秒钟的时间内收到15,000次点击,则不应该有15,000个数据库连接,并且您不应该让所有这些请求都达到PHP。您需要缓存这些请求。如果发生这种情况,您的系统存在根本缺陷。家庭互联网上的1个用户在物理上不可能将资源使用量大幅增加。
我建议在你的情况下获得VPS或其他允许你使用反向代理并使用更多缓存/黑名单/资源监控的东西。