hideden.hatenablog.com

はてなぶろぐー。URLなげー。

IPチェック

前職で必要に迫られて2年ほど前に接続元の国名を調べるスクリプトを書いたd:id:hideden:20051108が、なんか間違った事書いてある上にわかりづらい。もう1回書くのもだるいのでバックアップを漁ったところ、発見。

[hideden@sv1]$ perl netstat_country_code.pl                                                                                                                                   
Getting IP List... 
Parse IP List... 
Getting netstat... 
Analyzing netstat... 

JP : 13
CN : 1
TW : 2

実行するとこんな感じ。netstat実行して、Port80番へのその時点での接続の接続元を調べる。過疎サーバーだと何もでない。
なんの役に立つかはちょっと不明。

汚いけどまぁ動くからいいや。書き直すほど使う頻度高くないし。バックアップがわりにはっとく。

#!/usr/bin/perl
use strict;
use LWP::UserAgent;
use HTTP::Request;

$| = 1;
my @ip_list;
if ( -e "./ip_list.txt" && int( -M "./ip_list.txt" ) == 0 ) {
    print "Loading IP List Cache...\n";
    open( LIST, "ip_list.txt" );
    while (<LIST>) {
        chomp;
        my ( $st, $ed, $area ) = split( /\t/, $_ );
        push( @ip_list, { st => $st, ed => $ed, area => $area } );
    }
    close LIST;
}
else {
    print "Getting IP List... \n";
    my $ua = LWP::UserAgent->new();
    my $req = HTTP::Request->new( GET => "http://ftp.apnic.net/stats/apnic/delegated-apnic-latest" );
    my $res = $ua->request($req);
    die "can't get IP List... \n" unless $res->is_success;
    my $list = $res->content;
    
    print "Parse IP List... \n";
    my @list_data = split( /[\r\n]+/, $list );
    foreach (@list_data) {
        my ( $nic, $area, $type, $ip_addr, $num, $date, $mode ) = split( /\|/, $_ );
        next if $type ne 'ipv4';
        next if $area eq '*';
        my $long_ip;
        $long_ip = ($long_ip << 8) + $_ foreach split /\./, $ip_addr;
        push( @ip_list, { st => $long_ip, ed => $long_ip + $num, area => $area } );
    }
    @ip_list = sort { $a->{'st'} <=> $b->{'st'} } @ip_list;
    open( SAVE, ">./ip_list.txt" );
    foreach (@ip_list) {
        print SAVE "$_->{'st'}\t$_->{'ed'}\t$_->{'area'}\n";
    }
    close SAVE;
}
my $list_num = @ip_list;

print "Getting netstat... \n";
my $netstat = `netstat -an`;
my @n_stat = split( /[\r\n]+/, $netstat );
print "Analyzing netstat... \n\n";
my %res;
foreach (@n_stat) {
    my $flg   = 0;
    my $st_ip = 0;
    my $cnt   = $list_num;
    my ( $type, $rq, $sq, $lip, $rip, $stat ) = split( /[\s\t]+/, $_ );
    next if $type ne 'tcp';
    next if $stat eq 'TIME_WAIT';

    my ( $l_ip, $l_pt ) = split( /\:/, $lip );
    my ( $r_ip, $r_pt ) = split( /\:/, $rip );
    next if $l_pt ne '80';  # port 80 connection only

    my $ip;
    $ip = ($ip << 8) + $_ foreach split /\./, $r_ip;
    next if $ip == 0;

    while ( $cnt > 10 ) {
        if ( $cnt % 2 == 1 ) {
            $cnt = int( $cnt / 2 ) + 1;
        }
        else {
            $cnt = $cnt / 2;
        }
        if ( $ip_list[ $st_ip + $cnt - 1 ]->{'ed'} <= $ip ) {
            $st_ip = $st_ip + $cnt - 1;
        }
    }
    for ( my $i = $cnt ; $i > 0 ; $i-- ) {
        if (   $ip_list[ $st_ip + $i ]->{'st'} <= $ip
            && $ip_list[ $st_ip + $i ]->{'ed'} >= $ip )
        {
            $res{ $ip_list[ $st_ip + $i ]->{'area'} }++;
            $flg = 1;
            last;
        }
    }
    $res{'UNKNOWN'}++ if $flg == 0;
}

print "$_ : $res{$_}\n" foreach sort keys %res;