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のドキュメントにも、地理情報が出力された。