好吧,我制作了一个脚本来仅针对核心请求处理它(没有会话请求或其他不调用核心的请求)。如果你看看谷歌,你会发现脚本/类会因为每次高负载而杀死你的服务器。事实上,许多人使用 SESSION 并且可能还使用 SQL/Database 将使您获得作为服务器杀手的泛洪保护。此外,SESSION 需要 Cookie(或 GET SID),因此您可以轻松地操纵 SESSION 以获得新的 SESSION ID。
我的功能是基于文本的,并且做一个简单的处理。坏事是您可能不得不不时使用 CronJob 删除 ips。与其他脚本相比,它的速度大约快 10 倍(并且比会话节省更多)。
我不知道它是否真的有用。;) 您可能希望将 rpm 值更改为 less 或/以及 200 req。我的设置是禁止机器人在 <=6 秒内执行间隔请求。
<?php
function ht_request_limiter() {
if (!isset($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
if (empty($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
$path = '/your/path/ipsec/'; // I use a function to validate a path first and return if false...
$path = $path.$_SERVER['REMOTE_ADDR'].'.txt'; // Real file path (filename = <ip>.txt)
$now = time(); // Current timestamp
if (!file_exists($path)) { // If first request or new request after 1 hour / 24 hour ban, new file with <timestamp>|<counter>
if ($handle = fopen($path, 'w+')) {
if (fwrite($handle, $now.'|0')) { chmod($path, 0700); } // Chmod to prevent access via web
fclose($handle);
}
}
else if (($content = file_get_contents($path)) !== false) { // Load existing file
$content = explode('|',$content); // Create paraset [0] -> timestamp [1] -> counter
$diff = (int)$now-(int)$content[0]; // Time difference in seconds from first request to now
if ($content[1] == 'ban') { // If [1] = ban we check if it was less than 24 hours and die if so
if ($diff>86400) { unlink($path); } // 24 hours in seconds.. if more delete ip file
else {
header("HTTP/1.1 503 Service Unavailable");
exit("Your IP is banned for 24 hours, because of too many requests.");
}
}
else if ($diff>3600) { unlink($path); } // If first request was more than 1 hour, new ip file
else {
$current = ((int)$content[1])+1; // Counter + 1
if ($current>200) { // We check rpm (request per minute) after 200 request to get a good ~value
$rpm = ($current/($diff/60));
if ($rpm>10) { // If there was more than 10 rpm -> ban (if you have a request all 5 secs. you will be banned after ~17 minutes)
if ($handle = fopen($path, 'w+')) {
fwrite($handle, $content[0].'|ban');
fclose($handle);
// Maybe you like to log the ip once -> die after next request
}
return;
}
}
if ($handle = fopen($path, 'w+')) { // else write counter
fwrite($handle, $content[0].'|'.$current .'');
fclose($handle);
}
}
}
}
编辑:我测试请求时间的方法是使用 microtime 并模拟 10'000 个用户。我问谷歌并测试(例如)http://technitip.net/simple-php-flood-protection-class
所以我不知道那里应该简单吗?您一次有大约 3 个 SQL 请求,例如:
$this -> user_in_db($ip))
$this->user_flooding($ip);
$this->remove_old_users();
它可能提供更多功能,但所有合法用户都白白使用服务器时间。;)