開発 サーバー

GeoIPが使えなくなっていたのでGeoIP2に変更

2019年2月18日

ページが見えなくなった

nginxを再起動すると一部ページにアクセスできないといった問題が発生した

nginxのログを見ても

2019/02/17 21:47:17 [alert] 12146#0: worker process 12164 exited on signal 11 (core dumped) 

といった感じで何かしらエラーをはいているぐらいしかわからなかった。
しかし、調べてみるとGeoIPのファイルが0バイトになっていたのが原因ということがわかった。

GeoIPは提供終了しGeoIP2に置き換わっている

毎日2時ごろにGeoIPのデータを取得するスクリプトを組んでいたが、2018年4月1日で更新終了、2019年1月2日で提供終了となっていた。

そのため、1月からGeoIPのデータが取得できない状態になってみたい。nginx再起動するまで気づかなかったのは起動時にファイル取得していたのかと思われる。

GeoIPがなくなったからIPで国別・市別に行うことはできないのか?ということはなく、代替としてGeoIP2を使用することができるみたいです。

しかし、GeoIPのように使えるわけではなく、仕組みを変更する必要があるっぽい。

nginxでGeoIP2を使う

GeoIP2はGeoIPと同じくmaxmindより取得が可能なので取得してきます。
無償で取得する場合はLite版になります。
有償版との違いは更新頻度の違いだそうです。

wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz

GeoIPの時はgzipでしたが、GeoIP2はtar.gzになっているので注意
次に、GeoIP2を使うにはlibmaxminddbが必要になるため、yumより取得

#yum install libmaxminddb-devel

使い方

まずは、GeoIP2がどのような値が取得できるのかmmdblookupで確認します。

[root@kaede ]# mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 8.8.8.8
 
  {
    "continent": 
      {
        "code": 
          "NA" <utf8_string>
        "geoname_id": 
          6255149 <uint32>
        "names": 
          {
            "de": 
              "Nordamerika" <utf8_string>
            "en": 
              "North America" <utf8_string>
            "es": 
              "Norteamérica" <utf8_string>
            "fr": 
              "Amérique du Nord" <utf8_string>
            "ja": 
              "北アメリカ" <utf8_string>
            "pt-BR": 
              "América do Norte" <utf8_string>
            "ru": 
              "Северная Америка" <utf8_string>
            "zh-CN": 
              "北美洲" <utf8_string>
          }
      }
    "country": 
      {
        "geoname_id": 
          6252001 <uint32>
        "iso_code": 
          "US" <utf8_string>
        "names": 
          {
            "de": 
              "USA" <utf8_string>
            "en": 
              "United States" <utf8_string>
            "es": 
              "Estados Unidos" <utf8_string>
            "fr": 
              "États-Unis" <utf8_string>
            "ja": 
              "アメリカ合衆国" <utf8_string>
            "pt-BR": 
              "Estados Unidos" <utf8_string>
            "ru": 
              "США" <utf8_string>
            "zh-CN": 
              "美国" <utf8_string>
          }
      }
    "registered_country": 
      {
        "geoname_id": 
          6252001 <uint32>
        "iso_code": 
          "US" <utf8_string>
        "names": 
          {
            "de": 
              "USA" <utf8_string>
            "en": 
              "United States" <utf8_string>
            "es": 
              "Estados Unidos" <utf8_string>
            "fr": 
              "États-Unis" <utf8_string>
            "ja": 
              "アメリカ合衆国" <utf8_string>
            "pt-BR": 
              "Estados Unidos" <utf8_string>
            "ru": 
              "США" <utf8_string>
            "zh-CN": 
              "美国" <utf8_string>
          }
      }
  }

IPアドレスから国を索引してみたのですが、多言語対応されていますね。
これらの情報よりnginxに設定します。

#load_module "modules/ngx_http_geoip_module.so";←GeoIPをコメント
 
load_module "modules/ngx_http_geoip2_module.so";←GeoIP2を追加
 
 
#geoip_country  /usr/share/GeoIP/GeoIPv6.dat;  ←GeoIPをコメント
 
##GeoIP2の設定を追加
    geoip2 /【GeoIP2の物理ファイルまでの絶対パス】/GeoLite2-Country.mmdb {
        auto_reload 5m; #←5分毎に再取得
        $geoip2_metadata_country_build metadata build_epoch; #メタデータの取得
 
        #default・・・索引できなかった時の国名(デフォルト値)
        #source・・・どのIPアドレスをもとに索引するか
        #iso_code・・・日本:JPとかアメリカ:USとか
        $geoip2_data_country_code default=US source=$remote_addr country iso_code;
 
        #country names en・・・国名を英語で取得
        $geoip2_data_country_name country names en;
    }
 
##例)国名をMAPで判断する場合
    map $geoip2_data_country_code $allowed_country {
        default no;
        JP yes;
    }

「country iso_code」とか「country names en」はmmdblookupコマンドで取得したメタデータにて判断します。
日本語の国名を取得したいならば「country names ja」になりますし、北アメリカなど大陸で表示したい場合は「continent names ja」になります。
それをnginxの変数に格納していく形になります。

参考サイト

NGINX Docs | GeoIP2

GeoIP2 module | NGINX

ngx_http_geoip2_module

GeoIP2 City Accuracy

-開発, サーバー
-, ,