Nous calculons les bots "maléfiques" potentiels et les bloquons par IP



Bonne journée Dans l'article, je vais vous dire comment il est possible pour les utilisateurs d'hébergement ordinaires d'attraper des adresses IP qui génèrent une charge excessive sur le site, puis de les bloquer à l'aide d'outils d'hébergement, il y aura "un peu" de code php, quelques captures d'écran.

Données d'entrée:

  1. Site créé sur CMS WordPress
  2. Hosting Beget (ce n'est pas une publicité, mais les captures d'écran du panneau d'administration seront de ce fournisseur d'hébergement)
  3. Le site WordPress a été lancé quelque part au début de 2000 et contient un grand nombre d'articles et de documents.
  4. PHP version 7.2
  5. WP a la dernière version
  6. Depuis quelque temps, le site a commencé à générer une charge élevée sur MySQL selon l'hébergement. Chaque jour, cette valeur dépassait 120% de la norme par compte
  7. Selon Yandex. Le site métrique est visité par 100-200 personnes par jour

Tout d'abord, cela a été fait:

  1. Les bases de données sont débarrassées des déchets accumulés
  2. Les plugins inutiles sont désactivés, des sections de code obsolète sont supprimées

En même temps, j'attire l'attention sur les options de mise en cache (plugins de mise en cache), nous avons fait des observations - mais la charge de 120% à partir d'un site était inchangée et ne pouvait qu'augmenter.

A quoi ressemblait la charge approximative sur les bases de données d'hébergement


En haut se trouve le site en question, juste en dessous d'autres sites qui ont les mêmes cms et environ le même trafic, mais créent moins de charge.

Analyse

  • De nombreuses tentatives ont été faites avec des options de mise en cache des données, des observations ont été faites pendant plusieurs semaines (l'avantage de l'hébergement pendant cette période, je n'ai jamais écrit que je suis si mauvais et que je vais me déconnecter)
  • Il y a eu une analyse et une recherche de requêtes lentes, puis la structure de la base de données et le type de table ont été légèrement modifiés
  • Pour l'analyse, l'AWStats intégré a été principalement utilisé (en passant, il a aidé à calculer l'adresse IP la plus mauvaise en fonction du volume de trafic
  • Métrique - la métrique donne des informations uniquement sur les personnes, pas sur les robots
  • Il y a eu des tentatives d'utilisation de plugins pour WP, qui peuvent filtrer et bloquer les visiteurs même par pays de localisation et par diverses combinaisons
  • Une manière complètement radicale s'est avérée être de fermer le site pendant une journée avec la mention «Nous sommes en maintenance» - cela a également été fait avec l'aide du célèbre plug-in. Dans ce cas, nous nous attendons à ce que la charge baisse, mais pas à des valeurs à gauche, car l'idéologie de WP est basée sur les hooks et les plugins commencent leur activité quand une sorte de «hook» se produit, et avant que le «hook» ne se produise, des requêtes vers la base de données peuvent déjà être faites

Idée

  1. Calculez les adresses IP qui font beaucoup de demandes en peu de temps.
  2. Fixez le nombre de visites sur le site
  3. En fonction du nombre de visites, bloquer l'accès au site
  4. Bloquer en utilisant l'entrée «Refuser de» dans le fichier .htaccess
  5. D'autres options, comme iptables et les règles pour Nginx sans considération, car j'écris sur l'hébergement

Une idée est venue, il faut donc la mettre en œuvre, car sans elle ...

  • Nous créons des tableaux pour l'accumulation de données

    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; 
  • Créez un fichier dans lequel nous placerons le code. Le code sera écrit dans le tableau des candidats au blocage et conservera un historique de débogage.

    Code de fichier pour l'enregistrement des adresses 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); 


    L'essence du code est d'obtenir l'adresse IP du visiteur et de l'écrire dans le tableau. Si ip est déjà dans le tableau, le champ cnt sera augmenté (le nombre de requêtes vers le site)
  • Maintenant ça fait peur ... Maintenant ils vont me brûler pour mes actions :)
    Pour enregistrer chaque appel sur le site, nous incluons le code du fichier dans le fichier WordPress principal - wp-load.php. Oui, nous modifions le fichier du noyau précisément après que la variable globale $ wpdb existe déjà

Donc, maintenant, nous pouvons voir à quelle fréquence telle ou telle adresse IP est notée dans notre tableau et avec une tasse de café nous y regardons toutes les 5 minutes pour comprendre l'image



Copiez ensuite simplement l'IP «nuisible», ouvrez le fichier .htaccess et ajoutez-le à la fin du fichier

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

Tout, maintenant 94.242.55.248 - n'a pas accès au site et ne génère pas de charge sur la base de données

Mais à chaque fois, copier de ses propres mains n'est pas une tâche très juste, et en plus, le code a été conçu comme autonome

Ajoutez un fichier qui sera exécuté par CRON toutes les 30 minutes:

Code de fichier modifiant .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))); 


Le code du fichier est assez simple et primitif et son idée principale est de prendre les candidats au blocage et de saisir les règles de blocage dans le fichier .htaccess entre les commentaires
# start_auto_deny_list et # end_auto_deny_list

Maintenant, l'ip "nuisible" est bloquée par elle-même, et le fichier .htaccess ressemble à ceci:

 # 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 

Par conséquent, après le début d'un tel code, vous pouvez voir le résultat dans le panneau d'hébergement:



PS: Le matériel est protégé par le droit d'auteur, même si j'en ai publié une partie sur mon site, mais sur Habre, une version plus étendue a été obtenue.

Source: https://habr.com/ru/post/fr473030/


All Articles