はじめに
担当: 守矢 ![]()
今回は、CentOS 7 / Nginx 1.17 の環境にGeoIP2を導入し、海外IPからのアクセスを制御する方法を紹介します。
既存環境への影響を抑えるため、
- Nginx本体を変更しない
- 対象環境に開発ツールを追加しない
- 変更範囲を最小限にする
という方針で、Dockerを利用して動的モジュールをビルドする方法を採用しました。
この記事では、GeoIP2導入までの判断と手順をまとめています。
要件
海外IPアクセスを制御します。
| 国 | 動作 |
|---|---|
| JP | 許可 |
| JP以外 | 403 |
例として特定ディレクトリへの海外アクセスをブロックします。
環境
| 項目 | 内容 |
|---|---|
| OS | CentOS 7 |
| Nginx | 1.17 |
※記載の構成や設定値は一例です
GeoIP2導入方法の検討
GeoIP2導入には大きく2つの方法があります。
A案:RPMで nginx-module-geoip2 を導入
RHEL系ではリポジトリから nginx-module-geoip2 を導入する方法もあります。
sudo yum install nginx-module-geoip2
※環境によっては追加リポジトリが必要になる場合があります。
ただし、Nginxモジュールは ABI互換性 が必要で、
Nginx本体とモジュールのビルド条件が一致していないと
モジュールのロードに失敗する可能性があります。
今回の環境では既存の Nginx パッケージ構成を変更するリスクがあったため、この方法は採用しませんでした。
B案:GeoIP2モジュールをビルド(動的モジュール)
もう1つは、現在利用している Nginx に合わせて GeoIP2 モジュールをビルドする方法です。
Nginxは .so モジュールをロードできます。
load_module modules/ngx_http_geoip2_module.so;
今回は この方法を採用しました。
ただし、GeoIP2モジュールのビルドには、gcc、make、Nginxのソースコード、libmaxminddb-develなどが必要です。
開発パッケージを追加すると、依存関係の変更などによって既存環境に影響する可能性があります。
そのため、ビルドは対象環境では行わず、ローカルのDocker環境で実施する方針としました。
🐳 DockerでCentOS 7環境を再現
対象環境に近いOS環境を再現するため、
ローカルでCentOS 7のDocker環境を作り、検証とビルドを行いました。
Dockerfileでは主に次のことを行っています。
- CentOS 7のvaultリポジトリを使うように変更
- nginx 1.17.0のソースを取得
-
ngx_http_geoip2_moduleを取得 -
libmaxminddb-develなどビルドに必要なパッケージをインストール - 対象環境に合わせたconfigureオプションで動的モジュールをビルド
- GeoLite2-Countryを配置してnginx設定まで含めて動作確認
初回検証では動作確認のため
GeoLite2-Country.mmdb を手動で配置しています。
実運用では geoipupdate による自動更新を使用します。
ポイント
GeoIP2モジュールのビルドをDocker上で行うことで、対象環境への影響を最小限に抑えています。
対象環境への反映
Docker環境でビルドした後
ngx_http_geoip2_module.so
を対象環境に配置しました。
sudo cp ngx_http_geoip2_module.so /usr/lib64/nginx/modules/
※配置先パスは環境により異なるため、nginx -V の --modules-path を基準に読み替えてください。
導入には、モジュール配置に加えて次も必要です。
-
libmaxminddbランタイムライブラリ - GeoIP DB(
GeoLite2-Country.mmdb) - Nginx設定(
load_module/geoip2/map)
Nginxビルド情報確認
nginx -V
確認ポイント
--with-compat
--modules-path=/usr/lib64/nginx/modules
--with-compat は、動的モジュールの互換性を確保するためのビルドオプションです。ただし、このオプションだけでモジュールの互換性が保証されるわけではありません。
実際には、Nginxバージョン・configureオプション・依存ライブラリの差分も併せて確認する必要があります。
依存ライブラリ
GeoIP2モジュールは libmaxminddb に依存します。
通常は以下のコマンドでインストールできます。
yum install libmaxminddb
今回は、既存環境への影響を抑えるため、yumリポジトリからの直接インストールを避け、RPMファイルを指定してローカルインストールしました。
curl -O https://vault.centos.org/7.9.2009/os/x86_64/Packages/libmaxminddb-1.2.0-6.el7.x86_64.rpm
sudo yum localinstall libmaxminddb-1.2.0-6.el7.x86_64.rpm
※RPMの直接導入は常に安全という意味ではありません。適用時は配布元・署名・依存関係を確認してください。
Nginx設定
モジュールロード
load_module modules/ngx_http_geoip2_module.so;
GeoIP設定
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
auto_reload 1h;
$geoip2_country_code country iso_code;
}
map $geoip2_country_code $block_non_jp {
default 1; # JP以外はブロック
JP 0; # JPのみ許可
}
この設定では、国コードが取得できない場合(空・不明)も default 1 に該当するため 403 になります。
アクセス制御例
location /restricted/ {
# 単純なreturnのため if を使用
if ($block_non_jp) {
return 403;
}
}
Nginx設定確認
sudo nginx -t
Nginx設定反映
sudo systemctl reload nginx
以上で 海外IPブロックの基本設定は完了です。
(GeoIPによるアクセス制御自体はここまでで動作します)
GeoIP DB自動更新
GeoLite2-Country の更新頻度は、MaxMind公開情報(2026-10時点)では
毎週 火曜・金曜 です。
更新の有無を定期的に確認するため、cronで毎日実行する設定としています。更新がない場合は、データベースの再ダウンロードは行われません。
0 5 * * * /usr/local/bin/geoipupdate -f /etc/GeoIP.conf >> /var/log/geoipupdate.log 2>&1
auto_reload により nginx 再起動は不要です。
⚠️ ハマったポイント
今回の作業では、古い環境ならではの問題にもいくつか遭遇しました。
CentOS 7のミラーが利用できない
CentOS 7は既にEOLとなっているため、通常のミラーが利用できず
そのままではパッケージインストールができない状態でした。
そのため、Docker検証環境では vaultリポジトリを利用する設定に変更しています。
既存のGeoIP関連パッケージに注意
古い環境では、過去のGeoIP関連パッケージが残っていることがあります。
例えば
- GeoIP.dat
- 古い geoipupdate
などが存在しており、現在の GeoIP2 / MaxMindDB とは形式が異なります。
そのため、今回の導入では
libmaxminddbGeoLite2-Country.mmdb
を使用する形に整理しました。
このようなケースがあるため、事前に確認しておくと安全です。
⚠️ 注意
GeoIP判定は 100%正確ではありません。
理由
- VPN
- Proxy
- AWS
- Cloudflare
- Carrier NAT
GeoIPによる判定だけでは十分とは言えないため、
環境によっては
GeoIP + WAF + rate limit
などを組み合わせて運用するケースもあります。
参考
まとめ
古い環境では
- Nginx本体を変更しない
- 開発ツールを入れない
- 変更範囲を最小化する
といった方針が重要になることがあります。
今回は、GeoIP2を動的モジュールとして追加し、
必要な依存ライブラリ・DB・設定を反映することで、
既存環境への影響を最小限に抑えて導入することができました。