限制共享主机上 IP 的资源使用
Limiting Resource Usage for an IP on a Shared Host
最近,我有一个 IP 快速连续调用同一页面 15,000 次,这耗尽了大量服务器资源(来自主机服务的警告电子邮件)。我在共享主机上,因此无法加载新模块,因此没有真正的选项来真正限制 IP 的带宽。
所以,我想弄清楚如何使用最少的资源来发现有问题的 IP 并将其重定向到 403 禁止访问的页面。我已经在检查常见的黑客攻击并使用 Project HoneyPot,但是对 15,000 个页面点击中的每一个都执行此操作效率不高(而且,像这个一样,它并没有捕获所有这些)。
我目前将对每个页面的访问记录到名为 visitors
的 mysql table 中。我可以想出几种方法来解决这个问题:
选项 1:使用 MySql:
1) 查询 visitors
table 过去 10 秒内来自 IP 的点击次数。
2) 如果大于某个数字(15?),将 visitors
中的最后一个条目标记为针对该 IP 被阻止。
3) 对于每个后续页面请求,visitors
table 上的查询将显示 ip 被阻止,然后我可以重定向到 403 禁止页面。
选项 2:即时修改包含黑名单 IP 的包含文件:
1) Include
一个文件,其中 returns 一组列入黑名单的 IP
2)如果当前IP不在列表中,则查询选项1中的visitors
table,查看该IP在最近10秒内的点击次数是否大于一定数量。
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();
}
?>
这里有很多要点需要解决。
查询与包含
这基本上取决于托管它的服务器。共享主机并不以良好的 IO 而闻名,您将不得不对此进行测试。这也取决于您要将多少个 IP 列入黑名单。
阻止恶意 IP
理想情况下,您不希望恶意用户点击 PHP 一旦您确定他们是恶意的。在 apache 的共享环境中做到这一点的唯一真正方法是阻止它们访问 htaccess。不推荐,但可以从 PHP.
修改 htaccess
Order Deny,Allow
Deny from xxx.xxx.xxx.xxx
缓存
阅读您的问题后,我主要担心的是您似乎没有理解问题。如果您在几秒的时间范围内收到 15,000 次点击,那么您不应该有 15,000 个数据库连接,也不应该让所有这些请求都点击 PHP。您需要缓存这些请求。如果发生这种情况,则您的系统存在根本性缺陷。家庭互联网上的 1 个用户实际上不可能使您的资源使用量激增那么多。
共享主机不是个好主意
我建议根据您的情况获得 VPS 或其他允许您使用反向代理并使用更多 caching/blacklisting/resource 监控的东西。
最近,我有一个 IP 快速连续调用同一页面 15,000 次,这耗尽了大量服务器资源(来自主机服务的警告电子邮件)。我在共享主机上,因此无法加载新模块,因此没有真正的选项来真正限制 IP 的带宽。
所以,我想弄清楚如何使用最少的资源来发现有问题的 IP 并将其重定向到 403 禁止访问的页面。我已经在检查常见的黑客攻击并使用 Project HoneyPot,但是对 15,000 个页面点击中的每一个都执行此操作效率不高(而且,像这个一样,它并没有捕获所有这些)。
我目前将对每个页面的访问记录到名为 visitors
的 mysql table 中。我可以想出几种方法来解决这个问题:
选项 1:使用 MySql:
1) 查询 visitors
table 过去 10 秒内来自 IP 的点击次数。
2) 如果大于某个数字(15?),将 visitors
中的最后一个条目标记为针对该 IP 被阻止。
3) 对于每个后续页面请求,visitors
table 上的查询将显示 ip 被阻止,然后我可以重定向到 403 禁止页面。
选项 2:即时修改包含黑名单 IP 的包含文件:
1) Include
一个文件,其中 returns 一组列入黑名单的 IP
2)如果当前IP不在列表中,则查询选项1中的visitors
table,查看该IP在最近10秒内的点击次数是否大于一定数量。
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();
}
?>
这里有很多要点需要解决。
查询与包含
这基本上取决于托管它的服务器。共享主机并不以良好的 IO 而闻名,您将不得不对此进行测试。这也取决于您要将多少个 IP 列入黑名单。
阻止恶意 IP
理想情况下,您不希望恶意用户点击 PHP 一旦您确定他们是恶意的。在 apache 的共享环境中做到这一点的唯一真正方法是阻止它们访问 htaccess。不推荐,但可以从 PHP.
修改 htaccessOrder Deny,Allow
Deny from xxx.xxx.xxx.xxx
缓存
阅读您的问题后,我主要担心的是您似乎没有理解问题。如果您在几秒的时间范围内收到 15,000 次点击,那么您不应该有 15,000 个数据库连接,也不应该让所有这些请求都点击 PHP。您需要缓存这些请求。如果发生这种情况,则您的系统存在根本性缺陷。家庭互联网上的 1 个用户实际上不可能使您的资源使用量激增那么多。
共享主机不是个好主意
我建议根据您的情况获得 VPS 或其他允许您使用反向代理并使用更多 caching/blacklisting/resource 监控的东西。