Tunatambua roboti zinazowezekana "mbaya" na kuzizuia kwa IP

Tunatambua roboti zinazowezekana "mbaya" na kuzizuia kwa IP

Siku njema! Katika makala nitakuambia jinsi watumiaji wa mwenyeji wa kawaida wanaweza kupata anwani za IP zinazozalisha mzigo mkubwa kwenye tovuti na kisha kuzizuia kwa kutumia zana za kukaribisha, kutakuwa na "kidogo" cha msimbo wa php, viwambo vichache.

Data ya ingizo:

  1. Tovuti iliyoundwa kwenye CMS WordPress
  2. Kukaribisha Beget (hii si tangazo, lakini skrini za msimamizi zitatoka kwa mtoa huduma huyu mwenyeji)
  3. WordPress Tovuti ilizinduliwa mahali fulani mwanzoni mwa miaka ya 2000 na ina idadi kubwa ya makala na vifaa
  4. Toleo la PHP 7.2
  5. WP ina toleo jipya zaidi
  6. Kwa muda sasa, tovuti ilianza kutoa mzigo mkubwa kwenye MySQL kulingana na data ya mwenyeji. Kila siku thamani hii ilizidi 120% ya kawaida kwa akaunti
  7. Kulingana na Yandex. Tovuti ya Metrica inatembelewa na watu 100-200 kwa siku

Kwanza kabisa, hii ilifanyika:

  1. Majedwali ya hifadhidata yaliondolewa takataka zilizokusanywa
  2. Programu-jalizi zisizohitajika zilizimwa, sehemu za msimbo uliopitwa na wakati ziliondolewa

Wakati huo huo, ningependa kuteka mawazo yako kwa ukweli kwamba chaguzi za caching (caching plugins) zilijaribiwa, uchunguzi ulifanywa - lakini mzigo wa 120% kutoka kwa tovuti moja haukubadilishwa na inaweza kukua tu.

Jinsi mzigo wa takriban kwenye hifadhidata za upangishaji ulionekana

Tunatambua roboti zinazowezekana "mbaya" na kuzizuia kwa IP
Juu ni tovuti inayozungumziwa, chini kidogo kuna tovuti zingine ambazo zina sentimita sawa na takriban trafiki sawa, lakini huunda mzigo mdogo.

Uchambuzi

  • Majaribio mengi yalifanywa na chaguzi za uhifadhi wa data, uchunguzi ulifanyika kwa wiki kadhaa (kwa bahati nzuri, wakati huu mwenyeji hakuwahi kuniandikia kuwa nilikuwa mbaya sana na ningetenganishwa)
  • Kulikuwa na uchanganuzi na utafutaji wa maswali ya polepole, kisha muundo wa hifadhidata na aina ya jedwali zilibadilishwa kidogo
  • Kwa uchanganuzi, tulitumia AWStats zilizojengwa ndani (kwa njia, ilisaidia kuhesabu anwani mbaya ya IP kulingana na kiwango cha trafiki.
  • Metric - kipimo hutoa taarifa kuhusu watu pekee, si kuhusu roboti
  • Kumekuwa na majaribio ya kutumia programu-jalizi za WP ambazo zinaweza kuchuja na kuzuia wageni hata kwa nchi ya eneo na mchanganyiko mbalimbali.
  • Njia kali kabisa iligeuka kuwa kufunga tovuti kwa siku na noti "Tuko chini ya matengenezo" - hii pia ilifanywa kwa kutumia programu-jalizi maarufu. Katika kesi hii, tunatarajia mzigo utashuka, lakini sio kwa maadili ya sifuri, kwani itikadi ya WP inategemea ndoano na programu-jalizi huanza shughuli zao wakati "ndoano" inatokea, na kabla ya "ndoano" kutokea, maombi kwa hifadhidata yanaweza. tayari kufanywa

Wazo

  1. Kukokotoa anwani za IP zinazotuma maombi mengi kwa muda mfupi.
  2. Rekodi idadi ya vibao kwenye tovuti
  3. Zuia ufikiaji wa tovuti kulingana na idadi ya vibao
  4. Zuia kwa kutumia ingizo la "Kataa kutoka" katika faili ya .htaccess
  5. Sikuzingatia chaguzi zingine, kama iptables na sheria za Nginx, kwa sababu ninaandika juu ya mwenyeji

Wazo limetokea, kwa hivyo linahitaji kutekelezwa, kwani bila hii ...

  • Kuunda majedwali ili kukusanya data
    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;
    
  • Wacha tuunda faili ambayo tutaweka nambari. Msimbo utarekodi katika majedwali ya mgombea anayezuia na kuweka historia ya utatuzi.

    Nambari ya faili ya kurekodi anwani za 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);
    
    

    Kiini cha msimbo ni kupata anwani ya IP ya mgeni na kuiandika kwenye jedwali. Ikiwa ip tayari iko kwenye jedwali, uwanja wa cnt utaongezwa (idadi ya maombi kwenye tovuti)

  • Sasa jambo la kutisha ... Sasa watanichoma kwa matendo yangu :)
    Ili kurekodi kila ombi kwenye tovuti, tunajumuisha msimbo wa faili kwenye faili kuu WordPress — wp-load.php. Ndiyo, tunabadilisha faili kuu, na haswa baada ya kigezo cha $wpdb cha kimataifa kuwa tayari kipo.

Kwa hivyo, sasa tunaweza kuona ni mara ngapi hii au anwani hiyo ya IP imewekwa alama kwenye meza yetu na kwa kikombe cha kahawa tunaangalia huko mara moja kila dakika 5 ili kuelewa picha.

Tunatambua roboti zinazowezekana "mbaya" na kuzizuia kwa IP

Kisha nakili kwa urahisi IP "ya hatari", fungua faili ya .htaccess na uiongeze hadi mwisho wa faili.

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

Hiyo ndiyo yote, sasa 94.242.55.248 - haina ufikiaji wa tovuti na haitoi mzigo kwenye hifadhidata.

Lakini kila wakati kunakili kwa mkono kama hii sio kazi ya haki sana, na zaidi ya hayo, kanuni hiyo ilikusudiwa kuwa ya uhuru.

Wacha tuongeze faili ambayo itatekelezwa kupitia CRON kila dakika 30:

Kurekebisha msimbo wa faili .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)));

Msimbo wa faili ni rahisi sana na wa zamani na wazo lake kuu ni kuchukua wagombea wa kuzuia na kuingiza sheria za kuzuia katika faili ya .htaccess kati ya maoni.
# anza_orodha_ya_kukanusha_otomatiki na # maliza_orodha_ya_kukanusha_otomatiki

Sasa IP "zinazodhuru" zimezuiwa zenyewe, na faili ya .htaccess inaonekana hivi:

# 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

Kama matokeo, baada ya nambari hii kuanza kufanya kazi, unaweza kuona matokeo kwenye paneli ya mwenyeji:

Tunatambua roboti zinazowezekana "mbaya" na kuzizuia kwa IP

PS: Nyenzo ni za mwandishi, ingawa nilichapisha sehemu yake kwenye wavuti yangu, nilipata toleo lililopanuliwa zaidi la Habre.

Chanzo: mapenzi.com

Nunua upangishaji wa kuaminika wa tovuti zilizo na ulinzi wa DDoS, seva za VPS VDS 🔥 Nunua upangishaji wa tovuti unaoaminika kwa ulinzi wa DDoS, seva za VPS VDS | ProHoster