2026年10月3日

2026年10月3日

WordPress管理画面のIP制限をIPv6に対応させる設定方法(Apache・Nginx)

WordPressの管理画面(wp-admin と wp-login.php)をIPアドレスで制限するとき、IPv4のアドレスだけを許可していると、IPv6で接続してきた自分自身が締め出されることがあります。結論から言うと、IPv6は「1個のアドレス」ではなく「/64 などのプレフィックス(範囲)」で許可し、IPv4とIPv6の両方を並べて書くのが基本です。この記事では、自分の接続元IPv6の調べ方、Apache・Nginxでの書き方、プロキシやCDNを挟む場合の注意、締め出されたときの戻し方までを順に説明します。

なぜIPv6だとIP制限がうまくいかないのか

IPv4の家庭回線では、ルーターに割り当てられた1個のグローバルアドレスを家の中の端末が共有するのが一般的でした。そのため「この1個を許可する」という書き方で済みました。

IPv6では事情が違います。プロバイダからは /64 や /56 といった「範囲(プレフィックス)」が割り当てられ、パソコンやスマートフォンは、その範囲の中から自分でアドレスを作ります。さらに多くのOSは、プライバシー保護のために一時アドレスを使い、一定時間ごとに下位64ビットを変えます。昨日許可したアドレスが、今日は別のアドレスになっているのはこのためです。

もう一つの落とし穴がデュアルスタックです。サーバーにAAAAレコード(IPv6)があり、自宅回線もIPv6に対応していると、ブラウザはIPv6を優先して接続することが多く、状況によってIPv4に切り替わることもあります。IPv4だけを許可していると「ときどき403になる」という分かりにくい症状になります。

自分の接続元IPv6とプレフィックスを調べる

最初に、管理画面へアクセスするときに実際に使われているアドレスを確認します。推測で書くと締め出しの原因になります。

  • サーバーのアクセスログで、自分が直前に開いたURLの行を探し、先頭のアドレスを見る
  • IPアドレス確認サービスで、IPv4とIPv6の両方を表示させる
  • ターミナルから curl -4 と curl -6 で、それぞれの経路で接続できるかを確かめる
# 自分の端末から、IPv6経路でログイン画面にアクセスできるか(応答コードだけ見る)
curl -6 -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-login.php

# 同じくIPv4経路
curl -4 -s -o /dev/null -w "%{http_code}\n" https://example.com/wp-login.php

ログに出たアドレスが 2001:db8:1234:5678:a1b2:c3d4:e5f6:7890 のような形なら、先頭4ブロックがプレフィックス(/64)にあたることが多いです。許可するのは 2001:db8:1234:5678::/64 のような範囲にします。ここでの 2001:db8:: は説明用に予約されたアドレスなので、実際の値に置き換えてください。

注意点として、プロバイダや契約によっては、ルーターの再起動や一定期間でプレフィックス自体が変わることがあります。固定のプレフィックスが得られない環境では、IP制限を唯一の対策にせず、2段階認証と組み合わせる方が運用しやすくなります。

Apache(.htaccess)で IPv4・IPv6 を許可する

Apache 2.4 では Require ip がIPv6とCIDR表記に対応しています。古い Order / Allow / Deny の書き方はApache 2.2系のもので、混ぜると意図しない結果になるため使いません。

作業の前に、既存の .htaccess をダウンロードしてバックアップしておきます。

wp-login.php を制限する

WordPressのルートにある .htaccess の、# BEGIN WordPress ブロックの外(上側)に追記します。ブロックの内側はWordPressが書き換えることがあるためです。

<Files "wp-login.php">
    # IPv4(固定IPなど)
    Require ip 203.0.113.10
    # IPv6 は /64 のプレフィックスで許可
    Require ip 2001:db8:1234:5678::/64
</Files>

Require を複数並べると「どれか1つに一致すれば許可」という扱いになります。

wp-admin ディレクトリを制限する

wp-admin フォルダの中に .htaccess を新しく作ります。ここで気をつけたいのが admin-ajax.php です。テーマやプラグインがサイトの表側(ログインしていない訪問者の画面)から呼び出すことがあり、これまで塞ぐとフォームや絞り込み検索などが動かなくなります。

Require ip 203.0.113.10
Require ip 2001:db8:1234:5678::/64

# 表側から呼ばれるファイルは誰でも通す
<Files "admin-ajax.php">
    Require all granted
</Files>

フォームプラグインなどが admin-post.php を使っている場合も同じように除外が要ります。設定後はサイトの表側のフォームや検索も動作を確認してください。

なお、レンタルサーバーによっては .htaccess での Require が許可されていない(AllowOverride の設定による)場合や、コントロールパネル側に管理画面のアクセス制限機能が用意されている場合があります。各社の機能や表記は変わるため、利用中のサーバーのマニュアルを確認してください(2026年10月現在)。

Nginx で IPv4・IPv6 を許可する

Nginxでは allow と deny を上から順に評価し、最初に一致したものが使われます。IPv6のCIDRもそのまま書けます。前提として、server ブロックに listen [::]:443 ssl; のようなIPv6の待ち受けがあり、DNSにAAAAレコードがあることを確認しておきます。

# ログイン画面
location = /wp-login.php {
    allow 203.0.113.10;
    allow 2001:db8:1234:5678::/64;
    deny  all;

    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;  # 環境に合わせて変更
}

# 表側からも呼ばれるため制限しない(完全一致の location が優先される)
location = /wp-admin/admin-ajax.php {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

# 管理画面ディレクトリ
location ^~ /wp-admin/ {
    allow 203.0.113.10;
    allow 2001:db8:1234:5678::/64;
    deny  all;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

location = /wp-login.php のような完全一致の書き方をすると、通常の location ~ \.php$ には処理が回らないため、PHPへ渡す設定をその中にも書く必要があります。ここを忘れると、許可したアドレスからもPHPのソースがダウンロードされたり、404になったりします。include するファイル名やソケットのパスはディストリビューションやPHPのバージョンで異なるので、既存の設定に合わせてください。

変更後は sudo nginx -t で文法を確かめてから sudo systemctl reload nginx で反映します。

CDNやリバースプロキシを挟んでいる場合

CloudflareなどのCDNや、ロードバランサーの後ろにWordPressがある場合、サーバーから見える接続元は利用者ではなくプロキシのアドレスになります。このまま利用者のIPv6で制限しても一致せず、全員が403になるか、逆にプロキシのアドレスを許可して全員を通してしまいます。

対策は、信頼できるプロキシのアドレスからの接続に限って、本当の接続元をヘッダーから取り出す設定です。Apacheでは mod_remoteip(RemoteIPHeader と RemoteIPTrustedProxy)、Nginxでは realip モジュール(set_real_ip_from と real_ip_header)を使います。Cloudflareの場合、プロキシのアドレス範囲にはIPv4とIPv6の両方があり、範囲は公式に公開されていて更新されることがあります。CDN側の機能(ファイアウォールルールなど)で管理画面のパスを制限する方法もあります。

また、サーバーがIPv4とIPv6を同じソケットで受けている構成では、IPv4の接続元が ::ffff:203.0.113.10 のような形でログに出ることがあります。ログの表記を見て、許可リストの書き方と合っているかを確認してください。

確認と、締め出されたときの戻し方

設定後は、次の順に確認します。

  1. 許可したIPv6経路(curl -6)とIPv4経路(curl -4)の両方で wp-login.php が200になる
  2. 許可していない回線(スマートフォンのモバイル回線など)からは403になる
  3. サイトの表側のフォーム、検索、カート機能などが今までどおり動く

締め出された場合に備えて、FTP・SFTP・SSH、またはサーバーのファイルマネージャーに入れることを事前に確かめておきます。戻し方は、追記した部分を削除するか、wp-admin に作った .htaccess を htaccess.off などに名前を変えるだけです。Nginxの場合は追記した location を元に戻して reload します。本番で試す前に、ステージング環境で同じ設定を確認しておくと安全です。

まとめ

  • IPv6はアドレスが変わるのが前提なので、1個のアドレスではなく /64 などのプレフィックスで許可する
  • デュアルスタックではIPv4とIPv6の両方で接続されうるため、両方を許可リストに並べる
  • Apacheは Require ip、Nginxは allow / deny でIPv6のCIDRをそのまま書ける
  • admin-ajax.php(必要なら admin-post.php)は表側から使われるので制限から外す
  • CDNやプロキシの後ろでは、本当の接続元を取り出す設定が先に要る
  • プレフィックスが変わる回線ではIP制限だけに頼らず、2段階認証と組み合わせ、FTPなどの戻し手段を確保しておく

お気軽にご相談ください

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