GeoIP2 に対応した geoipupdate コマンドを面倒臭くビルドする。

スポンサーリンク

geoipupdate をビルドする理由

 GeoIP は MaxMind 社が提供する IP アドレスを元に地理情報を取得する為のサービスで、無償公開されているデータベースを用いればアクセス元の国名と都市名までに限って取得出来る。
 現在、筆者が運用している Linux サーバーを CentOS 7.5 となっており GeoIP のパッケージも GeoIP-1.5.0-11.el7.x86_64 が導入済み。
 しかしこのパッケージに含まれる GeoIP データベース更新プログラムである geoipupdate は次の実行例の様に既に使用できない古いバージョンの物だった。

sudo /usr/bin/geoipupdate -v
Opened License file /etc/GeoIP.conf
Read in license key 000000000000
number of product ids 0 
/usr/share/GeoIP/GeoIP.dat can't be opened, proceeding to download database
Connecting to MaxMind GeoIP Update server
via Host or Proxy Server: updates.maxmind.com:80
Downloading gzipped GeoIP Database...
Done
Saving gzip file to /usr/share/GeoIP/GeoIP.dat.gz ... Done
Uncompressing gzip file ... Done
Writing uncompressed data to /usr/share/GeoIP/GeoIP.dat ...Performing sanity checks ... database_info  FAIL
Received Error -21 (Sanity check database_info string failed) when attempting to update GeoIP Database

 これは MaxMind 社が GeoIP サービスを止めて GeoIP2 に移行している為である。
 そこで GeoIP2 に対応した geoipupdate を結構面倒臭くソースからビルドしてみた手順をメモとしてみる。

geoipupdate ビルドまで下準備

 ビルドする為の作業ディレクトリは一般ユーザの ~/src 以下としているので、参考にされる場合には実環境と読み替える必要あり。
 ビルドした物のインストール先となる --prefix も /usr/local 以下じゃなくて /opt 以下にしたい等でそのままで不味ければ任意に変更する事。
 また、ライブラリパスとして /usr/local/lib を設定していないようであれば /etc/ld.so.conf.d 以下に lib.conf 等と適当なファイル名を作成し、次のようにしておく。

cat /etc/ld.so.conf.d/lib.conf 
/usr/local/lib
/usr/local/curl/lib

OpenSSL 1.1.0 系のビルド

 パッケージとして OpenSSL 1.0.2k がインストール済みとはなっているが、Nginx をビルドするときに OpenSSL 自体のソースが必要になってくるという個人的理由から折角だからメンテナンス期間の長い新しいバージョンを利用することにする。パッケージ版の OpenSSL とは分けて使用する等、運用上の注意は必要。

 ソースのダウンロードは次のオフィシャルサイトより 1.1.0 系の最新版を用いた。本記事執筆時点では 1.1.0i となるのでコマンド実行例もそれに合わせる。

/source/index.html
cd ~/src
wget https://www.openssl.org/source/openssl-1.1.0i.tar.gz
tar xzvf openssl-1.1.0i.tar.gz
cd openssl-1.1.0i 
./config --prefix=/usr/local/openssl shared zlib
make && sudo make install

 これで OpenSSL 1.1.0i のインストールは完了した。

nghttp2 のビルド

 geoipupdate では libcurl を必要としてくる。別に yum で libcurl-devel をインストールしてしまえば一発なのだが、CentOS 標準の curl は HTTP/2 非対応なので折角だから HTTP/2 対応に必要な nghttp2 もビルドする。
 nghttp2 で使用する OpenSSL のライブラリは折角だし先にインストールしておいた OpenSSL 1.1.0i の物を用いる事にした。

cd ~/src
git clone https://github.com/nghttp2/nghttp2.git
cd nghttp2
git submodule update --init
autoreconf -i
automake
autoconf
./configure OPENSSL_CFLAGS="-I/usr/local/openssl/include" OPENSSL_LIBS="-L/usr/local/openssl/lib -lssl -lcrypto" --enable-asio-lib
make && sudo make install

 これで nghttp2 の必要ファイルがインストールされた。

libssh2 のビルド

 これもまた curl のビルドで必要とされる為にソースからビルドする。OpenSSL 1.1.0i のライブラリを使おうかなという理由。面倒なら libssh2-devel を yum でドーンすれば済む話し。

cd ~/src
git clone https://github.com/libssh2/libssh2.git
cd libssh2
./buildconf 
./configure --with-openssl=/usr/local/openssl --with-libssl-prefix=/usr/local/openssl/include/openssl
make && sudo make install
sudo ldconfig

 これで libssh2 も必要ファイルがインストールされた。

cURL のビルド

 やっと cURL のビルドに入る事が出来る。
 configure オプションはなるべく CentOS のパッケージ curl-7.47.1-4.0.cf.rhel7.x86_64 の curl コマンドに近いサポート形式にしてみた。
 流石に面倒臭い libmetalink と libidn2 は yum で楽をした。

sudo yum install libmetalink-devel libidn2-devel
cd ~/src
git clone https://github.com/curl/curl.git
cd curl
./buildconf
./configure --prefix=/usr/local/curl --with-nghttp2=/usr/local/ --with-libidn2 --with-gssapi --with-ssl=/usr/local/openssl --enable-ipv6 --enable-unix-sockets --with-libssh2=/usr/local/lib --with-libmetalink

make && sudo make install
sudo ln -s /usr/local/curl/bin/curl /usr/local/bin
sudo ldconfig

 これで curl コマンドも次の様にビルド完了と。

curl --version
curl 7.61.1-DEV (x86_64-unknown-linux-gnu) libcurl/7.61.1-DEV OpenSSL/1.1.0i zlib/1.2.7 libidn2/2.0.5 libssh2/1.8.0 nghttp2/1.33.0-DEV
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy Metalink 

 HTTP/2 対応としておいたので次の様にしてみるとちゃんと対応出来ていると分かる。なにか検証したいときに便利。

curl --head --http2 https://bucci.bp7.org/                                                [~]
HTTP/2 200 
...
...

geoipupdate のビルド

 寄り道多めに面倒臭い事をしてきたが、ここで本命のビルド。
 libcurl は先程ビルドしてインストールした物を利用させる。

git clone --depth=1 https://github.com/maxmind/geoipupdate
cd geoipupdate
./bootstrap
./configure CPPFLAGS="-I/usr/local/curl/include" CFLAGS="-I/usr/local/curl/include" LDFLAGS="-L/usr/local/curl/lib" --prefix=/usr/local/geoip
make && sudo make install

geoipupdate を使って GeoIP2 データベースの取得/更新

 geoipupdate コマンドはそのまま打ち込むだけでも良いが、初回は -v オプションを付けて正しく動作しているか確認する。

sudo /usr/local/geoip/bin/geoipupdate -v
geoipupdate 3.1.0
Opened License file /usr/local/geoip/etc/GeoIP.conf
Insert edition_id GeoLite2-Country
Insert edition_id GeoLite2-City
Read in license key /usr/local/geoip/etc/GeoIP.conf
Number of edition IDs 2
url: https://updates.maxmind.com/app/update_getfilename?product_id=GeoLite2-Country
md5hex_digest: 00000000000000000000000000000000
url: https://updates.maxmind.com/geoip/databases/GeoLite2-Country/update?db_md5=00000000000000000000000000000000
Uncompress file /usr/local/geoip/share/GeoIP/GeoLite2-Country.mmdb.gz to /usr/local/geoip/share/GeoIP/GeoLite2-Country.mmdb.test
Rename /usr/local/geoip/share/GeoIP/GeoLite2-Country.mmdb.test to /usr/local/geoip/share/GeoIP/GeoLite2-Country.mmdb
url: https://updates.maxmind.com/app/update_getfilename?product_id=GeoLite2-City
md5hex_digest: 00000000000000000000000000000000
url: https://updates.maxmind.com/geoip/databases/GeoLite2-City/update?db_md5=00000000000000000000000000000000
Uncompress file /usr/local/geoip/share/GeoIP/GeoLite2-City.mmdb.gz to /usr/local/geoip/share/GeoIP/GeoLite2-City.mmdb.test
Rename /usr/local/geoip/share/GeoIP/GeoLite2-City.mmdb.test to /usr/local/geoip/share/GeoIP/GeoLite2-City.mmdb

 GeoIP2 データベース取得後、次の様にファイルが存在していれば大丈夫。

ls /usr/local/geoip/share/GeoIP/
GeoLite2-City.mmdb  GeoLite2-Country.mmdb

 データベース保存ディレクトリは /usr/local/geoip/etc/GeoIP.conf にて指定可能なので他のディレクトリに置きたい場合はファイル内コメントを読みながら変更しておくと良いだろう。

GeoIP2 データベースの定期更新

 cron を用いて週一で geoipupdate を読んでおくだけで良い。

Automatic Updates for GeoIP2 and GeoIP Legacy Databases « MaxMind Developer Site

 オフィシャルの例にならって

25 20 * * 5 /usr/local/geoip/bin/geoipupdate

 で良いかなと。

この記事の目的を台無しにするコマンド

sudo yum install epel-release
sudo yum --enablerepo=epel install geolite2-city geolite2-country

 なんてやると

/usr/share/GeoIP/GeoLite2-City.mmdb
/usr/share/GeoIP/GeoLite2-Country.mmdb

 という風に GeoIP2 データベースがインストールされる。
 更新は yum check-update をしていればそのうち更新される。

おわりに

 GeoIP2 のデータベースだけ欲しいのであれば yum 一発。
 しかし過程の中で OpenSSL と cURL に必要性があったのでまぁ面倒臭い事をしたけど「まぁいいかこれで」で終わることが出来た。
 尚、GeoIP2 データベースの利用目的は Nginx で特定の国からのアクセスを遮断する目的がある為。
 これはまた別で記事としたい。

スポンサーリンク