国を指定して ipfilter.dat を作成する例3:ipinfodb.com のデータ Complete(Country) を利用した場合
- 「%03s」は間違い。正しくは「%03d」
2010-08-06 修正
2009-07-05 修正
前回は一般の企業 ipinfodb.com が作成したIP範囲のリストとして「GeoLite Country」を利用した。もう1つ一般企業が作成したデータ「Complete(Country)」を利用した例を示したい(国指定のIP範囲リスト作成は今回が最終回)
前提条件
1.元データをダウンロード
- データは毎月第一週に更新される
wget -nd -nc http://mirrors.portafixe.com/ipinfodb/ip_database/current/ipinfodb_one_table_full_country.csv.zip
2.解凍
unzip -u ipinfodb_one_table_full_country.csv.zip bzip2 -dc ip_group_country.csv.bz2 >ip_group_country.csv
3.データ概要
- 解凍後のファイルサイズは8メガ強。10万行強でセミコロン(;)区切り
フィールド | 意味 |
---|---|
第1フィールド | 10進数化した開始IPアドレス |
第2フィールド | 可能なIPアドレスの範囲(ネットワークアドレス+CIDR表記) |
第3フィールド | ISO 3166 ベースの国コード |
第4フィールド | 国名 |
"ip_start";"ip_cidr";"country_code";"country_name" "0";"0.0.0.0/8";"RD";"Reserved" "16777216";"1.0.0.0/8";"RD";"Reserved" "33554432";"2.0.0.0/8";"RD";"Reserved" "50331648";"3.0.0.0/8";"US";"United States" 中 略 "4227858432";"252.0.0.0/8";"RD";"Reserved" "4244635648";"253.0.0.0/8";"RD";"Reserved" "4261412864";"254.0.0.0/8";"RD";"Reserved"
4.ipfilter.dat 形式に変換
BEGIN { FS = ";"; # OFS = ","; match_counter = 0; CLS_A = 16777216; CLS_B = 65536; CLS_C = 256; OFFSET[1] = 1; OFFSET[2] = 3; OFFSET[3] = 7; OFFSET[4] = 15; OFFSET[5] = 31; OFFSET[6] = 63; OFFSET[7] = 127; OFFSET[8] = 255; OFFSET[9] = 511; OFFSET[10] = 1023; OFFSET[11] = 2047; OFFSET[12] = 4095; OFFSET[13] = 8191; OFFSET[14] = 16383; OFFSET[15] = 32767; OFFSET[16] = 65535; OFFSET[17] = 131071; OFFSET[18] = 262143; OFFSET[19] = 524287; OFFSET[20] = 1048575; OFFSET[21] = 2097151; OFFSET[22] = 4194303; OFFSET[23] = 8388607; OFFSET[24] = 16777215; OFFSET[25] = 33554431; OFFSET[26] = 67108863; OFFSET[27] = 134217727; OFFSET[28] = 268435455; OFFSET[29] = 536870911; OFFSET[30] = 1073741823; OFFSET[31] = 2147483647; OFFSET[32] = 4294967295; } /"CN";"China"/ || /"HK";"Hong Kong"/ || /"TW";"Taiwan"/ || /"JP";"Japan"/ { gsub( /"/, "" ); if(split($2, ip_cidr, "/") != 2) { print "[ERROR]split error"; exit 2; }else if(NUMrize(ip_cidr[1]) != $1) { print "[ERROR]NUMrize error",ip_cidr[1],$1; exit 3; } gsub(",", " ", $4); printf "%-s - %-s , %03d , [%s]%s\r\n", ip_cidr[1], IPrize($1 + OFFSET[32-ip_cidr[2]]), 58, $3, $4; ++match_counter; } END { printf "### The total number of matched records in the IPInfoDB: %d\r\n", match_counter; } ############################## User-defined Functions ############################## function NUMrize(ip){ if( split(ip, IPs, ".") != 4 ) { print "[IP Field Error]Total number of IP field is invalid"; exit 4; } return int(IPs[1])*CLS_A + int(IPs[2])*CLS_B + int(IPs[3])*CLS_C + int(IPs[4]); } function IPrize(num){ a = int(num/CLS_A); b = int( (num-a*CLS_A)/CLS_B ); c = int( (num - a*CLS_A - b*CLS_B)/CLS_C ); d = num - a*CLS_A - b*CLS_B - c*CLS_C; return sprintf("%d.%d.%d.%d", a, b, c, d ); }
処理の流れとしては、
- BEGIN ブロックで FS に読み込むファイルのセパレータを設定。カウンターを初期化。OFFSET 配列は CIDR 計算用に使う。配列番号をビット幅に見立ててその取り得る値の数から1を引いた数(例:4番目の配列なら2の4乗 - 1で15となる)
- /正規表現/ ブロックで抽出条件(今回の場合は中国 or 香港 or 台湾 or 日本)に一致したレコードのみを処理する(awk では or を 釗釗 と書く)
- 二重引用符(ダブルクォーテーション)を削除
- 第2フィールドをスラッシュ(/)の前後で分割し、それぞれを ip_cidr 配列に格納
- 10進数化した ip_cidr[1](開始IPアドレス) が第1フィールドと同じか確認
- 終了アドレスは第1フィールドに CIDR から計算した OFFSET を加えて IP 文字列に変換(IPrize)する
- match_counter を加算(+1)
- END ブロックで処理した行数(match_counter)をコメント文として出力
下記のようにコマンドを実行する
gawk -f IPInfoDB2ipfilter.awk ip_group_country.csv
出力結果のサンプル
17.80.0.0 - 17.80.127.255 , 058 , [HK]Hong Kong 17.83.128.0 - 17.83.255.255 , 058 , [JP]Japan 24.233.71.245 - 24.233.71.245 , 058 , [JP]Japan 32.60.34.16 - 32.60.34.23 , 058 , [JP]Japan 中 略 222.240.0.0 - 222.247.255.255 , 058 , [CN]China 222.248.0.0 - 222.249.255.255 , 058 , [CN]China 222.250.0.0 - 222.250.255.255 , 058 , [TW]Taiwan 222.251.0.0 - 222.251.127.255 , 058 , [TW]Taiwan ### The total number of matched records in the IPInfoDB: 5855
5.数値をゼロ埋めに変更する(例:1 ⇒ 001)
下記のようにコマンドを実行する
gawk -f IPInfoDB2ipfilter.awk ip_group_country.csv | gawk -f FillByZero.awk
出力結果のサンプル
017.080.000.000 - 017.080.127.255 , 058 , [HK]Hong Kong 017.083.128.000 - 017.083.255.255 , 058 , [JP]Japan 024.233.071.245 - 024.233.071.245 , 058 , [JP]Japan 032.060.034.016 - 032.060.034.023 , 058 , [JP]Japan 中 略 222.240.000.000 - 222.247.255.255 , 058 , [CN]China 222.248.000.000 - 222.249.255.255 , 058 , [CN]China 222.250.000.000 - 222.250.255.255 , 058 , [TW]Taiwan 222.251.000.000 - 222.251.127.255 , 058 , [TW]Taiwan ### The total number of matched records in the IPInfoDB: 5855
6.IPアドレスの範囲が連続しているレコードを連結してファイルサイズを減らす
gawk -f IPInfoDB2ipfilter.awk ip_group_country.csv | gawk -f FillByZero.awk | gawk -f ConnectRecords.awk
- 約半分に削減される。処理後の出力のサンプルは以下の通り
017.080.000.000 - 017.080.127.255 , 058 , [HK]Hong Kong 017.083.128.000 - 017.083.255.255 , 058 , [JP]Japan 024.233.071.245 - 024.233.071.245 , 058 , [JP]Japan 032.060.034.016 - 032.060.034.023 , 058 , [JP]Japan 中 略 222.166.000.000 - 222.229.079.255 , 058 , [HK]Hong Kong_[CN]China_[CN]China_以後省略 222.229.096.000 - 222.230.255.255 , 058 , [JP]Japan_[JP]Japan_[JP]Japan 222.231.064.000 - 222.231.255.255 , 058 , [JP]Japan_[JP]Japan 222.240.000.000 - 222.251.127.255 , 058 , [CN]China_[CN]China_[TW]Taiwan_[TW]Taiwan ### The total number of matched records: 5855 Compacted: 2795
7.使い方
作成した ipfilter.dat を対応アプリに読み込ませます
さすがに飽きてきた...国別のIPアドレスを抽出するのは今回が最後
まとめ
4行で ipfilter.dat が作成できた
wget -nd -nc http://mirrors.portafixe.com/ipinfodb/ip_database/current/ipinfodb_one_table_full_country.csv.zip
unzip -u ipinfodb_one_table_full_country.csv.zip
bzip2 -dc ip_group_country.csv.bz2 >ip_group_country.csv
gawk -f IPInfoDB2ipfilter.awk ip_group_country.csv | gawk -f FillByZero.awk | gawk -f ConnectRecords.awk >ipfilter.dat