2013/12/22

nginxのhttp_geoip_moduleでアクセスログにクライアントIPの地理情報を出力する。

http_geoip_module

nginxのhttp_geoip_moduleを使うとクライアントのIPアドレスから地理情報を取得できる、と知ったので試してみた。nginxのドキュメントは、ここにあります。

http_geoip_moduleは、MaxMind社が公開するIPアドレス-地理情報マッピングデータベースを利用する、ということで、http_geoip_moduleを利用するには、同社のデータファイルやもろもろのツールなどをインストール必要があるらしい。

geoip-databaseとlibgeoip-dev

Debian系のOSでは、aptでgeoip-databaseとlibgeoip-devをインストールできる。やってみると、geoip-databaseは予めインストールされとった。(ちなみに、Ubuntuっす。)

$ sudo apt-get install geoip-database
Reading package lists... Done
Building dependency tree       
Reading state information... Done
geoip-database is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 12 not upgraded.
## もう入ってた・・
$ sudo apt-get install libgeoip-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  geoip-bin
The following NEW packages will be installed:
  geoip-bin libgeoip-dev
0 upgraded, 2 newly installed, 0 to remove and 12 not upgraded.
Need to get 227 kB of archives.
After this operation, 1021 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://jp.archive.ubuntu.com/ubuntu/ precise/main geoip-bin amd64 1.4.8+dfsg-2 [42.4 kB]
Get:2 http://jp.archive.ubuntu.com/ubuntu/ precise/main libgeoip-dev amd64 1.4.8+dfsg-2 [185 kB]
Fetched 227 kB in 0s (641 kB/s)      
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
 LANGUAGE = "en_US:",
 LC_ALL = (unset),
 LC_CTYPE = "ja_JP.UTF-8",
 LC_COLLATE = "ja_JP.UTF-8",
 LC_MESSAGES = "ja_JP.UTF-8",
 LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Selecting previously unselected package geoip-bin.
(Reading database ... 52114 files and directories currently installed.)
Unpacking geoip-bin (from .../geoip-bin_1.4.8+dfsg-2_amd64.deb) ...
Selecting previously unselected package libgeoip-dev.
Unpacking libgeoip-dev (from .../libgeoip-dev_1.4.8+dfsg-2_amd64.deb) ...
Processing triggers for man-db ...
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Setting up geoip-bin (1.4.8+dfsg-2) ...
Setting up libgeoip-dev (1.4.8+dfsg-2) ...

GeoIPデータファイル

geoip-databaseが予めインストールされていたため、IPアドレス-国情報マッピングファイル(GeoIP.dat)は、/usr/share/GeoIP/にすでにファイルがあったのだけど、これだけだと都市名の情報が引けないので、GeoLiteCity.datとというファイルを別途ダウンロードする必要がある。そして、GeoIP.datと同じディレクトリに置く。

$ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
$ gnuzip GeoLiteCity.dat.gz
$ sudo mv GeoLiteCity.dat.gz /usr/share/GeoIP/

nginx

nginxは、cofigureの時点でhttp_geoip_moduleを有効化しないといけない。なので、今回は最新の安定版のソースをダウンロードしてきて、ビルドしなおした。(↓の./configure時のオプションは、実際は他にも色々指定してます。)

$ cd /usr/local/src
$ sudo wget http://nginx.org/download/nginx-1.4.4.tar.gz
$ tar zxf nginx-1.4.4.tar.gz
$ sudo ./configure --prefix='/usr/local/nginx' --with-http_geoip_module
$ sudo make
$ sudo make install

nginx.conf

http_geoip_moduleを利用するために、nginx.confにちょっと追記した。

geoip_countryディレクティブ
GeoIP.datのパスを指定して、$geoip_country_code、$geoip_country_code3、$geoip_country_nameを有効にする。
geoip_cityディレクティブ
GeoLiteCity.datのパスを指定して、$geoip_cityや$geoip_latitude、$geoip_longitudeなどを有効にする。

この2つのディレクティブは、ファイルパスを指定するのだけど、ここの例のようにファイル名だけ指定すると、ファイルオープンエラーとなるので、絶対パスを指定した(ら、うまく動きました。) で、$geoip_xxxxxという一連の変数が利用可能になるので、これらをアクセスログフォーマットに埋めてあげると、ログに出力されるようなる。今回設定したnginxは、fluentdでmongodbに蓄積させるためにltsv形式でログを出力しているので、geoip関連もltsv形式でログフォーマットに追加した。修正したnginx.confは、↓のようになった。
:

http {
    :
  geoip_country /usr/share/GeoIP/GeoIP.dat;
  geoip_city    /usr/share/GeoIP/GeoLiteCity.dat;
    :

  log_format ltsv "time:$time_local"
                  "\thost:$remote_addr"
                  "\tforwardedfor:$http_x_forwarded_for"
                  "\tuser:$remote_user"
                  "\treq:$request"
                  "\tmethod:$request_method"
                  "\turi:$request_uri"
                  "\tstatus:$status"
                  "\tsize:$body_bytes_sent"
                  "\treferer:$http_referer"
                  "\tua:$http_user_agent"
                  "\treqtime:$request_time"
                  "\tcache:$upstream_http_x_cache"
                  "\truntime:$upstream_http_x_runtime"
                  "\tapptime:$upstream_response_time"
                  "\tvhost:$host"
                  "\tgeoip_country_name:$geoip_city_country_name"    # <= 国名
                  "\tgeoip_country_code3:$geoip_city_country_code3"  # <= JPNとかUSAとか
                  "\tgeoip_city:$geoip_city"                         # <= 都市名
                  "\tgeoip_latitude:$geoip_latitude"                 # <= 緯度
                  "\tgeoip_longitude:$geoip_longitude";              # <= 経度
    :
}
:
nginx再起動して、何やらアクセスすると、ログとfluendが出力してくれるmongodbのドキュメントにも、地理情報が出力された。

0 件のコメント: