Бид боломжит "муу" роботуудыг тодорхойлж, тэдгээрийг IP-ээр хаадаг

Бид боломжит "муу" роботуудыг тодорхойлж, тэдгээрийг IP-ээр хаадаг

Сайхан өдөр! Нийтлэлд би ердийн хостинг хэрэглэгчид сайт дээр хэт их ачаалал үүсгэдэг IP хаягийг хэрхэн барьж, дараа нь хостинг хэрэгслээр хаах боломжтойг танд хэлэх болно, тэнд "бага зэрэг" php код, цөөн хэдэн дэлгэцийн агшин байх болно.

Мэдээлэл оруулах:

  1. CMS WordPress дээр вэбсайт үүсгэсэн
  2. Хостинг Бегет (энэ нь сурталчилгаа биш, гэхдээ админ самбарын дэлгэцийн агшинг тухайн хостинг үйлчилгээ үзүүлэгчээс авах болно)
  3. WordPress сайт нь 2000 оны эхээр хаа нэгтээ нээгдсэн бөгөөд олон тооны нийтлэл, материалтай
  4. PHP хувилбар 7.2
  5. WP нь хамгийн сүүлийн хувилбартай
  6. Хэсэг хугацааны турш сайт нь байршуулах мэдээллийн дагуу MySQL дээр өндөр ачаалал үүсгэж эхэлсэн. Өдөр бүр энэ үнэ цэнэ нь дансны нормоос 120% -иас давсан
  7. Yandex-ийн дагуу. Метрика сайтыг өдөрт 100-200 хүн зочилдог

Юуны өмнө үүнийг хийсэн:

  1. Мэдээллийн сангийн хүснэгтүүдийг хуримтлагдсан хог хаягдлаас цэвэрлэв
  2. Шаардлагагүй залгаасуудыг идэвхгүй болгож, хуучирсан кодын хэсгүүдийг устгасан

Үүний зэрэгцээ, кэш хийх сонголтуудыг (кэшлэх залгаасууд) туршиж үзсэн, ажиглалт хийсэн боловч нэг сайтаас 120% -ийн ачаалал өөрчлөгдөөгүй бөгөөд зөвхөн өсөх боломжтой байсанд анхаарлаа хандуулахыг хүсч байна.

Хостинг мэдээллийн сангийн ойролцоогоор ачаалал ямар байсан бэ

Бид боломжит "муу" роботуудыг тодорхойлж, тэдгээрийг IP-ээр хаадаг
Дээд талд нь тухайн сайт байгаа бол яг доор нь ижил см-тэй, ойролцоогоор ижил урсгалтай боловч ачаалал багатай бусад сайтууд байна.

Анализ

  • Өгөгдлийн кэш хийх сонголтуудыг олон оролдлого хийж, хэдэн долоо хоногийн турш ажиглалт хийсэн (Аз болоход, энэ хугацаанд хостинг надад хэзээ ч намайг маш муу, салгагдах болно гэж бичээгүй)
  • Удаан асуулгад дүн шинжилгээ хийж, хайлт хийсэн бөгөөд дараа нь мэдээллийн сангийн бүтэц, хүснэгтийн төрөл бага зэрэг өөрчлөгдсөн
  • Шинжилгээний хувьд бид үндсэндээ суурилуулсан AWStats-ийг ашигласан (дашрамд хэлэхэд энэ нь замын хөдөлгөөний хэмжээнээс хамааран хамгийн муу IP хаягийг тооцоолоход тусалсан.
  • Метрик - хэмжигдэхүүн нь роботуудын тухай биш зөвхөн хүмүүсийн тухай мэдээллийг өгдөг
  • WP-д зориулсан залгаасуудыг ашиглах оролдлого гарч ирсэн бөгөөд зочдыг тухайн улс орон болон янз бүрийн хослолоор шүүж, хааж болно.
  • Бүрэн радикал арга бол "Бид засвар үйлчилгээ хийж байна" гэсэн тэмдэглэл бүхий сайтыг нэг өдрийн турш хаах явдал байв - үүнийг алдартай залгаасыг ашиглан хийсэн. Энэ тохиолдолд WP-ийн үзэл баримтлал нь дэгээ болон залгаасууд дээр суурилдаг тул "дэгээ" үүсэхээс өмнө үйл ажиллагаагаа эхлүүлдэг тул "дэгээ" үүсэхээс өмнө өгөгдлийн санд хүсэлт гаргах боломжтой байдаг тул бид ачаалал буурах болно гэж найдаж байна. аль хэдийн хийгдсэн

Санаа

  1. Богино хугацаанд маш их хүсэлт гаргадаг IP хаягуудыг тооцоол.
  2. Сайт руу хандсан тоог тэмдэглэ
  3. Үзсэн тоогоор сайт руу нэвтрэхийг хориглоно
  4. .htaccess файл дахь "Deny from" оруулгыг ашиглан блокло
  5. Iptables, Nginx-ийн дүрэм гэх мэт бусад сонголтыг авч үзээгүй, учир нь би байршуулах талаар бичиж байна

Нэг санаа гарч ирсэн тул үүнийг хэрэгжүүлэх шаардлагатай байна, үүнгүйгээр ...

  • Өгөгдөл хуримтлуулах хүснэгт үүсгэх
    CREATE TABLE `wp_visiters_bot` (
    	`id` INT(11) NOT NULL AUTO_INCREMENT,
    	`ip` VARCHAR(300) NULL DEFAULT NULL,
    	`browser` VARCHAR(500) NULL DEFAULT NULL,
    	`cnt` INT(11) NULL DEFAULT NULL,
    	`request` TEXT NULL,
    	`input` TEXT NULL,
    	`data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    	PRIMARY KEY (`id`),
    	UNIQUE INDEX `ip` (`ip`)
    )
    COMMENT='Кандидаты для блокировки'
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT=1;
    

    CREATE TABLE `wp_visiters_bot_blocked` (
    	`id` INT(11) NOT NULL AUTO_INCREMENT,
    	`ip` VARCHAR(300) NOT NULL,
    	`data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    	PRIMARY KEY (`id`),
    	UNIQUE INDEX `ip` (`ip`)
    )
    COMMENT='Список уже заблокированных'
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT=59;
    

    CREATE TABLE `wp_visiters_bot_history` (
    	`id` INT(11) NOT NULL AUTO_INCREMENT,
    	`ip` VARCHAR(300) NULL DEFAULT NULL,
    	`browser` VARCHAR(500) NULL DEFAULT NULL,
    	`cnt` INT(11) NULL DEFAULT NULL,
    	`data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    	`data_add` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
    	PRIMARY KEY (`id`),
    	UNIQUE INDEX `ip` (`ip`)
    )
    COMMENT='История всех запросов для дебага'
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT=1;
    
  • Кодоо байрлуулах файл үүсгэцгээе. Код нь блоклох нэр дэвшигчдийн хүснэгтэд бичиж, дибаг хийх түүхийг хадгална.

    IP хаягийг бүртгэх файлын код

    <?php
    
    if (!defined('ABSPATH')) {
        return;
    }
    
    global $wpdb;
    
    /**
     * Вернёт конкретный IP адрес посетителя
     * @return boolean
     */
    function coderun_get_user_ip() {
    
        $client_ip = '';
    
        $address_headers = array(
            'HTTP_CLIENT_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED',
            'HTTP_X_CLUSTER_CLIENT_IP',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'REMOTE_ADDR',
        );
    
        foreach ($address_headers as $header) {
            if (array_key_exists($header, $_SERVER)) {
    
                $address_chain = explode(',', $_SERVER[$header]);
                $client_ip = trim($address_chain[0]);
    
                break;
            }
        }
    
        if (!$client_ip) {
            return '';
        }
    
    
        if ('0.0.0.0' === $client_ip || '::' === $client_ip || $client_ip == 'unknown') {
            return '';
        }
    
        return $client_ip;
    }
    
    $ip = esc_sql(coderun_get_user_ip()); // IP адрес посетителя
    
    if (empty($ip)) {// Нет IP, ну и идите лесом...
        header('Content-type: application/json;');
        die('Big big bolt....');
    }
    
    $browser = esc_sql($_SERVER['HTTP_USER_AGENT']); //Данные для анализа браузера
    
    $request = esc_sql(wp_json_encode($_REQUEST)); //Последний запрос который был к сайту
    
    $input = esc_sql(file_get_contents('php://input')); //Тело запроса, если было
    
    $cnt = 1;
    
    //Запрос в основную таблицу с временными кондидатами на блокировку
    $query = <<<EOT
        INSERT INTO wp_visiters_bot (`ip`,`browser`,`cnt`,`request`,`input`)
            VALUES  ('{$ip}','{$browser}','{$cnt}','{$request}','$input')
             ON DUPLICATE KEY UPDATE cnt=cnt+1,request=VALUES(request),input=VALUES(input),browser=VALUES(browser)
    EOT;
    
    //Запрос для истории
    $query2 = <<<EOT
        INSERT INTO wp_visiters_bot_history (`ip`,`browser`,`cnt`)
            VALUES  ('{$ip}','{$browser}','{$cnt}')
             ON DUPLICATE KEY UPDATE cnt=cnt+1,browser=VALUES(browser)
    EOT;
    
    
    $wpdb->query($query);
    
    $wpdb->query($query2);
    
    

    Кодын мөн чанар нь зочны IP хаягийг авч, хүснэгтэд бичих явдал юм. Хэрэв ip нь хүснэгтэд байгаа бол cnt талбар нэмэгдэх болно (сайт руу илгээсэн хүсэлтийн тоо)

  • Одоо аймаар нь... Одоо миний үйлдлээс болж намайг шатаах болно :)
    Сайт руу илгээсэн хүсэлт бүрийг бүртгэхийн тулд бид файлын кодыг WordPress үндсэн файлтай холбоно - wp-load.php. Тийм ээ, бид цөмийн файлыг өөрчилдөг ба $wpdb глобал хувьсагч аль хэдийн байгаа болсны дараа

Тиймээс одоо бид хүснэгтэд энэ эсвэл тэр IP хаягийг хэр олон удаа тэмдэглэж байгааг харж, 5 минут тутамд нэг аяга кофе ууж, зургийг ойлгохын тулд тийшээ хардаг.

Бид боломжит "муу" роботуудыг тодорхойлж, тэдгээрийг IP-ээр хаадаг

Дараа нь зүгээр л "хортой" IP-г хуулж, .htaccess файлыг нээж, файлын төгсгөлд нэмнэ үү.

Order allow,deny
Allow from all
# start_auto_deny_list
Deny from 94.242.55.248
# end_auto_deny_list

Энэ бол одоо 94.242.55.248 - сайт руу нэвтрэх эрхгүй бөгөөд мэдээллийн санд ачаалал үүсгэдэггүй.

Гэхдээ ийм байдлаар гараар хуулах нь тийм ч зөв ажил биш бөгөөд үүнээс гадна код нь бие даасан байх зорилготой байсан.

30 минут тутамд CRON-ээр хэрэгжих файлыг нэмье:

htaccess-ийг өөрчлөх файлын код

<?php

/**
 * Файл автоматического задания блокировок по IP адресу
 * Должен запрашиваться через CRON
 */
if (empty($_REQUEST['key'])) {
    die('Hello');
}

require('wp-load.php');

global $wpdb;

$limit_cnt = 70; //Лимит запросов по которым отбирать

$deny_table = $wpdb->get_results("SELECT * FROM wp_visiters_bot WHERE cnt>{$limit_cnt}");

$new_blocked = [];

$exclude_ip = [
    '87.236.16.70'//адрес хостинга
];

foreach ($deny_table as $result) {

    if (in_array($result->ip, $exclude_ip)) {
        continue;
    }

    $wpdb->insert('wp_visiters_bot_blocked', ['ip' => $result->ip], ['%s']);
}

$deny_table_blocked = $wpdb->get_results("SELECT * FROM wp_visiters_bot_blocked");

foreach ($deny_table_blocked as $blocked) {
    $new_blocked[] = $blocked->ip;
}

//Очистка таблицы
$wpdb->query("DELETE FROM wp_visiters_bot");

//echo '<pre>';print_r($new_blocked);echo '</pre>';

$file = '.htaccess';

$start_searche_tag = 'start_auto_deny_list';

$end_searche_tag = 'end_auto_deny_list';

$handle = @fopen($file, "r");
if ($handle) {

    $replace_string = '';//Тест для вставки в файл .htaccess

    $target_content = false; //Флаг нужного нам участка кода

    while (($buffer = fgets($handle, 4096)) !== false) {

        if (stripos($buffer, 'start_auto_deny_list') !== false) {
            $target_content = true;
            continue;
        }

        if (stripos($buffer, 'end_auto_deny_list') !== false) {
            $target_content = false;

            continue;
        }

        if ($target_content) {
            $replace_string .= $buffer;
        }
    }
    if (!feof($handle)) {
        echo "Ошибка: fgets() неожиданно потерпел неудачуn";
    }
    fclose($handle);
}

//Текущий файл .htaccess
$content = file_get_contents($file);

$content = str_replace($replace_string, '', $content);

//Очищаем все блокировки в файле .htaccess
file_put_contents($file, $content);

//Запись новых блокировок
$str = "# {$start_searche_tag}" . PHP_EOL;

foreach ($new_blocked as $key => $value) {
    $str .= "Deny from {$value}" . PHP_EOL;
}

file_put_contents($file, str_replace("# {$start_searche_tag}", $str, file_get_contents($file)));

Файлын код нь маш энгийн бөгөөд энгийн бөгөөд гол санаа нь блоклох нэр дэвшигчдийг авч, тайлбаруудын хооронд .htaccess файлд блоклох дүрмийг оруулах явдал юм.
# автоматаар_татгалзах_жагсаалтыг эхлүүлэх ба # автоматаар_татгалзах_жагсаалтыг дуусгах

Одоо "хортой" IP-г өөрөө хаасан бөгөөд .htaccess файл нь иймэрхүү харагдаж байна:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Order allow,deny
Allow from all

# start_auto_deny_list
Deny from 94.242.55.248
Deny from 207.46.13.122
Deny from 66.249.64.164
Deny from 54.209.162.70
Deny from 40.77.167.86
Deny from 54.146.43.69
Deny from 207.46.13.168
....... ниже другие адреса
# end_auto_deny_list

Үүний үр дүнд, энэ код ажиллаж эхэлсний дараа та үр дүнг байршуулах самбараас харж болно.

Бид боломжит "муу" роботуудыг тодорхойлж, тэдгээрийг IP-ээр хаадаг

Жич: Энэ материал нь зохиогчийнх, гэхдээ би түүний зарим хэсгийг вэбсайт дээрээ нийтэлсэн боловч Habre дээр илүү өргөтгөсөн хувилбарыг авсан.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх