අපි විභව "නපුරු" බොට් හඳුනාගෙන ඒවා IP මගින් අවහිර කරන්නෙමු

අපි විභව "නපුරු" බොට් හඳුනාගෙන ඒවා IP මගින් අවහිර කරන්නෙමු

සුබ දිනක්! සාමාන්‍ය සත්කාරක පරිශීලකයින්ට වෙබ් අඩවියේ අධික බරක් ජනනය කරන IP ලිපින අල්ලාගෙන සත්කාරක මෙවලම් භාවිතයෙන් ඒවා අවහිර කරන්නේ කෙසේදැයි ලිපියෙන් මම ඔබට කියමි, php කේතයේ “ටිකක්”, තිරපිටපත් කිහිපයක් ඇත.

ආදාන දත්ත:

  1. CMS WordPress මත නිර්මාණය කරන ලද වෙබ් අඩවිය
  2. Hosting Beget (මෙය වෙළඳ දැන්වීමක් නොවේ, නමුත් පරිපාලක මණ්ඩලයේ තිරපිටපත් මෙම විශේෂිත සත්කාරක සපයන්නාගෙන් වේ)
  3. වර්ඩ්ප්‍රෙස් වෙබ් අඩවිය 2000 මුල් භාගයේ කොතැනක හෝ දියත් කරන ලද අතර ලිපි සහ ද්‍රව්‍ය විශාල ප්‍රමාණයක් ඇත.
  4. PHP අනුවාදය 7.2
  5. WP හි නවතම අනුවාදය ඇත
  6. දැන් කාලයක් තිස්සේ, වෙබ් අඩවිය සත්කාරක දත්ත වලට අනුව MySQL මත ඉහළ බරක් ජනනය කිරීමට පටන් ගත්තේය. සෑම දිනකම මෙම අගය ගිණුමකට සම්මතයෙන් 120% ඉක්මවා ඇත
  7. Yandex අනුව. Metrica අඩවියට දිනකට පුද්ගලයින් 100-200ක් පැමිණේ

පළමුවෙන්ම, මෙය සිදු කරන ලද්දේ:

  1. දත්ත සමුදා වගු එකතු වූ කසළ ඉවත් කරන ලදී
  2. අනවශ්‍ය ප්ලගීන අක්‍රිය කර ඇත, යල් පැන ගිය කේතයේ කොටස් ඉවත් කරන ලදී

ඒ අතරම, හැඹිලි විකල්ප (හැඹිලි ප්ලගීන) උත්සාහ කර ඇති බව, නිරීක්ෂණ සිදු කරන ලද බව මම ඔබේ අවධානයට යොමු කිරීමට කැමැත්තෙමි - නමුත් එක් වෙබ් අඩවියකින් 120% ක බරක් නොවෙනස්ව පැවති අතර එය වර්ධනය විය හැකිය.

සත්කාරක දත්ත සමුදායන් මත දළ වශයෙන් පැටවීම කෙබඳු විය

අපි විභව "නපුරු" බොට් හඳුනාගෙන ඒවා IP මගින් අවහිර කරන්නෙමු
ඉහළින්ම ඇත්තේ අදාළ වෙබ් අඩවියයි, පහළින් ඇත්තේ එකම සෙ.මී. සහ ආසන්න වශයෙන් එකම ගමනාගමනය ඇති නමුත් අඩු බරක් ඇති වෙනත් අඩවි ය.

විශ්ලේෂණය

  • දත්ත හැඹිලි විකල්ප සමඟ බොහෝ උත්සාහයන් සිදු කරන ලදී, නිරීක්ෂණ සති කිහිපයක් පුරා සිදු කරන ලදී (වාසනාවකට මෙන්, මෙම කාලය තුළ සත්කාරක සමාගම මා එතරම් නරක බවත් විසන්ධි වන බවත් මට ලියා නැත)
  • මන්දගාමී විමසුම් සඳහා විශ්ලේෂණයක් සහ සෙවීමක් සිදු විය, පසුව දත්ත සමුදා ව්‍යුහය සහ වගු වර්ගය තරමක් වෙනස් විය
  • විශ්ලේෂණය සඳහා, අපි මූලික වශයෙන් භාවිතා කළේ ගොඩනඟන ලද AWStats (මාර්ගය වන විට, රථවාහන පරිමාව මත පදනම්ව නරකම IP ලිපිනය ගණනය කිරීමට එය උපකාරී විය.
  • මෙට්‍රික් - මෙට්‍රික් තොරතුරු සපයන්නේ මිනිසුන් ගැන පමණි, බොට් ගැන නොවේ
  • WP සඳහා ප්ලගීන භාවිතා කිරීමට උත්සාහ කර ඇති අතර එමඟින් අමුත්තන් සිටින රට සහ විවිධ සංයෝජනයන් අනුව පවා අමුත්තන් පෙරීමට සහ අවහිර කිරීමට හැකිය.
  • සම්පූර්ණයෙන්ම රැඩිකල් ක්‍රමයක් වූයේ “අපි නඩත්තු කරමින් සිටිමු” යන සටහන සමඟ වෙබ් අඩවිය දිනකට වසා දැමීමයි - මෙය ද ප්‍රසිද්ධ ප්ලගිනය භාවිතයෙන් සිදු කරන ලදී. මෙම අවස්ථාවෙහිදී, WP දෘෂ්ටිවාදය පදනම් වන්නේ කොකු සහ ප්ලගීන "කොක්කක්" සිදු වූ විට ඔවුන්ගේ ක්‍රියාකාරකම් ආරම්භ කරන බැවින්, "කොක්ක" සිදුවීමට පෙර, දත්ත සමුදාය වෙත ඉල්ලීම් කළ හැකි බැවින්, බර අඩු වනු ඇතැයි අපි බලාපොරොත්තු වෙමු, නමුත් අගයන් ශුන්‍යයට නොවේ. දැනටමත් සාදා ඇත

අදහස

  1. කෙටි කාලයක් තුළ ඉල්ලීම් ගොඩක් කරන IP ලිපින ගණනය කරන්න.
  2. අඩවියට පහරවල් ගණන වාර්තා කරන්න
  3. පහර ගණන මත පදනම්ව වෙබ් අඩවියට පිවිසීම අවහිර කරන්න
  4. .htaccess ගොනුව තුළ "Deny from" ඇතුළත් කිරීම භාවිතා කිරීම අවහිර කරන්න
  5. මම Nginx සඳහා iptables සහ නීති වැනි වෙනත් විකල්ප සලකා බැලුවේ නැත, මන්ද මම සත්කාරකත්වය ගැන ලියන බැවිනි.

අදහසක් දර්ශනය වී ඇත, එබැවින් එය ක්‍රියාත්මක කළ යුතුය, මෙය නොමැතිව ...

  • දත්ත රැස් කිරීම සඳහා වගු නිර්මාණය කිරීම
    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 ගොනුව තුළ අවහිර කිරීමේ නීති ඇතුළත් කිරීමයි.
#ආරම්භක_ස්වයං_ප්‍රතික්ෂේප_ලැයිස්තුව සහ # අවසන්_ස්වයං_ප්‍රතික්ෂේප_ලැයිස්තුව

දැන් "හානිකර" IPs තමන් විසින්ම අවහිර කර ඇති අතර, .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 මගින් අවහිර කරන්නෙමු

PS: ද්රව්යය කර්තෘගේ ය, මම එහි කොටසක් මගේ වෙබ් අඩවියේ පළ කළද, මට Habre හි වඩාත් පුළුල් කළ අනුවාදයක් ලැබුණි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න