2012-01-29 11 views
2

単一のIPアドレスがあまりにも多くの帯域幅を使用し、私のWebページにすばやくアクセスするのを防ぐ方法を知りたかったのです。つまり、ユーザーのIPアドレス(私は$_SERVER['REMOTE_ADDR']と思う)をチェックし、このユーザーからの最近の訪問をチェックし、時間差を計算し、間隔が短い場合はページのレンダリングをブロックします。私は正しい?もしそうなら、どのようにしてサーバー上で過度のリソースや時間を消費することなくそれを行うことができますか?データベースアプローチがある場合は、あまりにも多くのロックを引き起こしていませんか?IPアドレスに基づくページ訪問の回数の制限

+4

このようにして1人のユーザーが本当にあなたのサイトを攻撃したい場合、単純なPHP IPブロックはそれらを止めません。特に、リクエストはすでにPHPに入っているので、とにかくリソースを使用しています。 – animuson

+0

あなたの欠けている最も重要なものは、あなた専用のVPS、専用サーバーか、ファイアウォールへのアクセス権がありますか、あるいはパッケージを入手できますか?または管理された共有ホスティング –

+0

サーバーが専用です。 –

答えて

4

Apacheのmod_bandwidthが

すなわちBandWidth <domain|ip|all> <rate>

http://mansurovs.com/tech/apache-bandwidth-throttling

+2

あなたの権利、リクエストがPHPに当たった場合、攻撃者はすでに勝ちました。 –

+0

私はPHPにアクセスする前にクライアントを制限したいのですが、使用している帯域幅を制限したくありません。単純なマルチスレッドクローラーのように実装されているクライアントがあり、Webサイトのすべてのページをダウンロードしているとします。誰がそれを防ぐことができますか? –

5

特定のIPアドレスを制御することを可能にする最良の方法は、あなたがブロックしようとしている人に依存します。 (b)セッションベースのアプローチを使用して、DBのヒットを避けることができます。それがボットなら、あなたはセッションに頼ることができません(セッションヘッダーを送信していないかもしれないし、現在は悪意のあるボットかもしれないからです)。それはボットをだなら、あなたはおそらく、データベースベースのソリューションを実装します

<?php 
$min_seconds_between_refreshes = 3; 

session_start(); 

if(array_key_exists('last_access', $_SESSION) && time()-$min_seconds_between_refreshes <= $_SESSION['last_access']) { 
    // The user has been here at least $min_seconds_between_refreshes seconds ago - block them 
    exit('You are refreshing too quickly, please wait a few seconds and try again.'); 
} 
// Record now as their last access time 
$_SESSION['last_access'] = time(); 
?> 

:それは、あなたはセッションクッキーを設定してOKだと仮定すると、本物のユーザー

である場合、あなたはこのような何かをしたいでしょう類似の論理を持つ。

実際、両方の場合の正しい解決策は、おそらくアプリケーションサーバーの前にあるキャッシングプロキシサーバーです。これにより、メインのアプリケーションサーバーの負荷が軽減され、このような状況についてそれほど心配する必要はありません。

+0

シンプルなクローラですべてのサーバの帯域幅を使いたいと思うかもしれない* evil *ユーザ/ botをブロックします。データベースアプローチのオーバーヘッドはどうですか? –

+0

そう、セッションのアプローチは機能しません。 DBにはオーバーヘッドがありますが、おそらくリクエストごとに数回DBに当たっていますか? 1つの余分なことはそれほど大きな違いはありません。しかし、それは醜いテーブルになるでしょう、あなたは定期的に古い訪問者をクリアするために何かを書く必要があります。 @eugeneによる解決策が私にとっては最高のようです。 – Howard

1

Memcacheを使用する洪水検出コードがあります。ユーザーが1分以内に50回を超える訪問をした場合、彼は300秒間ブロッキングします。リモートアドレスは、クライアントを識別するために使用されます。

<?php 

$limit = 50; 
$seconds = 60; 
$block_for_seconds = 300; 

$status = 'OK'; 

$memcache = new Memcache; 
$memcache->connect('localhost', 11211); 

$ip = $_SERVER['REMOTE_ADDR']; 

$r = $memcache->get($ip, array('c', 't')); 

$c = 1; // count 
$init_time = time(); 
if($r) { 
    $s = $r[3]; // status 
    $c = $r[0]+1; 
    $init_time = $r[1]; 
    if($s == 'TOO_MANY_REQUESTS') { 
    $d = time()-$r[1]; // time since block 
    if($block_for_seconds-$d > 0) { // still blocked 
     die('Flood detected!! You are going to wait '.($block_for_seconds-$d).' and try again.'); 
    } else { // block is over 
     $status = 'OK'; 
     $init_time = time(); 
     $c = 0; 
    } 
    } 

    $new_time = time(); 
    if($c > $limit) { // check if happened within a minute 
    $time_elapsed = $new_time - $init_time; 
    if($time_elapsed < $seconds) { 
     $status = 'TOO_MANY_REQUESTS'; 
    } 
    print "time elapsed: $time_elapsed, count:$c"; 
    $c = 0; 
    $init_time = time(); 
    } 
} 
print_r($r); 
$memcache->set($ip, array($c, $init_time, $new_time, $status)); 
?> 
関連する問題