GeoIP2のCSVデータでPostgresSQLデータベースを更新して国別拒否リストを生成
国単位でIPアドレス制限を行うためにPostgreSQLにインポートしたGeoIP2のデータを更新しようとしたときの覚書。
環境: CentOS Stream 8, PostgreSQL 14.6, nginx 1.22.1
GeoIP Updateは独自形式のデータベースバイナリ
公式が公開しているGeoIP Updateというプログラムが使えるか調査。
- Updating GeoIP and GeoLite Databases | MaxMind Developer Portal
- GitHub - maxmind/geoipupdate: GeoIP update client code
YUMリポジトリにもあったけどバージョンが低い。
# dnf search geoip
# dnf info geoipupdate
Name : geoipupdateVersion : 2.5.0
だけどGeoIP Updateは独自形式(mmdb)で保存される。
これをnginxから参照する方法もあるみたいだけど、nginx自体のbuildが必要との情報があったので、前と同じcsv形式でPostgreSQLのデータベースをアップデートすることにした。
国別IPアドレスのCSVファイルをダウンロード
最新のCSVダウンロード手順
- MaxMindへログイン
- 左メニューのGeoIP2/GeoLite2のDownload Files
- 「GeoLite2 Country: CSV Format」のDownload ZIPをクリック
ZIPファイルの中身
- GeoLite2-Country-Blocks-IPv6.csv: IPv6一覧
- GeoLite2-Country-Blocks-IPv4.csv: IPv4一覧
- GeoLite2-Country-Locations-ja.csv: IPアドレスIDと国コードの対応リスト(日本語版)
PostgreSQLデータベースへインポート
新規作成時は前の記事を参考に。
nginxで国単位のIPアドレス制限
postgresユーザーでSQLコマンド発行
# su - postgres
$ psql geo
確認のためテーブル一覧表示。
geo=# \d
データ削除
geo=# truncate table geoip2_location;
geo=# truncate table geoip2_network;
IPv4とIPv6をインポート
geo=# \copy geoip2_network(network, geoname_id, registered_country_geoname_id, represented_country_geoname_id,is_anonymous_proxy, is_satellite_provider) from '/opt/geo/GeoLite2-Country-Blocks-IPv4.csv' with (format csv, header);
geo=# \copy geoip2_network(network, geoname_id, registered_country_geoname_id, represented_country_geoname_id,is_anonymous_proxy, is_satellite_provider) from '/opt/geo/GeoLite2-Country-Blocks-IPv6.csv' with (format csv, header);
IPアドレスIDと国コードの対応リストをインポート
geo=# \copy geoip2_location(geoname_id, locale_code, continent_code, continent_name, country_iso_code, country_name, is_in_european_union) from '/opt/geo/GeoLite2-Country-Locations-ja.csv' with (format csv, header);
geo=# quit
nginxの拒否/許可リストを生成
nginxの設定ファイル用にdeny/allow文字を付けてSQL文を実行する。
(SQLの実行結果をファイルに書き出す)
ロシアからのIPアドレスを拒否するnginxのconfファイル。
$ psql geo -c "SELECT concat('deny ', network, ';') FROM geoip2_network gn LEFT JOIN geoip2_location gl on gn.geoname_id = gl.geoname_id WHERE gl.country_iso_code = 'RU';" >> deny_RU.conf
中国からのIPアドレスを拒否するnginxのconfファイル。
$ psql geo -c "SELECT concat('deny ', network, ';') FROM geoip2_network gn LEFT JOIN geoip2_location gl on gn.geoname_id = gl.geoname_id WHERE gl.country_iso_code = 'CN';" >> deny_CN.conf
北朝鮮からのIPアドレスを拒否するnginxのconfファイル。
$ psql geo -c "SELECT concat('deny ', network, ';') FROM geoip2_network gn LEFT JOIN geoip2_location gl on gn.geoname_id = gl.geoname_id WHERE gl.country_iso_code = 'KP';" >> deny_KP.conf
日本からのIPアドレスを許可するnginxのconfファイル。
$ psql geo -c "SELECT concat('allow ', network, ';') FROM geoip2_network gn LEFT JOIN geoip2_location gl on gn.geoname_id = gl.geoname_id WHERE gl.country_iso_code = 'JP';" >> allow_JP.conf
ファイルの先頭と末尾のいらない文を削除。
viコマンドは「1G」で先頭に、「G」でファイル末尾に移動できる。
「dd」で行削除。
# less deny_RU.conf
rootに戻ってnginxの設定ディレクトリに配置
# mv /var/lib/pgsql/deny_* /etc/nginx/conf.d/global/
拒否リストの確認
# less /etc/nginx/conf.d/global/wordpress_restrictions.conf
include conf.d/global/deny_RU.conf;include conf.d/global/deny_CN.conf;include conf.d/global/deny_KP.conf;
nginx再読み込み。
# nginx -t
# systemctl reload nginx
あとはgitで他のサーバーと共有する。
そのうち自動更新するスクリプトを作りたい。