IPアドレスから地域を特定する2 - GeoLite Legacy Country CSV
前回、GeoLite2 と GeoIP2 Java API 等のライブラリを使って IP アドレスから国と都市を特定しましたが、今回は GeoLite Legacy の Country CSV ファイル (IPv4用) を使って国を特定する処理を実装してみます。
なお、前回は IPv6 でも処理できましたが、今回は IPv4 のみを処理対象としています。
今回のソースは http://github.com/fits/try_samples/tree/master/blog/20141008/
はじめに
GeoLite Legacy の Country CSV ファイル GeoIPCountryWhois.csv
のフォーマットは下記のようになっています。
Country CSV フォーマット
<開始IP>,<終了IP>,<開始IPの数値>,<終了IPの数値>,<国名コード>,<国名>
内容は下記の通りです。
GeoIPCountryWhois.csv
"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia" "1.0.1.0","1.0.3.255","16777472","16778239","CN","China" "1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia" "1.0.8.0","1.0.15.255","16779264","16781311","CN","China" "1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan" ・・・
3・4 列目の数値は IP アドレスを 32bit の正の整数値で表現したものです。
なお、GeoIPCountryWhois.csv ファイルは GeoLite Legacy Downloadable Databases の GeoLite Country の CSV/zip からダウンロードできます。
国の判定
GeoIPCountryWhois.csv ファイルを使った国の判定は下記のように処理できます。
注意点として、IPv4 を数値化した値は 32bit の正の整数ですが、Java に unsigned int のような型はありませんので、long 型などで扱う事になります。
また、Inet4Address
の hashCode()
メソッドで (1) の値を取得できるのですが、unsigned
な値ではありませんので下記のような方法で変換します。
(例えば、IP アドレス 150.70.96.0
を数値化した 2521194496
は、Java の int 型では -1773772800
となります)
- (a) Java 8 から追加された
Integer.toUnsignedLong(int)
メソッドを使用 - (b)
0xffffffff
と AND 演算する (<Inet4Address の hashCode 値> & 0xffffffff
)
get_country.groovy
if (args.length < 2) { println '<geolite country csv file> <ip address>' return } // (a) def toNumForIP = { Integer.toUnsignedLong(it.hashCode()) } // (b) 以下でも可 // def toNumForIP = { it.hashCode() & 0xffffffff } def ip = toNumForIP( InetAddress.getByName(args[1]) ) new File(args[0]).eachLine() { def r = it.replaceAll('"', '').split(',') def from = r[2] as long def to = r[3] as long if (from <= ip && ip <= to) { println r.last() System.exit(0) } } println 'Unknown'
実行結果は下記の通りです。
実行結果1
> groovy get_country.groovy GeoIPCountryWhois.csv 1.21.127.254 Japan
実行結果2
> groovy get_country.groovy GeoIPCountryWhois.csv 223.255.254.1 Singapore
実行結果3
> groovy get_country.groovy GeoIPCountryWhois.csv 192.168.1.1 Unknown