Я получаю ошибку, которую я не могу воспроизвести.
Следующий код является частью модуля, который защищает от атак. Этот фрагмент отслеживает количество обращений к конкретному агенту пользователя бота, который я получаю.
После многих лет беспроблемного использования, я внезапно получаю ошибку:
Неверно сформированное числовое значение;
Это происходит на линии:
$seconds = time() - $time;
Значение $ time равно 2016-10-02 19:33:42
функция safefilename () возвращает:
Mozilla-5-0-совместимый-spbot-5-0-3-HTTP-OpenLinkProfiler-орг-бот
Имя файла, на который записывается и считывается:
bot_2016-10-02–19-33-42_Mozilla-5-0-совместимая-spbot-5-0-3-HTTP-Open_104.131.179.5.log
методология
Код ниже задает боты и записывает имя файла, основанное на пользовательском агенте, и время создания файла. Каждый раз, когда этот пользовательский агент используется, он добавляет «X» в файл, чтобы я мог отслеживать, сколько раз этот агент посетил. Если бот нацелен на меня более определенного количества раз, я блокирую его.
Приведенный ниже код дает результат желания при тестировании и в производстве – кроме случаев, когда эта ошибка возникает. В упомянутом файле записано 6 байтов, поэтому оно было прочитано и записано успешно 5 раз раньше.
Ошибка php была зарегистрирована в 06:37:04, и мой файл журнала сервера показывает эти хиты:
104.131.63.140 - - [10/Dec/2016:06:36:59 -0800] "GET /robots.txt HTTP/1.1" 301 257 "-" "Mozilla/5.0 (compatible; spbot/5.0.3; +http://OpenLinkProfiler.org/bot )"
104.131.63.140 - - [10/Dec/2016:06:36:59 -0800] "GET /robots.txt HTTP/1.1" 200 1460 "-" "Mozilla/5.0 (compatible; spbot/5.0.3; +http://OpenLinkProfiler.org/bot )"
104.131.63.140 - - [10/Dec/2016:06:37:04 -0800] "GET / HTTP/1.1" 403 937 "-" "Mozilla/5.0 (compatible; spbot/5.0.3; +http://OpenLinkProfiler.org/bot )"
104.131.63.140 - - [10/Dec/2016:06:37:05 -0800] "GET / HTTP/1.1" 301 247 "-" "Mozilla/5.0 (compatible; spbot/5.0.3; +http://OpenLinkProfiler.org/bot )"
PHP Code Я извлек следующий код, который можно запустить самостоятельно для тестирования.
// this is my site address define("STATIC_SITE_ROOT", "http://static"); $agent = "Mozilla/5.0 (compatible; spbot/5.0.3; +http://OpenLinkProfiler.org/bot )"; $ip = '127.0.0.1'; $t = new test(); $t->testAgent($agent, $ip); class test { public $agent; public $ip; public $maxbadpages = 100; function testAgent($agent, $ip){ $this->agent = $agent; $this->ip = $ip; if (strlen($badbot = $this->badbot($this->agent)) > 0){ $new = FALSE; $path = $_SERVER['DOCUMENT_ROOT'] . "/logs"; // $filename = "bot-" . time() . "-" . safefilename(substr($this->agent, 0, 50)); $safefilename = safefilename(substr($this->agent, 0, 50)); $filename = "bot_" . date("Ymd--His") . "_" . $safefilename . "_" . $this->ip . ".log"; $filter = $safefilename; $afiles = getDirArray($path, $filter); if (count($afiles) > 0){ // bot file already exists $filename = $afiles[0]; } else { // add time to filename if crating new file $new = TRUE; } $fullfilename = "$path/$filename"; // log a counter (# bytes in file) file_put_contents($fullfilename, "X", FILE_APPEND); // number of hits == size of file $size = filesize($fullfilename); // count hits to determine if block via htaccess // if > # entries in log from a useragent, ban it if ($size > $this->maxbadpages){ $this->blockagent($this->agent, $this->ip, "> $this->maxbadpages hits"); } elseif (! $new) { // test for hits per second $blockagent = FALSE; $parts = explode("_", $filename); // 2nd part is the time // $time = strtotime($parts[1]); $parts2 = explode("--", $parts[1]); $time = $parts2[0] . " " . str_replace("-",":",$parts2[1]); // seconds is time elapsed $seconds = time() - $time; // check for various scenarios if ($size > $seconds * 2){ // more than average of 2 hits per second for any period $blockagent = TRUE; $reason = "$size (hits) > $seconds (seconds) * 2"; } if ($seconds >= 10 && $size > $seconds * 1){ // more than 1 hit per second over 10 seconds $blockagent = TRUE; $reason = "$seconds (seconds) >= 10 && $size (hits) > $seconds (seconds) * 1"; } if ($blockagent){ $this->blockagent($this->agent, $this->ip, $reason); } } $this->blockAccess("bad bot: ". $badbot); } } function blockAgent($message){ die("Block Agent: " . $message); } function blockAccess($message){ die("Block Access: " . $message); } function badbot($agent) { if (stripos($agent, "bot") !==FALSE){ return "match 'bot' in agent: ($agent)"; } elseif (stripos($agent, "spider") !==FALSE){ return "match 'spider' in agent: ($agent)"; } elseif (stripos($agent, "crawl") !==FALSE){ return "match 'crawl' in agent: ($agent)"; } $badbots = array( "007AC9", "2Bone", "404 Checker", "There are many more bad bots contained in this array..."); foreach ($badbots as $bot) { //If the spider text is found in the current user agent, then return true if (stripos($agent, $bot) !== false){ return "$bot ($agent)"; return "match: $bot in agent: ($agent)"; } } //If it gets this far then no bot was found! return ""; } } function safefilename($string){ // convert entities eg Á => Á $string = htmlentities($string, ENT_QUOTES, 'UTF-8'); // replace the entities with letter equivalents $string = preg_replace('~&([az]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', '$1', $string); // return entities which did not have letter equivalents back to entities $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8'); // replace non valid chars with dash and multiple dashes with only one $string = preg_replace(array('~[^0-9a-z]~i', '~[ -]+~'), '-', $string); return trim($string, ' -'); } function getDirArray($path = "./", $filter = ".*", $exclude = '', $sorted = true, $optfilter2 = '') { // for server directories, can't use the static url $path = str_replace(STATIC_SITE_ROOT, $_SERVER['DOCUMENT_ROOT'], $path); if (file_exists($path) == false) { if (mkdir($path, 0777, true) == false) { die($path); exit; } } $handle = opendir($path); $dir = array(); while ($file = readdir($handle)) { if (is_file("$path/$file") && preg_match("/$filter/", $file) && (strlen($exclude) == 0 ? TRUE : !preg_match("/$exclude/", $file))) { if ($optfilter2 == '') { // No 2n filter $dir[] = $file; } else { $pos = strpos($file, $optfilter2); if ($pos === false) { // Not found } else { $dir[] = $file; } } } } closedir($handle); if ($sorted == true) { sort($dir); } return $dir; }