"Gaiztoak" potentzialak kalkulatzen ditugu eta IP bidez blokeatzen ditugu

"Gaiztoak" potentzialak kalkulatzen ditugu eta IP bidez blokeatzen ditugu

Egun ona! Artikuluan kontatuko dizuet nola ohiko hostingaren erabiltzaileek gunean gehiegizko karga sortzen duten IP helbideak harrapatzen dituzten eta ondoren ostalaritza tresnak erabiliz blokeatu ditzaketen, php kodea "pixka bat" egongo da, pantaila-argazki batzuk.

Sarrerako datuak:

  1. CMS WordPress-en sortutako webgunea
  2. Hosting Beget (hau ez da iragarki bat, baina administrazio-paneleko pantaila-argazkiak ostalaritza-hornitzaile jakin honenak izango dira)
  3. WordPress gunea 2000. urtearen hasieran abiarazi zen nonbait eta artikulu eta material ugari ditu
  4. PHP bertsioa 7.2
  5. WP-k azken bertsioa du
  6. Aspalditik, gunea MySQL-n karga handia sortzen hasi zen hosting datuen arabera. Egunero balio horrek arauaren % 120 gainditzen zuen kontu bakoitzeko
  7. Yandex-en arabera. Metrica gunea egunean 100-200 pertsonak bisitatzen dute

Lehenik eta behin, hau egin zen:

  1. Datu-baseen taulak metatutako zaborrez garbitu ziren
  2. Behar ez ziren pluginak desgaitu ziren, zaharkitutako kodearen atalak kendu ziren

Aldi berean, zure arreta erakarri nahi nuke caching aukerak (caching pluginak) probatu zirela, behaketak egin zirela, baina gune bateko % 120ko karga ez zen aldatu eta hazi besterik ezin zen egin.

Nolakoa zen ostalaritza datu-baseen gutxi gorabeherako karga

"Gaiztoak" potentzialak kalkulatzen ditugu eta IP bidez blokeatzen ditugu
Goialdean dago aipatutako gunea, behean cms berdinak eta gutxi gorabehera trafiko berdina duten beste gune batzuk daude, baina karga gutxiago sortzen dutenak.

Analisia

  • Saiakera asko egin ziren datuen cache-aukerekin, behaketak hainbat astetan egin ziren (zorionez, denbora horretan ostalaritzak ez zidan inoiz idatzi hain gaizki nengoela eta deskonektatuko nintzela)
  • Kontsulta geldoen azterketa eta bilaketa egin zen, gero datu-basearen egitura eta taula mota apur bat aldatu ziren
  • Analisirako, batez ere AWStats integratua erabili dugu (bide batez, trafiko-bolumenaren arabera IP helbide txarrena kalkulatzen lagundu du.
  • Metrika - metrikak pertsonei buruzko informazioa ematen du soilik, ez botei buruzkoa
  • WPrako pluginak erabiltzen saiatu dira bisitariak iragazi eta blokeatu ditzaketen kokapenaren herrialdearen eta hainbat konbinazioren arabera ere.
  • Erabat erradikala izan zen gunea egun batez ixtea "Mantentze lanetan gaude" oharrarekin - hau ere plugin ospetsua erabiliz egin zen. Kasu honetan, karga jaitsiko dela espero dugu, baina ez zero balioetara, WP ideologia amuetan oinarritzen baita eta plugin-ak "kako" bat gertatzen denean hasten dute beren jarduera, eta "kakoa" gertatu baino lehen, datu-baserako eskaerak egin daitezke. dagoeneko eginak izan

Idea

  1. Kalkulatu denbora tarte laburrean eskaera asko egiten dituzten IP helbideak.
  2. Erregistratu webguneko aipamen kopurua
  3. Blokeatu gunerako sarbidea hit-kopuruaren arabera
  4. Blokeatu .htaccess fitxategiko "Deny from" sarrera erabiliz
  5. Ez nuen beste aukerarik kontuan hartu, iptables eta Nginx-erako arauak esaterako, ostalaritzari buruz idazten ari naizelako

Ideia bat agertu da, beraz, gauzatu egin behar da, hau gabe bezala...

  • Datuak pilatzeko taulak sortzea
    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;
    
  • Sortu dezagun fitxategi bat bertan kokatuko dugun kodea. Kodea blokeatzeko hautagaien tauletan grabatuko da eta arazketarako historia gordeko du.

    IP helbideak grabatzeko fitxategi-kodea

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

    Kodearen funtsa bisitariaren IP helbidea lortu eta taula batean idaztea da. IP-a taulan badago jada, cnt eremua handituko da (gunerako eskaera kopurua)

  • Orain beldurgarria... Orain erreko naute nire ekintzengatik :)
    Eskaera bakoitza gunera grabatzeko, fitxategi-kodea WordPress fitxategi nagusiarekin konektatzen dugu - wp-load.php. Bai, nukleoaren fitxategia aldatzen dugu eta, hain zuzen, $wpdb aldagai globala jada existitzen den ondoren

Beraz, orain ikus dezakegu zenbateko maiztasun hau edo beste IP helbide markatzen den gure taulan eta kafe-katilu batekin 5 minutuz behin begiratzen dugu argazkia ulertzeko

"Gaiztoak" potentzialak kalkulatzen ditugu eta IP bidez blokeatzen ditugu

Ondoren, kopiatu IP "kaltegarria", ireki .htaccess fitxategia eta gehitu fitxategiaren amaieran

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

Hori da, orain 94.242.55.248 - ez du gunerako sarbiderik eta ez du datu-basean kargarik sortzen

Baina horrela eskuz kopiatzea ez da oso lan zuzena, eta gainera, kodea autonomoa izan nahi zuen.

Gehitu dezagun 30 minuturo CRON bidez exekutatuko den fitxategi bat:

Fitxategi-kodea .htaccess aldatzen

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

Fitxategiaren kodea nahiko sinplea eta primitiboa da eta bere ideia nagusia da blokeatzeko hautagaiak hartzea eta iruzkinen artean .htaccess fitxategian blokeatzeko arauak sartzea.
# start_auto_deny_list eta # end_auto_deny_list

Orain IP "kaltegarriak" beraiek blokeatzen dira, eta .htaccess fitxategiak honelako itxura du:

# 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

Ondorioz, kode hau funtzionatzen hasi ondoren, emaitza ostalaritza panelean ikus dezakezu:

"Gaiztoak" potentzialak kalkulatzen ditugu eta IP bidez blokeatzen ditugu

PS: Materiala egilearena da, zati bat nire webgunean argitaratu badut ere, Habre-n bertsio zabalagoa lortu dut.

Iturria: www.habr.com

Gehitu iruzkin berria