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 や中継で回避できます。公開ページ全体ではなく、ログイン画面や管理画面に絞って使うのが現実的です。
Nginx の GeoIP2 設定の流れ。MaxMind に登録、geoipupdate でデータベースを取得、モジュールを読み込み、geoip2 と map で判定、location で制限

旧 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 に登録してライセンスキーを作る

  1. MaxMind の GeoLite2 のページから無料アカウントを作ります。
  2. ログイン後、アカウントの管理画面で License Key を発行します(キーは発行時にしか表示されないので控えます)。
  3. 使うデータベースは、国だけなら 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 要素認証などと組み合わせる補助策として使います。

関連記事

参考: 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 の注意を追加)。この記事はワードプレス博士(ライトセンド株式会社)が運営しています。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲