web-dev-qa-db-ja.com

ボットがWebサーバーを殺さないようにする必要がある

ホスティングアカウント内の一部のWebサイトで極端なボットの問題が発生しています。ボットは、ホストアカウント全体でCPUリソースの98%以上と帯域幅の99%以上を使用します。これらのボットは、私のサイトでは1時間あたり1 GBのトラフィックで生成しています。これらすべてのサイトの実際の人的トラフィ​​ックは100 MB /月未満です。

これらのボットをブロックするためにrobots.txtと.htaccessファイルの両方について広範な調査を行いましたが、すべての方法が失敗しました。

また、robots.txtファイルにコードを入れてスクリプトディレクトリへのアクセスをブロックしましたが、これらのボット(Google、MS Bing、Yahoo)はルールを無視し、とにかくスクリプトを実行します。

Google、MS Bing、Yahooのボットを完全にブロックしたくありませんが、クロールレートを制限したいです。また、robots.txtファイルにCrawl-delayステートメントを追加しても、ボットの速度が低下することはありません。すべてのサイトの現在のrobots.txtおよび.htaccesコードを以下に示します。

クロールレートを絶対的な最低速度に落とすようにMicrosoftとGoogleの両方のウェブマスターツールをセットアップしましたが、これらのサイトには10​​ヒット/秒のレートでヒットしています。

さらに、エラーの原因となるファイルをアップロードするたびに、VPS Webサーバー全体が数秒以内にダウンし、これらのボットによる攻撃の猛攻撃のためにサイトにアクセスすることさえできなくなります。

ウェブサイトへのトラフィックのオンスロットを停止するにはどうすればよいですか?

過去数か月間、この問題についてWebホスティング会社(site5.com)に何度も尋ねてみましたが、彼らはこの問題を解決することができません。

本当に必要なのは、ボットがrss2html.phpスクリプトを実行しないようにすることです。セッションとCookieの両方を試しましたが、両方とも失敗しました。

robots.txt

User-agent: Mediapartners-Google
Disallow: 
User-agent: Googlebot
Disallow: 
User-agent: Adsbot-Google
Disallow: 
User-agent: Googlebot-Image
Disallow: 
User-agent: Googlebot-Mobile
Disallow: 
User-agent: MSNBot
Disallow: 
User-agent: bingbot
Disallow: 
User-agent: Slurp
Disallow: 
User-Agent: Yahoo! Slurp
Disallow: 
# Directories
User-agent: *
Disallow: /
Disallow: /cgi-bin/
Disallow: /ads/
Disallow: /assets/
Disallow: /cgi-bin/
Disallow: /phone/
Disallow: /scripts/
# Files
Disallow: /ads/random_ads.php
Disallow: /scripts/rss2html.php
Disallow: /scripts/search_terms.php
Disallow: /scripts/template.html
Disallow: /scripts/template_mobile.html

.htaccess

ErrorDocument 400 http://english-1329329990.spampoison.com
ErrorDocument 401 http://english-1329329990.spampoison.com
ErrorDocument 403 http://english-1329329990.spampoison.com
ErrorDocument 404 /index.php
SetEnvIfNoCase User-Agent "^Yandex*" bad_bot
SetEnvIfNoCase User-Agent "^baidu*" bad_bot
Order Deny,Allow
Deny from env=bad_bot
RewriteEngine on
RewriteCond %{HTTP_user_agent} bot\* [OR]
RewriteCond %{HTTP_user_agent} \*bot
RewriteRule ^.*$ http://english-1329329990.spampoison.com [R,L]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Send all blocked request to homepage with 403 Forbidden error!
RewriteRule ^(.*)$ index.php [F,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
# Don't show directory listings for directories that do not contain an index file (index.php, default.asp etc.)
Options -Indexes
<Files http://english-1329329990.spampoison.com>
order allow,deny
allow from all
</Files>
deny from 108.
deny from 123.
deny from 180.
deny from 100.43.83.132

追加されたユーザーエージェントのBOTチェックコードを表示するための更新

<?php
function botcheck(){
 $spiders = array(
   array('AdsBot-Google','google.com'),
   array('Googlebot','google.com'),
   array('Googlebot-Image','google.com'),
   array('Googlebot-Mobile','google.com'),
   array('Mediapartners','google.com'),
   array('Mediapartners-Google','google.com'),
   array('msnbot','search.msn.com'),
   array('bingbot','bing.com'),
   array('Slurp','help.yahoo.com'),
   array('Yahoo! Slurp','help.yahoo.com')
 );
 $useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
 foreach($spiders as $bot) {
   if(preg_match("/$bot[0]/i",$useragent)){
     $ipaddress = $_SERVER['REMOTE_ADDR']; 
     $hostname = gethostbyaddr($ipaddress);
     $iphostname = gethostbyname($hostname);
     if (preg_match("/$bot[1]/i",$hostname) && $ipaddress == $iphostname){return true;}
   }
 }
}
if(botcheck() == false) {
  // User Login - Read Cookie values
     $username = $_COOKIE['username'];
     $password = $_COOKIE['password'];
     $radio_1 = $_COOKIE['radio_1'];
     $radio_2 = $_COOKIE['radio_2'];
     if (($username == 'm3s36G6S9v' && $password == 'S4er5h8QN2') || ($radio_1 == '2' && $radio_2 == '5')) {
     } else {
       $selected_username = $_POST['username'];
       $selected_password = $_POST['password'];
       $selected_radio_1 = $_POST['group1'];
       $selected_radio_2 = $_POST['group2'];
       if (($selected_username == 'm3s36G6S9v' && $selected_password == 'S4er5h8QN2') || ($selected_radio_1 == '2' && $selected_radio_2 == '5')) {
         setcookie("username", $selected_username, time()+3600, "/");
         setcookie("password", $selected_password, time()+3600, "/");
         setcookie("radio_1", $selected_radio_1, time()+3600, "/");
         setcookie("radio_2", $selected_radio_2, time()+3600, "/");
       } else {
        header("Location: login.html");
       }
     }
}
?>

rss2html.phpスクリプトの先頭に以下を追加しました

// Checks to see if this script was called by the main site pages, (i.e. index.php or mobile.php) and if not, then sends to main page
   session_start();  
   if(isset($_SESSION['views'])){$_SESSION['views'] = $_SESSION['views']+ 1;} else {$_SESSION['views'] = 1;}
   if($_SESSION['views'] > 1) {header("Location: http://website.com/index.php");}
10
Sammy

rss2html.phpがクライアントによって直接使用されていない場合(つまり、リンクなどでなくPHPが常に使用している場合)、ボットをブロックしようとするのを忘れてください。あなたが本当にしなければならないのは、メインページで定数または何かを定義してから、他のスクリプトをincludeすることです。他のスクリプトでは、定数が定義されているかどうかを確認し、403エラー、空白ページ、または定義されていない場合は何でも吐き出します。

これが機能するためには、file_get_contentsではなくincludeを使用する必要があります。後者はファイルを読み込む(ローカルパスを使用している場合)か、全体で実行するためです他のプロセス(URLを使用している場合)。しかし、それはJoomla!のようなものです。スクリプトが直接含まれないようにするために使用します。また、URLではなくファイルパスを使用して、PHPコードが実行前に解析されないようにします。

さらに良いのは、ドキュメントルートの下からrss2html.phpを移動することですが、一部のホストはそれを困難にします。それがオプションであるかどうかは、サーバー/ホストのセットアップに依存します。

3
cHao

ボットが提供するユーザーエージェント文字列に基づいて404エラーをスローするようにスクリプトを設定できます。ボットはすぐにヒントを取得し、そのままにしておきます。

if(isset($_SERVER['HTTP_USER_AGENT'])){
   $agent = $_SERVER['HTTP_USER_AGENT'];
}

if(preg_match('/^Googlebot/i',$agent)){
   http_response_code(301);
   header("HTTP/1.1 301 Moved Permanently");
   header("Location: http://www.google.com/");
   exit;
}

ログを調べて、同様の方法でBingbotなどを拒否します-要求を停止しませんが、帯域幅をいくらか節約します-googlebotに独自の薬の味を与えます-Mwhahahahaha!

更新済み

あなたのコードを見ると、あなたの問題はここにあると思います:

if (preg_match("/$bot[1]/i",$hostname) && $ipaddress == $iphostname)

悪意のあるボットである場合、どこからでも来ている可能性があり、その$ipaddress句を取り出して、301または404応答をスローします。

ボックスの横を右に考える

  1. GooglebotはCookieを受け入れない なので、Cookieを保存できません。実際、すべてのユーザーにCookieが必要な場合、おそらくボットがページにアクセスできなくなります。
  2. Googlebotはフォームまたはjavascriptを理解しないため、リンクを動的に生成するか、ユーザーにボタンをクリックしてコードに到達させることができます(適切なトークンが添付されています)。

    <a href="#" onclick="document.location='rss2html.php?validated=29e0-27fa12-fca4-cae3';">Rss2html.php</a>

    • rss2html.php?validated = 29e0-27fa12-fca4-cae3-人間
    • rss2html.php-ボット
4
web_bod

PHP制限/スパイダー/ボット/クライアントなどのWebサイトリクエストのブロック

ここで、不要なリクエストをブロックしてウェブサイトのトラフィックを削減できるPHP関数を作成しました。クモ、ボット、迷惑なクライアントのための神。

クライアント/ボットブロッカー

DEMO:http://szczepan.info/9-webdesign/php/1-php-limit-block-website-requests- for-spiders-bots-clients-etc.html

CODE:

/* Function which can Block unwanted Requests
 * @return boolean/array status
 */
function requestBlocker()
{
        /*
        Version 1.0 11 Jan 2013
        Author: Szczepan K
        http://www.szczepan.info
        me[@] szczepan [dot] info
        ###Description###
        A PHP function which can Block unwanted Requests to reduce your Website-Traffic.
        God for Spiders, Bots and annoying Clients.

        */

        $dir = 'requestBlocker/'; ## Create & set directory writeable!!!!

        $rules   = array(
                #You can add multiple Rules in a array like this one here
                #Notice that large "sec definitions" (like 60*60*60) will blow up your client File
                array(
                        //if >5 requests in 5 Seconds then Block client 15 Seconds
                        'requests' => 5, //5 requests
                        'sek' => 5, //5 requests in 5 Seconds
                        'blockTime' => 15 // Block client 15 Seconds
                ),
                array(
                        //if >10 requests in 30 Seconds then Block client 20 Seconds
                        'requests' => 10, //10 requests
                        'sek' => 30, //10 requests in 30 Seconds
                        'blockTime' => 20 // Block client 20 Seconds
                ),
                array(
                        //if >200 requests in 1 Hour then Block client 10 Minutes
                        'requests' => 200, //200 requests
                        'sek' => 60 * 60, //200 requests in 1 Hour
                        'blockTime' => 60 * 10 // Block client 10 Minutes
                )
        );
        $time    = time();
        $blockIt = array();
        $user    = array();

        #Set Unique Name for each Client-File 
        $user[] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'IP_unknown';
        $user[] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        $user[] = strtolower(gethostbyaddr($user[0]));

        # Notice that i use files because bots does not accept Sessions
        $botFile = $dir . substr($user[0], 0, 8) . '_' . substr(md5(join('', $user)), 0, 5) . '.txt';


        if (file_exists($botFile)) {
                $file   = file_get_contents($botFile);
                $client = unserialize($file);

        } else {
                $client                = array();
                $client['time'][$time] = 0;
        }

        # Set/Unset Blocktime for blocked Clients
        if (isset($client['block'])) {
                foreach ($client['block'] as $ruleNr => $timestampPast) {
                        $left = $time - $timestampPast;
                        if (($left) > $rules[$ruleNr]['blockTime']) {
                                unset($client['block'][$ruleNr]);
                                continue;
                        }
                        $blockIt[] = 'Block active for Rule: ' . $ruleNr . ' - unlock in ' . ($left - $rules[$ruleNr]['blockTime']) . ' Sec.';
                }
                if (!empty($blockIt)) {
                        return $blockIt;
                }
        }

        # log/count each access
        if (!isset($client['time'][$time])) {
                $client['time'][$time] = 1;
        } else {
                $client['time'][$time]++;

        }

        #check the Rules for Client
        $min = array(
                0
        );
        foreach ($rules as $ruleNr => $v) {
                $i            = 0;
                $tr           = false;
                $sum[$ruleNr] = '';
                $requests     = $v['requests'];
                $sek          = $v['sek'];
                foreach ($client['time'] as $timestampPast => $count) {
                        if (($time - $timestampPast) < $sek) {
                                $sum[$ruleNr] += $count;
                                if ($tr == false) {
                                        #register non-use Timestamps for File 
                                        $min[] = $i;
                                        unset($min[0]);
                                        $tr = true;
                                }
                        }
                        $i++;
                }

                if ($sum[$ruleNr] > $requests) {
                        $blockIt[]                = 'Limit : ' . $ruleNr . '=' . $requests . ' requests in ' . $sek . ' seconds!';
                        $client['block'][$ruleNr] = $time;
                }
        }
        $min = min($min) - 1;
        #drop non-use Timestamps in File 
        foreach ($client['time'] as $k => $v) {
                if (!($min <= $i)) {
                        unset($client['time'][$k]);
                }
        }
        $file = file_put_contents($botFile, serialize($client));


        return $blockIt;

}


if ($t = requestBlocker()) {
        echo 'dont pass here!';
        print_R($t);
} else {
        echo "go on!";
}
2
dazzafact

http://perishablepress.com/blackhole-bad-bots/ で利用可能なスクリプトで同じ問題を解決しました。このブラックホールアプローチでは、悪意のあるIPのリストを収集し、.htaccessを使用してそれらを拒否しました。 (スクリプト自体が禁止しているため、必須ではありません。ただし、既知の不要なIPのphp解析を回避することでサーバーの負荷を減らす必要があります)3日でトラフィックが1日あたり5 GBから300 MBに減少しました。

多くの既知のジャンクボットをブロックするhtaccessルールの完全なリストについては、このページも確認してください。 http://www.askapache.com/htaccess/blocking-bad-bots-and-scrapers-with-htaccess.html

1
Nishad TR

サイトが偽のGoogleボットによってインデックス登録されている可能性があります。小切手を追加して、すべての偽のGoogleボットリクエストに対して404を提供することができます。

Googlebotを確認する方法を説明する記事は次のとおりです。 http://googlewebmastercentral.blogspot.com/2006/09/how-to-verify-googlebot.html

また、既知の偽のボットに対してレコードを確認することもできます。 http://stopmalvertising.com/security/fake-google-bots.html

1
BluesRockAddict

まず最初に、ユーザーエージェントからリクエストされたページ(使用している不正なクローラーのいずれか)に静的ページが提供されることを確認する必要があります。

Httpサーバーとの条件または同等のApache mod_rewrite。 Apacheの場合、次のようなものです。

RewriteCond  %{HTTP_USER_AGENT}  ^GoogleBot [OR]
RewriteCond  %{HTTP_USER_AGENT}  ^OtherAbusiveBot
RewriteRule  ^/$                 /static_page_for_bots.html  [L]
1
smassey

Smasseyの投稿を続けるには、いくつかの条件を設定できます。

RewriteCond  %{HTTP_USER_AGENT}  ^GoogleBot [OR]
RewriteCond  %{HTTP_USER_AGENT}  ^OtherAbusiveBot
RewriteRule  ^rss2html\.php$     /static.html  [L]

この方法では、ボットは引き続きページにアクセスしますが、そのページにはアクセスしません。 (正当な)ボットがルールを守っていないのは奇妙なので、他のソース(ドメイン名の転送など)からボットをページにプッシュするリファラーはありますか

1
ndrix

あなたがする必要があるのは、Apache/nginx/email/ftp用のSSL証明書をサーバーにインストールすることです。 HSTSを有効にし、ssl.confファイルを編集して、SSLv2 SSLv3 TLSv1が無効になり、着信接続が許可されないようにする必要があります。サーバーを正しい方法で強化すれば、ボットの問題は発生しません。

0
Robert

Cloudflareでドメインをセットアップします(このための無料サービス)。サーバーにヒットする前に、ドメインレベルで悪意のあるボットをブロックします。約20分かかります。コードに手を出す必要はありません。

私はすべてのサイトとすべてのクライアントサイトでこのサービスを使用しています。プロジェクトハニーポットの活用など、さまざまな手法に基づいて悪意のあるボットを特定します。

0
Brett Bumeter
// Checks to see if this script was called by the main site pages,
// (i.e. index.php or mobile.php) and if not, then sends to main page
session_start();  
if (isset($_SESSION['views'])) {$_SESSION['views'] = $_SESSION['views']+ 1;} else {$_SESSION['views'] = 1;}
if ($_SESSION['views'] > 1) {header("Location: http://website.com/index.php");}

このスクリプトは、コメントが言っていることを行いません。実際、完全に反対のことをします。これは、ボットがスクリプトを要求するときにセッション変数が設定されることはないため、常にボットを通過させます。潜在的に行うことは、正当な要求(index.phpまたはmobile.phpから)がスクリプトを複数回呼び出すことを防ぐことです。

ボットがスクリプトにアクセスするのを防ぐために、セッション変数(またはCookie)が実際に設定されている場合にのみアクセスを許可する必要があります。もちろん(悪意のある)ボットがCookieを受け入れないと仮定します。 (実際のGooglebotにはないことがわかっています。)

既に述べたように、rss2html.phpをWebルートの上(パブリックWebスペースの外側)に配置すると、ボットがスクリプトに直接アクセスできなくなりますが、これにより他の問題が発生するということですか?または、ディレクトリに配置し、そのディレクトリを.htaccessで保護します。または、直接のリクエストから.htaccess内のファイル自体を保護することもできますか?

0
MrWhite