2026年5月21日
2026年5月21日
Nginx の GeoIP2 で国別にアクセスを制限する方法|ngx_http_geoip2_module・GeoLite2 の更新・WordPress 管理画面の国制限
Nginx で国別にアクセスを制限するには、GeoIP2 用のモジュール(ngx_http_geoip2_module)と MaxMind の GeoLite2 データベースを使い、geoip2 ブロックで国コードを変数に入れ、map で許可・拒否を決めるのが 2026年11月現在の手順です。古い記事にある「GeoLite の .dat を wget する」手順は、データの配布が終わっているため動きません。
結論を先にまとめます。
- 旧
ngx_http_geoip_module(GeoIP Legacy)は、MaxMind が旧形式のデータ配布を終えているため新規には使えません。GeoIP2(.mmdb形式)に移ります。 - GeoLite2 は無料ですが、MaxMind のアカウント登録とライセンスキーが必要で、ダウンロードと更新は
geoipupdateで行います。 - Nginx 側は
geoip2ブロックで$geoip2_country_codeのような変数を作り、mapでallow/denyに相当する 0 / 1 を決め、locationでreturn 403します。 - Cloudflare などの CDN を通しているサイトでは、先に
real_ip_headerで閲覧者の実 IP を復元しないと、すべて CDN の国として判定されます。 - 国による制限は「攻撃を減らす補助」であり、VPN や中継で回避できます。公開ページ全体ではなく、ログイン画面や管理画面に絞って使うのが現実的です。
旧 geoip と GeoIP2 の違い
| 項目 | ngx_http_geoip_module(旧) | ngx_http_geoip2_module(GeoIP2) |
|---|---|---|
| データ形式 | GeoIP Legacy(.dat) |
GeoIP2(.mmdb) |
| 無料データの提供 | 終了(2019 年に配布終了) | GeoLite2(アカウント登録とライセンスキーが必要) |
| 必要なライブラリ | libGeoIP | libmaxminddb |
| モジュールの入手 | Nginx 標準(--with-http_geoip_module) |
第三者モジュール leev/ngx_http_geoip2_module。Debian / Ubuntu はパッケージあり |
| 変数 | $geoip_country_code など固定 |
geoip2 ブロックで自分で名前を付ける |
既存の設定で geoip_country を使っている場合、データベースの更新が止まっているので判定が古くなっています。この機会に GeoIP2 へ移してください。
手順 1: MaxMind に登録してライセンスキーを作る
- MaxMind の GeoLite2 のページから無料アカウントを作ります。
- ログイン後、アカウントの管理画面で License Key を発行します(キーは発行時にしか表示されないので控えます)。
- 使うデータベースは、国だけなら
GeoLite2-Country、都市まで必要ならGeoLite2-Cityです。国別制限なら Country で足ります。
利用条件(GeoLite2 End User License Agreement)に、データの再配布や表示に関する決まりがあります。社内のサーバーで判定に使うだけなら通常の範囲ですが、条件は登録時に確認してください。
手順 2: geoipupdate でデータベースを取得・更新する
GeoLite2 は定期的に更新されるので、手でダウンロードせず geoipupdate を使います(geoipupdate のドキュメント)。
# Debian / Ubuntu
sudo apt install geoipupdate
# RHEL 系(AlmaLinux / Rocky Linux)は EPEL から
sudo dnf install geoipupdate
設定ファイル /etc/GeoIP.conf にアカウント ID とライセンスキーを書きます。
AccountID 123456
LicenseKey ここに発行したキー
EditionIDs GeoLite2-Country
# 保存先は配布版の既定(Debian / Ubuntu は /var/lib/GeoIP、ほかは /usr/share/GeoIP が多い)。
# 変えるときは DatabaseDirectory /var/lib/GeoIP
sudo geoipupdate -v
ls -l /var/lib/GeoIP/ # GeoLite2-Country.mmdb があれば成功
パッケージ版の geoipupdate は、systemd のタイマーか cron で定期実行する設定が入っています(systemctl list-timers | grep geoip で確認)。無ければ週 1 回程度の cron を追加します。
手順 3: Nginx に GeoIP2 モジュールを入れる
Debian / Ubuntu(apt の Nginx)
sudo apt install libnginx-mod-http-geoip2
ls /etc/nginx/modules-enabled/ # 50-mod-http-geoip2.conf が置かれる
nginx -t
nginx.org のパッケージやソースビルドの Nginx
libmaxminddb を入れたうえで、動いている Nginx と同じ版のソースから動的モジュールをビルドします。
sudo apt install libmaxminddb-dev # RHEL 系は libmaxminddb-devel
cd /usr/local/src
git clone https://github.com/leev/ngx_http_geoip2_module
curl -LO https://nginx.org/download/nginx-1.26.3.tar.gz # 版は nginx -v に合わせる
tar xzf nginx-1.26.3.tar.gz && cd nginx-1.26.3
./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module
make modules
sudo cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
nginx.conf の先頭で読み込みます(パッケージ版では自動で置かれます)。
load_module modules/ngx_http_geoip2_module.so;
手順 4: 国コードを変数にして許可・拒否を決める
http ブロックに書きます。geoip2 ブロックで国コードを変数に入れ、map で許可する国を 1、それ以外を 0 にします。
http {
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_country_code country iso_code;
}
# 管理画面を許可する国(ISO 3166-1 の 2 文字コード)
map $geoip2_country_code $admin_allowed {
default 0;
JP 1;
"" 1; # 判定できない(プライベート IP など)は許可。拒否したいなら 0
}
}
auto_reload は、geoipupdate が置き換えたデータベースを再起動なしで読み直す間隔です。
手順 5: WordPress のログイン画面と管理画面だけを制限する
公開ページは制限せず、wp-login.php と /wp-admin/ だけを国で絞る例です。server ブロックに書きます。
server {
# ... 既存の設定 ...
location = /wp-login.php {
if ($admin_allowed = 0) { return 403; }
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ^~ /wp-admin/ {
if ($admin_allowed = 0) { return 403; }
# admin-ajax.php を外部プラグインが使う場合は、別 location で許可する
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}
}
if と return の組み合わせは Nginx が安全に扱える形です。/wp-admin/admin-ajax.php は公開ページの機能(フォームや無限スクロールなど)が未ログインで呼ぶことがあるので、制限から外すかどうかをサイトの機能に合わせて決めます。
反映と確認:
sudo nginx -t && sudo systemctl reload nginx
# 自分の国から: 200 か 302 が返る
curl -sI https://example.com/wp-login.php | head -1
# 判定の確認(ログに国コードを出す例)
# log_format geo '$remote_addr $geoip2_country_code "$request" $status';
海外からの見え方を確かめるには、海外拠点の VPN か、国外の監視サービスから wp-login.php にアクセスして 403 になることを見ます。
CDN(Cloudflare など)を通している場合
CDN 経由では $remote_addr が CDN の IP になり、全員が CDN の国として判定されます。先に ngx_http_realip_module で閲覧者の実 IP を復元します(realip モジュール)。
# Cloudflare の例。IP 一覧は Cloudflare 公式の IP Ranges から定期的に更新する
set_real_ip_from 173.245.48.0/20;
# ... Cloudflare の全レンジを列挙 ...
real_ip_header CF-Connecting-IP;
geoip2 は既定で $remote_addr を見るので、realip で置き換わった後の実 IP で判定されます。Cloudflare 自体にも国別のアクセス制御(WAF のカスタムルール)があるので、Cloudflare を使っているなら Nginx ではなく Cloudflare 側で制限する方が設定は簡単です。WordPress に Cloudflare を設定するも参照してください。
国別制限の限界
- GeoIP の判定は IP アドレスの登録情報に基づく推定で、VPN・プロキシ・海外のクラウドからの中継で回避できます。
- モバイル回線や企業ネットワークでは、実際の所在地と別の国に判定されることがあります。海外出張中の管理者が締め出される運用上の問題も起きます。
- したがって国別制限は、ログイン試行の総当たりを減らす補助として、2 要素認証やログイン回数の制限、Basic 認証による wp-admin の保護と組み合わせて使います。
よくある質問
Nginx の geoip モジュールと geoip2 モジュールはどう違いますか
旧 geoip モジュールは GeoIP Legacy 形式(.dat)のデータを読みますが、MaxMind はこの形式の配布を終えています。geoip2 モジュール(ngx_http_geoip2_module)は現在の .mmdb 形式を読み、GeoLite2 の無料データが使えます。新規の設定は geoip2 にします。
GeoLite2 は無料ですか。登録は必要ですか
無料ですが、MaxMind のアカウント登録とライセンスキーの発行が必要です。ダウンロードと定期更新は geoipupdate で行います。キーを使わず直接ダウンロードする古い手順は動きません。
国で制限すれば WordPress の不正ログインは防げますか
総当たりの試行を減らす効果はありますが、VPN や海外のサーバーからの中継で回避できるため、防げるとは言えません。ログイン回数の制限、2 要素認証、Basic 認証などと組み合わせてください。
Cloudflare を使っていると全員が同じ国になります
CDN 経由では接続元が CDN の IP になるためです。set_real_ip_from と real_ip_header CF-Connecting-IP で実 IP を復元してから判定してください。Cloudflare の WAF で国別に制限する方法もあります。
GeoLite2-City を使えば都市まで制限できますか
都市や地域のコードも変数に入れられますが、都市レベルの精度は国より低く、誤判定で正当な利用者を締め出しやすくなります。アクセス制御には国レベルまでにとどめるのが無難です。
まとめ
- 現在の Nginx の国別制限は GeoIP2(ngx_http_geoip2_module + GeoLite2
.mmdb)で行い、データはgeoipupdateで更新します。 geoip2で国コードを変数に入れ、mapで許可・拒否を決め、wp-login.phpと/wp-admin/のlocationでreturn 403します。- CDN 経由なら先に実 IP を復元し、国別制限は 2 要素認証などと組み合わせる補助策として使います。
関連記事
- WordPress の REST API へのアクセスを制限する方法
- htpasswd で Apache の Basic 認証パスワードを作成する方法|wp-admin の保護
- WordPress に Cloudflare を設定する完全ガイド
参考: ngx_http_geoip2_module(GitHub)、MaxMind GeoLite2 Free Geolocation Data、MaxMind – Updating Databases(geoipupdate)、Nginx ngx_http_realip_module
更新履歴: 2026-11-09 全面改訂(配布終了の旧 GeoLite 手順を GeoIP2・geoipupdate の手順に置き換え、WordPress 管理画面の制限例と CDN の注意を追加)。この記事はワードプレス博士(ライトセンド株式会社)が運営しています。