We calculate potential "evil" bots and block them by IP





Good day! In the article I’ll tell you how it is possible for ordinary hosting users to catch IP addresses generating excessive load on the site and then block them using hosting tools, there will be a “little bit” php code, a few screenshots.



Inputs:



  1. Website created on CMS WordPress
  2. Hosting Beget (this is not an advertisement, but the screenshots of the admin panel will be of this hosting provider)
  3. WordPress site launched somewhere in the beginning of 2000 and has a large number of articles and materials.
  4. PHP Version 7.2
  5. WP has the latest version
  6. For some time now the site began to generate a high load on MySQL according to the hosting. Every day, this value exceeded 120% of the norm per account
  7. According to Yandex. The metric site is visited by 100-200 people a day


First of all, it was done:



  1. Database tables are cleared of accumulated garbage
  2. Unnecessary plugins are disabled, sections of outdated code are removed


At the same time, I draw attention to the caching options (caching plugins), we made observations - but the load of 120% from one site was unchanged and could only grow.



How the approximate load on the hosting databases looked





In the top is the site in question, just below other sites that have the same cms and about the same traffic, but create less load.



Analysis





Idea



  1. Calculate IP addresses that make a lot of requests in a short period of time.
  2. Record the number of hits to the site
  3. Based on the number of hits block access to the site
  4. Block using the “Deny from” entry in the .htaccess file
  5. Other options, like iptables and rules for Nginx without considering, because I write about hosting


An idea came up, so you need to realize how without it ...





So, now we can see how often this or that IP address is noted in our table and with a coffee mug we look there every 5 minutes to understand the picture







Then simply copy the “harmful” IP, open the .htaccess file and add it to the end of the file



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





Everything, now 94.242.55.248 - does not have access to the site and does not generate a load on the database



But each time, copying with your hands is not a very righteous task, and besides, the code was conceived as standalone



Add a file that will be executed by CRON every 30 minutes:



File Code Modifying .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)));
      
      







The code of the file is quite simple and primitive and its main idea is to take the candidates for blocking and enter the blocking rules into the .htaccess file between comments

# start_auto_deny_list and # end_auto_deny_list



Now the "harmful" ip are blocked by themselves, and the .htaccess file looks something like this:



 # 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
      
      





As a result, after the beginning of the action of such code, you can see the result in the hosting panel:







PS: The material is copyright, even though I published part of it on my website, but on Habre a more extended version was obtained.



All Articles