端末IPによるアクセス先の振り分け方法あれこれ
こんにちは、亀本です。
ちょうど今日、予約していたCakePHPガイドブックが会社に届きました。
CakePHPはチュートリアルのサンプルを作ったり、その時に中をぼんやり眺める程度しか触っていなかったので、この機会にちょっと勉強してみようかなと思っています。
1つのフレームワーク本としては厚みがあり、著者陣も「日本でCakePHPといったら」という方々なので期待大です。
ついでに、あわせてsymfony本も読んでやってください、とか宣伝もしておきます(^^;。
さて、そんな話を振っておいて今回は全然違うIP制限のお話です。
携帯対応のサイトになると、できればPCからのアクセスと携帯端末からのアクセスを振り分けたい、という要求が出てきたりします。
USER_AGENTで振り分ける方法もありますが、これは偽装が極めて容易なので振り分け条件としては不十分です。
そこで多くの場合、各キャリアの発表しているIP帯域で振り分けをするという方法が取られます。
もちろん、IPで絞っても偽装されてしまうことはありますが、ちょっとしたお遊びレベルでの不正アクセスは防げます。
今回は、そんな「特定のIP帯域で振り分ける」という方法を自分の知る範囲内でまとめてみました。
# とはい え自分も詳しい方ではないので、他にもっといい方法あるだろー!これはだめだろー!という話があればぜひ教えてください。
1 .htaccessによるアクセス権限設定で振り分ける
最初は、.htaccessでアクセスを許容するIP帯域を設定して、拒否されたものをリダイレクトするという方法です。
Order deny,allow
Deny from All
# 許可するIP帯域を羅列
Allow from xxx.xxx.xxx.xxx/xx
Allow from xxx.xxx.xxx.xxx/xx
・
・
・
ErrorDocument 403 http://.....
多分、Apacheを利用する場合には一番手軽な方法です。管理も楽です。
ただ、「振り分け」という観点からすると、バッドノウハウの部類になるような気もします。
他の理由に起因するアクセス制限も同時にかけたい場合(管理側へのアクセスとか)に不便なんじゃ、とか思う点もあったりして、業務で使うとなると、個人的には微妙です。
個人でサイト作っていて色々考えるのが面倒だったりする場合には、これが一番手っ取り早いかな、という感じです。
2 mod_rewriteを利用する
次はApacheのmod_rewriteを利用する方法です。
RewriteEngin On
RewriteCond %{REMOTE_ADDR} !xxx\.xxx\.xxx\.* [OR]
RewriteCond %{REMOTE_ADDR} !xxx\.xxx\.xxx\.xxx [OR]
・
・
・
RewriteRule ^.*$ http://.... [L]
とすることで、特定のIP帯域以外の場合にRwriteRuleで指定したURLへリダイレクトするようにします。
合わせてHTTP_USER_AGENTなども見てやれるので、柔軟性も高くて便利です。
これを、携帯サイトのIP帯域による振り分けに使用する上で問題があるとすれば、帯域が中途半端な場合(xxx.xxx.xxx.xxx/26とか)には記述がかなり面倒になるという点でしょうか。
自分は、正規表現が目視で間違ってるとわからない方のPHPerなので、各キャリアから発表されているIP帯域一覧に正しく対応する正規表現を、何行も何行もサクサク書いていったりできないし、だからと言って個別に書いてたら発狂します。
携帯の振り分けに使うの であれば、DNSを逆引きしてREMOTE_HOSTを利用、というのがこの方法の現実的な使い方になるんじゃないでしょうか。なおその場合、それなりのアクセス数を稼ぐサイトであれば、逆引きの負荷に注意する必要があります。
# IP振り分けの話をしていて逆引きか。。。とか言わないでくださいw
mod_rewrite: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
参考: http://www.net-newbie.com/trans/mod_rewrite.html
3 PEAR::Net_IPv4を使う
やっぱりPHPerなので、こういうとき頼るのはPEARライブラリです。
Net_IPv4ライブラリを使うと、IP帯域による振り分けがアプリケーション側で容易に実装できます。
インストールはいつもの如く
$ pear install Net_IPv4
このNet_IPv4ライブラリのipInNetwork()メソッドを利用すると、指定したIP帯域内に含まれているかの判定が可能です。
以下が 簡単なサンプルです。
<?php
require_once("Net/IPv4.php");
// $ip_table_listに xxx.xxx.xxx.xxx/24 などのIP帯域の配列を格納
$is_mobile_ip = false;
foreach ($ip_table_list as $value)