hideden.hatenablog.com

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

アクセス元の国を判別する

やたらと重いサーバー。ふと、どれくらいアクセスされてるのかと思ってnetstatしてみると・・・

$ netstat -an | grep ':80 ' | wc -l
    758

うわ。多い。そりゃ当然重い。

このサーバーがやってるサービスは当然日本向け。だから日本以外からのお客様は別に見てもらってもなんら利益を産まないわけで。とりあえずはどこの国からアクセスがあるのか調査してみようかなーっと。
って事でちょっと思うところがあってアジア地域をメインにIPアドレスからアクセス元を調べてみることに。

アジアのIP割り当てを管理してるのはAPNICなのでここからIPv4の割り当て一覧を取得。
どうやら、
http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
に最新版がある模様。

apnic|CN|ipv4|202.101.128.0|16384|19980817|allocated
apnic|CN|ipv4|202.101.192.0|8192|19980817|allocated
apnic|CN|ipv4|202.101.224.0|2048|19960319|allocated

は、以下のような意味になります。

apnic 国コード ipv4 開始IPアドレス 割り当て個数 割り当て日 種別
apnic CN ipv4 202.101.128.0 16384 19980817 allocated
apnic CN ipv4 202.101.192.0 8192 19980817 allocated
apnic CN ipv4 202.101.224.0 2048 19960319 allocated


この割り当て個数を、111.222.333.444/24形式の『24』部分に変換するにはPerlの場合、

my $num = 16384;
print ( 24 - log($num)/log(2));

でOKです。iptablesなどに指定して拒否するならそのままでOKです。今回の目的は、あるIPアドレスがどの国かを判別することなので、とりあえずIPアドレスをロングIPアドレス*1に変換してから比較することにします。その方が楽だし。

my $ip = '192.168.0.1';
my $long_ip;
$long_ip  = ($long_ip << 8) + $_ foreach split /\./, $ip;
# $long_ip = 3232235521;

あとはコレをどばーっと変換しといて比較するだけですね。APNICだけでも結構な量があるので最低でも2分木検索でもやんないと結構時間がかかって鬱になったりします。笑

そんなこんなで調べた結果、、

国コード 接続数
JP 174
CN 436
KR 8
HK 3
TW 4

となったわけで。即CNとか言う国がiptablesで拒否られました。サーバーも軽くなったし、めでたしめでたし。

*1:ドットで4つに分けず、IPアドレスを10進数でそのまま表記したもの