« Amazon S3にバックアップをする2 | トップページ | LinuxでchrootによるJail環境を構築 »

2010年2月23日 (火)

auとdocomoのIPアドレス帯域のチェックツール

キャリアのIPを登録し忘れたせいで、最近立て続けにサイトにアクセスできない問
い合わせをいただいた。キャリアごとにWebで使用しているIPを公開しているのだ
が、ついチェックをサボるとこういうことになってしまう。
正直atomで公開してくれていると更新がわかって便利なのだが、auもdocomoも
Webページでしか公開していない。そこでezweb(au)PCサイトビューア(au)
brew(au)iモード(docomo) のWebページを解析して、変更があればメールで
通知するスクリプトを書いた。
チェックごとに前回チェックした時とのIPの差分をとって差分があった場合に通知
します。初回は必ずメールが来ます。cronに登録して毎日実行するといいと思いま
す。

#!/usr/bin/perl -w
use strict;
use warnings;
use LWP::Simple;
use HTML::TreeBuilder;
use Data::Dumper;
use Mail::Mailer;
use YAML ();
my $file_name  = "/var/tmp/mobile_app_ip.yml";

my %provider = (
    "ezweb"=>"http://www.au.kddi.com/ezfactory/tec/spec/ezsava_ip.html",
    "brew"=>"http://www.kddi.com/business/customer/tec/index.html",
    "ezpcsv"=>"http://www.au.kddi.com/ezfactory/tec/spec/pcsv.html",
    "imode" => "http://www.nttdocomo.co.jp/service/imode/make/content/ip/index.html",
    );
my %ydoc;
if( -f $file_name){
    %ydoc = YAML::LoadFile($file_name);
}
my %notices;
my %new_doc;
for my $prov_name (keys(%provider)){
    my $html = get($provider{$prov_name});
    my $tree = new HTML::TreeBuilder;
    $tree->parse($html);
    $tree->eof();
    my $num = 1;
    my %ip_set;
    my @ip_order;
    my $state;
    if($prov_name =~ /^ez/){
        for my $tag ( $tree->look_down("class", "TableText")){
            if($tag->as_text eq $num){
                $state = "ip";
                $num++;
                next;
            }
            unless($state){
                next;
            }
            if($state eq "ip"){
                $state = "mask";
                push @ip_order,$tag->as_text;
                $ip_set{$tag->as_text} = {provider=>$prov_name};
                next;
            }
            if($state eq "mask"){
                $ip_set{$ip_order[-1]}->{"mask"} = $tag->as_text;
                $state = undef;
                next;
            }
        }
    }
    elsif($prov_name =~ /brew/){
        for my $tag ( $tree->look_down("class", "center")){
            if($tag->as_text eq $num){
                $state = "ip";
                $num++;
                next;
            }
            unless($state){
                next;
            }
            if($state eq "ip"){
                $state = undef;
                my @nodes = split "/",$tag->as_text;
                $nodes[0] =~ s/\s+//g;
                $nodes[1] =~ s/\s+.*$//;
                push @ip_order,$nodes[0];
                $ip_set{$nodes[0]} = {provider=>$prov_name,"mask"=>"/".$nodes[1]};
            }
        }

    }
    else {
        my $cnt=0;
        for my $tag ( $tree->look_down("class", "normal txt")){
            my $li_html = $tag->as_HTML;
            my $li_tree = new HTML::TreeBuilder;
            $li_tree->parse($li_html);
            $li_tree->eof();
            for my $li ( $li_tree->find("li")){
                my @nodes = split "/",$li->as_text;
                $nodes[1] =~ s/\s+.*$//;
                push @ip_order,$nodes[0];
                $ip_set{$nodes[0]} = {provider=>$prov_name,"mask"=>"/".$nodes[1]};
            }
            $li_tree = $li_tree->delete;

            $cnt++;
            if($cnt > 1){
                last;
            }
        }
    }
    $tree = $tree->delete;
    for my $ip (@ip_order){
        if(!$ydoc{$prov_name} or !$ydoc{$prov_name}->{$ip}){
            $notices{$prov_name} = [] unless $notices{$prov_name};
            push @{$notices{$prov_name}},"ip:$ip" .$ip_set{$ip}->{"mask"} . " added.\n";
        }elsif($ydoc{$prov_name}->{$ip}->{"mask"} ne $ip_set{$ip}->{"mask"}){
            $notices{$prov_name} = [] unless $notices{$prov_name};
            push @{$notices{$prov_name}}," ip:$ip".$ip_set{$ip}->{"mask"} . " mask modified.\n";
        }
    }
    for my $ip (keys(%{$ydoc{$prov_name}})){
        unless($ip_set{$ip}){
            $notices{$prov_name} = [] unless $notices{$prov_name};
            push @{$notices{$prov_name}},"ip:$ip".$ydoc{$prov_name}->{$ip}->{"mask"} . " deleted.\n";
        }
    }
    $new_doc{$prov_name} = \%ip_set;
}
if(%notices){
    my $mailer = Mail::Mailer->new("smtp",Server=>"SMTPサーバ");
    $mailer->open({
        From => '送信元メールアドレス',
        To => '送信先メールアドレス',
        Subject => 'Provider IP Modified',
        }) or die "Can't open $! \n";

    for my $prov_name (keys(%notices)){
        print $mailer "\nPROVIDER:". $prov_name ." URL:" . $provider{$prov_name} ."\n";
        for my $message (@{$notices{$prov_name}}){
            print $mailer $message;
        }
    }
    $mailer->close();
}
open my $new_file ,">",$file_name;
print $new_file YAML::Dump(%new_doc);
close $new_file

EZアプリはPCサイトビューア用のIPでアクセスしてくるみたいだったので、PCサ
イトビューアのIPもチェックするようにした

Rubyで書こうと思っていたけど、nokogiriがlibxml2のdevel環境に依存している
が、私のサーバ環境ではインストールに失敗(libxml2とlibxml2-devのバージョン
が一致しない)したため、PerlのHTML::TreeBuilderを使用することにした。
こちらはサクッとCPANからインストールできた。

追記 2010 02.25
brew用のアドレス一覧のサイトがありました。
プログラムに追記しました。

|

« Amazon S3にバックアップをする2 | トップページ | LinuxでchrootによるJail環境を構築 »

perl」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/68673/47641213

この記事へのトラックバック一覧です: auとdocomoのIPアドレス帯域のチェックツール:

« Amazon S3にバックアップをする2 | トップページ | LinuxでchrootによるJail環境を構築 »