読者です 読者をやめる 読者になる 読者になる

IPアドレスの携帯判定処理について

携帯IPアドレスと携帯端末固有番号によるチェック処理を実装しようとしたけど
仕様上の問題でポシャりそうな感じなのでここにでも残す


IPアドレスは各キャリアともHP上に公開されており、
docomo
au
softbank
emobile
willcom


で、上記HPリストのIPアドレスかどうかで携帯orPC、キャリアの判定する。
IPリストはデータベースに格納


開発はphpなのでPEARモジュールでIPアドレスを取得するモジュールを
探したけどなかったのでperlNet::CIDR::MobileJPを利用させて頂く。
(ちなみにemobileは非対応だが3キャリアのIPが欲しかったので無問題)


CPANからモジュールをインスコ

# perl -MCPAN -eshell
cpan> install Net::CIDR::MobileJP
cpan> install Net::CIDR

↓のファイルを適当なディレクトリにコピって試しに実行

/usr/lib/perl5/site_perl/5.8.8/Net/CIDR/net-cidr-mobilejp-scraper.pl
$ perl net-cidr-mobilejp-scraper.pl

    • -

E:
- 210.230.128.224/28
- 121.111.227.160/27
- 61.117.1.0/28

CIDR形式で出力されるがこのままではデータベースでのチェック処理には向かないので
CIDRをIPアドレスのリストへ出力する関数を作成
ちなみにNet::CIDR::cidr2octetsはクラスC以上のアドレスだと下のオクテットが省略されるので
自分で展開してます
(例えば「210.230.128.0/24」を指定すると「210.230.128」が出力される)

sub myCidr2octets
{
my ($cidr) = @_;
my @list = Net::CIDR::cidr2octets($cidr);

return &setupIpaddrList(@list);
}

sub setupIpaddrList
{
my (@source) = @_;
my @dist = ();
foreach my $ip_source ( @source )
{
my @work = split(/\./, $ip_source);
my $cnt = @work;

$cnt = 4 - $cnt;

if( $cnt )
{
my @next = ();
for( my $i = 0; $i <= 255; $i++)
{
push(@next, $ip_source.'.'.$i);
}

push(@dist, &setupIpaddrList(@next));
}
else
{
push(@dist, ($ip_source) );
}
}
return @dist;
}


これを「net-cidr-mobilejp-scraper.pl」に組み込んでデータベースに格納
データベース定義はこんな感じ
(IPをintで格納すると落とし穴がありそうなのでcharにしてます)

CREATE TABLE `mobile_carrier_ip` (
`mobile_carrier_id` int(10) unsigned NOT NULL auto_increment,
`carrier_code` char(1) NOT NULL,
`ip_address` char(15) NOT NULL,
`created_at` datetime default NULL,
`update_at` datetime default NULL,
PRIMARY KEY (`mobile_carrier_id`),
UNIQUE KEY `uniq_idx_ip_addr` (`ip_address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

symfonyのfilterからクライアントIPアドレスを検索にかけてチェックを実装
(memcacheの利用とかも妄想)


ちなみにデータを入れてみた所、4776件だったのでデータ数的には大した事は無いです。