PHPで日本国外のIPアドレスをアクセス制限する

memcachedを利用し海外のIPアドレスに対して高速に503エラーを返す

日本に割り当てられているIPを取得

DOS/DDOSアタック対策の一環でPHPによる海外IPのアクセス制限を行う。

日本に割り当てられているIPアドレスは下のサイトで取得可能

http://www.cgis.biz/tools/access/

ページの下の方に

[IPアドレス表示]

というボタンがあり、押すとIPの一覧が表示される。今回は、

ip_address_jp.txt

というファイルを作成しIPアドレス一覧をコピーした。

IPリストをメモリにキャッシュする

アクセスがあるたびにIPアドレスリストのファイルにアクセスしていると負荷が高くなるので、memcachedを利用して以下のようにPHPでコードを書いた。

$ip = $_SERVER['REMOTE_ADDR'];

/* テスト用IPリスト
$test_ip_list = array(
	"210.248.0.1", // 日本のip
	"58.14.0.1", // 中国のip
	"10.0.0.1", // USのip
	"25.0.0.1" // UKのip
);
$index = mt_rand(0, 3);
$ip = $test_ip_list[$index];
*/

// パスの設定
$list = "c:\ip_address_jp.txt";

// memcachedの接続処理
$memcache = new Memcache();
$memcache->pconnect('127.0.0.1', 11211) or die('connect failed.');

// キャッシュ有無確認
if ( !$memcache->get('mem_pure') )
{
    $pure = @file($list); // キャッシュが無い場合はファイルから読む
    $memcache->set('mem_pure', $pure, 0, 86400); // メモリにキャッシュをセット
}

else
{
    $pure = $memcache->get('mem_pure'); // キャッシュが有る場合はメモリから読む
    //$memcache->delete('mem_pure'); // 開発中にキャッシュを削除する際に利用
}

// 日本割り当てのipをループ処理
$i = 0;
$c = count($pure);
while ($i < $c) {
    $cidr = chop($pure[$i]);
    list($subnet, $mask) = explode('/', $cidr);

    // アクセスしているIPアドレスと一致していれば、$jpをセットしてループを抜ける
    if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1) ) == ip2long($subnet))
    {
        $jp = true;
	break;
    }

    $i++;
}

// $jpがfalseの場合はHTTP503エラーを返す
if(empty($jp))
{
    header ('HTTP/1.0 503 Service Temporarily Unavailable');
    exit();
}

テスト用IPアドレスなども載せてあるので少々長くなっているが、肝心な部分は、

日本に割り当てられているIPリストをループして、アクセスしてきたIPアドレスとマッチング処理をするコード

が本記事において重要な部分になると思う。

その部分を書くにあたり参考にしたのが、php.netに載っていた下のコード

http://www.php.net/manual/en/function.ip2long.php#82397

上のPHPコードをauto_prepend_fileを利用して、メインスクリプト(WordPressなど)実行前に処理を入れることで、DDOSアタックやボットネットを利用した攻撃の影響を抑制するために利用出来る。

Webエンジニアブログにコメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

PHPで日本国外のIPアドレスをアクセス制限するの記事にコメントを投稿