Identifikojmë bot të mundshëm "të këqij" dhe i bllokojmë ata sipas IP-së

Identifikojmë bot të mundshëm "të këqij" dhe i bllokojmë ata sipas IP-së

Përshëndetje! Në këtë artikull do të tregoj si përdoruesit e hostimit të zakonshëm mund të kapin adresat IP që gjenerojnë ngarkesë të tepërt në faqe dhe më pas t'i bllokojnë ato me mjete hostimi, do të ketë 'pak' kod php, disa captura ekranesh.

Të dhënat fillestare:

  1. Faqja e internetit e krijuar në CMS WordPress
  2. Hosting Beget (kjo nuk është reklamë, por captura e admin panelit do të jenë nga ky ofrues hostimi)
  3. Faqja WordPress është aktivizuar diku në fillim të viteve 2000 dhe ka një numër të madh artikujsh dhe materialesh
  4. Versioni PHP 7.2
  5. WP ka versionin më të fundit
  6. Së fundmi, faqja ka filluar të gjenerojë ngarkesë të lartë në MySQL sipas të dhënave të hostimit. Çdo ditë ky vlerë tejkalonte 120% të normës për llogarinë
  7. Sipas Yandex.Metrika, faqja vizitohet nga 100-200 njerëz në ditë

Në radhë të parë u bë:

  1. U pastruan tabelat e DB nga mbeturinat e akumuluara
  2. U çaktivizuan pluginët e panevojshëm, u hoqën pjesët e kodit të vjetruar

Këtu po theksoj, u provuan variante të keqkekut (pluginët e keqkekut), u bënë vëzhgime - por ngarkesa prej 120% nga një faqe mbeti e pandryshuar dhe mund të rritej vetëm.

Si dukej ngarkesa e përafërt e bazave të të dhënave të hostimit

Identifikojmë bot të mundshëm "të këqij" dhe i bllokojmë ata sipas IP-së
Në krye ndodhet faqja në fjalë, pak më poshtë janë faqet e tjera që kanë të njëjtin CMS dhe një vizitë të ngjashme, por krijojnë më pak ngarkesë.

Analiza

  • U bënë shumë përpjekje me variante të keqkekut të të dhënave, u bënë vëzhgime për disa javë (fatmirësisht hostimi nuk më ka shkruar asnjëherë që jam kaq i keq dhe do të më çaktivizojnë)
  • U analizua dhe kërkua për kërkesat e ngadalta, më pas u modifikua pak struktura e DB dhe lloji i tabelave
  • Për analizë, në radhë të parë u përdor AWStats i ndërtuar brenda (ai ndihmoi për të identifikuar adresën IP më të keqe sipas volumit të trafikut)
  • Metrika - metrika jep informacion vetëm për njerëzit, jo për robotët
  • U bënë përpjekje për të përdorur pluginë për WP, që dinë të filtrojnë dhe bllokojnë vizitorët edhe sipas vendndodhjes dhe kombinimeve të ndryshme
  • Një mënyrë krejt radikale për të mbyllur faqen për një ditë me shënimin 'Ne jemi në mirëmbajtje' u realizua gjithashtu me ndihmën e plugin-it të njohur. Në këtë rast, pritej që ngarkesa të kishte rënë, por jo në nivele zero, pasi ideologjia e WP bazohet në hooks dhe pluginët fillojnë aktivitetin e tyre kur ndodh ndonjë 'hook', ndërsa deri në atë moment mund të ketë ndodhur tashmë kërkesa për databazen.

Ideja

  1. Të llogarisim IP adresat që bëjnë shumë kërkesa në një periudhë të shkurtër kohore.
  2. Të regjistrojmë numrin e kërkesave për faqen.
  3. Bllokimi i qasjes në faqen në bazë të numrit të kërkesave.
  4. Bllokimi me anë të shënimit 'Deny from' në skedarin .htaccess.
  5. Opsione të tjera, si iptables dhe rregullat për Nginx, nuk do të shqyrtohen, pasi po shkruaj për hostim.

Pati një ide, prandaj duhet ta realizojmë, si pa këtë…

  • Krijojmë tabela për grumbullimin e të dhënave.
    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='Kandidatët për bllokim'
    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='Lista e bllokuar tashmë'
    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='Historia e të gjitha kërkesave për debug'
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT=1;
    
  • Të krijojmë një skedar në të cilin do të vendosim kodin. Kodi do të regjistrojë në tabelat e kandidatëve për bllokim dhe do të ruajë historinë për debug.

    Kodi i skedarit, për regjistrimin e IP adresave.

    <?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);
    
    

    Thelbi i kodit është që të marrim IP adresin e vizitorit dhe ta regjistrojmë në tabelë. Nëse IP-ja tashmë ekziston në tabelë, do të rritet fusha cnt (numri i kërkesave për faqen).

  • Tani vjen e frikshmja… Tani do të më djegin për veprimet e mia 🙂
    Që të regjistrojmë çdo hyrje në faqe, do të lidhemi me kodin e skedarit në skedarin kryesor të WordPress — wp-load.php. Po, pikërisht po e ndryshojmë skedarin e bërthamës dhe pikërisht pasi që ekziston tashmë variabla globale $wpdb.

Tani, tani ne mund të shohim se sa shpesh një IP i caktuar përmendet në tabelën tonë dhe me një filxhan kafeje e shohim atje çdo 5 minuta për të kuptuar situatën.

Identifikojmë bot të mundshëm "të këqij" dhe i bllokojmë ata sipas IP-së

Më pas është e thjeshtë, kopjojmë IP-në "e dëmshme", hapim skedarin .htaccess dhe e shtojmë në fund të skedarit.

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

Kjo, tani 94.242.55.248 nuk ka qasje në sit dhe nuk gjeneron ngarkesë në DB.

Por kopjimi manual çdo herë nuk është një aktivitet shumë i drejtë, dhe për më tepër kodi është menduar si autonom.

Do të shtojmë një skedar që do të ekzekutohet çdo 30 minuta përmes CRON:

Kodi i skedarit që modifikon .htaccess

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

$new_blocked = [];

$exclude_ip = [
    '87.236.16.70' //adresa e hostimit
];

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;
}

//Pastrimi i tabelës
$wpdb->query("DELETE FROM wp_visiters_bot");

//$file = '.htaccess';

$start_searche_tag = 'start_auto_deny_list';

$end_searche_tag = 'end_auto_deny_list';

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

    $replace_string = ''; //Test për të përfshirë në skedarin .htaccess

    $target_content = false; //Flagi i pjesës së nevojshme të kodit

    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 "Gabim: fgets() papritur dështoi\n";
    }
    fclose($handle);
}

//Skedari aktual .htaccess
$content = file_get_contents($file);

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

//Kclear të gjitha bllokimet në skedarin .htaccess
file_put_contents($file, $content);

//Regjistrimi i bllokimeve të reja
$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)));

Kodi i skedarit është mjaft i thjeshtë dhe primitiv, dhe ideja kryesore është të merret kandidati për bllokim dhe të shkruhen rregullat e bllokimit në skedarin .htaccess midis komenteve.
# start_auto_deny_list и # end_auto_deny_list

Tani IP-të "e dëmshme" bllokohen automatikisht, dhe skedari .htaccess duket përafërsisht kështu:

# 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

Pas vendit, pasi një kod i till fillon të funksionojë, mund të shihni rezultatet në panelin e hostimit:

Identifikojmë bot të mundshëm "të këqij" dhe i bllokojmë ata sipas IP-së

PS: Materiali është autorësor, megjithëse një pjesë e tij e kam publikuar në faqen time, por në Habre doli një version më të zgjeruar.

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster