限制共享主机上的IP的资源使用情况

时间:2015-04-11 18:42:00

标签: php mysql resources

最近,我连续快速连续一次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();
    }

?>

1 个答案:

答案 0 :(得分:0)

这里有很多要点。

查询与包含

这基本上归结为它托管的服务器。共享主机并不以良好的IO而闻名,您必须对此进行测试。这还取决于您将被列入黑名单的IP数量。

阻止恶意IP

理想情况下,一旦确定恶意用户是恶意用户,就不希望恶意用户访问PHP。在apache的共享环境中执行此操作的唯一真正方法是阻止它们进入htaccess。它不推荐,但可以从PHP修改htaccess。

Order Deny,Allow
Deny from xxx.xxx.xxx.xxx

缓存

我在阅读你的问题时主要担心的是你似乎不明白这个问题。如果您在几秒钟的时间内收到15,000次点击,则不应该有15,000个数据库连接,并且您不应该让所有这些请求都达到PHP。您需要缓存这些请求。如果发生这种情况,您的系统存在根本缺陷。家庭互联网上的1个用户在物理上不可能将资源使用量大幅增加。

共享托管是一个坏主意

我建议在你的情况下获得VPS或其他允许你使用反向代理并使用更多缓存/黑名单/资源监控的东西。