Wir berechnen potenzielle "böse" Bots und blockieren sie durch IP



Guten Tag! In dem Artikel werde ich Ihnen erklären, wie es gewöhnlichen Hosting-Benutzern möglich ist, IP-Adressen abzufangen, die eine übermäßige Belastung der Website erzeugen, und sie dann mithilfe von Hosting-Tools zu blockieren. Es wird "ein wenig" PHP-Code geben, ein paar Screenshots.

Eingabedaten:

  1. Website erstellt auf CMS WordPress
  2. Hosting Beget (dies ist keine Werbung, aber die Screenshots des Admin-Panels stammen von diesem Hosting-Anbieter)
  3. Die WordPress-Site wurde Anfang 2000 gestartet und enthält eine große Anzahl von Artikeln und Materialien.
  4. PHP Version 7.2
  5. WP hat die neueste Version
  6. Seit einiger Zeit erzeugt die Site laut Hosting eine hohe Belastung für MySQL. Dieser Wert lag jeden Tag über 120% der Norm pro Konto
  7. Laut Yandex. Die Metrik-Site wird täglich von 100 bis 200 Personen besucht

Zunächst wurde es getan:

  1. Datenbanken werden von angesammeltem Müll befreit
  2. Nicht benötigte Plugins sind deaktiviert, Abschnitte veralteten Codes werden entfernt

Gleichzeitig mache ich auf die Caching-Optionen (Caching-Plugins) aufmerksam, wir haben Beobachtungen gemacht - aber die Auslastung von 120% von einer Site war unverändert und konnte nur wachsen.

Wie die ungefähre Belastung der Hosting-Datenbanken aussah


Oben befindet sich die betreffende Site direkt unter anderen Sites, die denselben CMS und ungefähr denselben Verkehr haben, aber weniger Last verursachen.

Analyse

  • Viele Versuche wurden mit Optionen zum Zwischenspeichern von Daten unternommen, Beobachtungen wurden über mehrere Wochen gemacht (der Vorteil des Hostings während dieser Zeit habe ich noch nie geschrieben, dass ich so schlecht bin und mich trennen werde)
  • Es wurde analysiert und nach langsamen Abfragen gesucht, dann wurden die Datenbankstruktur und der Tabellentyp geringfügig geändert
  • Für die Analyse wurden hauptsächlich die integrierten AWStats verwendet (übrigens half es, die schlechteste IP-Adresse durch den Verkehr zu berechnen
  • Metrik - Die Metrik gibt nur Informationen über Personen, nicht über Bots
  • Es gab Versuche, Plugins für WP zu verwenden, mit denen Besucher auch nach Standortland und nach verschiedenen Kombinationen gefiltert und blockiert werden können
  • Es stellte sich heraus, dass es völlig radikal war, die Site für einen Tag mit der Markierung „Wir sind in Wartung“ zu schließen - dies wurde auch mit dem berühmten Plug-In durchgeführt. In diesem Fall erwarten wir, dass die Last sinkt, jedoch nicht auf Werte von 0 nach links, da die Ideologie von WP auf Hooks basiert und Plugins ihre Aktivität beginnen, wenn eine Art „Hook“ auftritt und bevor der „Hook“ auftritt, können bereits Abfragen an die Datenbank durchgeführt werden

Idee

  1. Berechnen Sie IP-Adressen, die in kurzer Zeit viele Anfragen stellen.
  2. Legen Sie die Anzahl der Besuche auf der Website fest
  3. Basierend auf der Anzahl der Treffer wird der Zugriff auf die Site blockiert
  4. Blockieren Sie mit dem Eintrag "Verweigern von" in der .htaccess-Datei
  5. Andere Optionen, wie Iptables und Regeln für Nginx, ohne zu berücksichtigen, weil ich über Hosting schreibe

Eine Idee kam auf, also muss man sie umsetzen, wie ohne ...

  • Wir erstellen Tabellen zur Datenakkumulation

    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; 
  • Erstellen Sie eine Datei, in die wir den Code einfügen. Der Code wird in die Tabelle der Kandidaten zum Blockieren geschrieben und führt einen Verlauf zum Debuggen.

    Dateicode zum Aufzeichnen von IP-Adressen
     <?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); 


    Der Kern des Codes besteht darin, die IP-Adresse des Besuchers abzurufen und in die Tabelle zu schreiben. Wenn ip bereits in der Tabelle enthalten ist, wird das Feld cnt erhöht (Anzahl der Anforderungen an die Site).
  • Jetzt ist es beängstigend ... Jetzt werden sie mich für meine Handlungen verbrennen :)
    Um jeden Aufruf der Site aufzuzeichnen, fügen wir den Dateicode in die Hauptdatei von WordPress ein - wp-load.php. Ja, wir ändern die Kerneldatei genau, nachdem die globale Variable $ wpdb bereits vorhanden ist

Jetzt können wir sehen, wie oft diese oder jene IP-Adresse in unserer Tabelle vermerkt ist, und bei einer Tasse Kaffee schauen wir alle 5 Minuten dorthin, um das Bild zu verstehen



Kopieren Sie dann einfach die "schädliche" IP, öffnen Sie die .htaccess-Datei und fügen Sie sie am Ende der Datei hinzu

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

Alles, jetzt 94.242.55.248 - hat keinen Zugriff auf die Site und generiert keine Last auf der Datenbank

Aber jedes Mal ist das Kopieren mit eigenen Händen keine sehr gerechte Aufgabe, und außerdem wurde der Code als autonom konzipiert

Fügen Sie eine Datei hinzu, die alle 30 Minuten von CRON ausgeführt wird:

Dateicode zum Ändern von .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))); 


Der Code der Datei ist recht einfach und primitiv. Die Hauptidee besteht darin, Kandidaten für die Blockierung zu nehmen und die Blockierungsregeln zwischen den Kommentaren in die .htaccess-Datei einzugeben
# start_auto_deny_list und # end_auto_deny_list

Jetzt werden die "schädlichen" IP-Adressen von selbst blockiert, und die .htaccess-Datei sieht ungefähr so ​​aus:

 # 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 

Infolgedessen können Sie nach dem Beginn der Aktion eines solchen Codes das Ergebnis im Hosting-Bereich sehen:



PS: Das Material ist urheberrechtlich geschützt, obwohl ich einen Teil davon auf meiner Website veröffentlicht habe, aber auf Habre wurde eine erweiterte Version erhalten.

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


All Articles