2026年7月30日
2026年7月30日
ApacheのIP制限・アクセス制御の設定方法(Require ipの書き方とWordPress管理画面の守り方)
Apache 2.4でIPアドレスによるアクセス制限をかけるには、Require ip を使います。古い記事でよく見る Order / Allow / Deny は互換用の書き方で、新しい書き方と混ぜると意図しない結果になりがちです。この記事では、Require の基本、WordPressの管理画面とログインページだけを特定のIPに限定する設定、CDNやロードバランサーの背後で正しいIPを判定する方法、締め出されたときの戻し方までを説明します。
Apache 2.4のアクセス制御の基本
Apache 2.4では、アクセスの許可・拒否を mod_authz_core と mod_authz_host が担当し、Require ディレクティブで条件を書きます。よく使う形は次のとおりです。
# すべて許可 / すべて拒否
Require all granted
Require all denied
# 1つのIP、範囲(CIDR)、IPv6
Require ip 203.0.113.10
Require ip 198.51.100.0/24
Require ip 2001:db8:1234::/48
# サーバー自身からのアクセス
Require local
Apacheの設定ファイルでは、ディレクティブと同じ行の後ろにコメント(#)を書けません。コメントは独立した行に書く、と覚えておくと構文エラーを避けられます。上の例は書き方の一覧で、実際にはこの中から必要なものを組み合わせて使います。
1つのセクションに Require を複数並べると、どれか1つに当てはまれば許可されます(暗黙の RequireAny)。「すべての条件を満たすときだけ許可」にしたい場合は <RequireAll> で囲みます。特定のIPだけを拒否する書き方は、この RequireAll と Require not の組み合わせです。
<RequireAll>
Require all granted
Require not ip 192.0.2.0/24
</RequireAll>
Require not は単独では使えず、RequireAll の中で「許可の条件」と組み合わせる必要があります。単独で書くと構文エラーになるのがよくあるつまずきです。
古い書き方からの移行
Order deny,allow / Deny from all / Allow from 203.0.113.10 は、mod_access_compat が有効なときだけ動く互換用の書き方です。同じ範囲に新旧の書き方が混ざると評価の順序が分かりにくくなるため、見つけたら次のように置き換えます。
| 旧(2.2系の書き方) | 新(2.4系の書き方) |
|---|---|
Order allow,deny + Allow from all |
Require all granted |
Order deny,allow + Deny from all |
Require all denied |
Deny from all + Allow from 203.0.113.10 |
Require ip 203.0.113.10 |
プラグインが .htaccess に古い書き方を出力していることもあるので、置き換える前にその行を書いたのがどのプラグインかを確認しておきます。
WordPressの管理画面とログインページをIPで制限する
不正ログインの試行を減らすうえで効果が大きいのが、wp-login.php と wp-admin へのアクセスを管理者のIPだけに絞る方法です。ただし wp-admin/admin-ajax.php は、問い合わせフォームや「いいね」ボタンなど、訪問者側の機能からも呼ばれます。ここまで拒否するとサイトの一部が動かなくなるため、例外として許可します。
VirtualHostに書く場合(推奨)
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example.com/public
# ログインページ
<Files "wp-login.php">
Require ip 203.0.113.10 198.51.100.0/24
</Files>
# 管理画面(admin-ajax.php だけは誰でも利用可)
<Directory "/var/www/example.com/public/wp-admin">
Require ip 203.0.113.10 198.51.100.0/24
<Files "admin-ajax.php">
Require all granted
</Files>
</Directory>
</VirtualHost>
<Files> は <Directory> より後に評価されるため、admin-ajax.php には内側の Require all granted が適用されます。プラグインによっては admin-post.php を訪問者向けのフォーム送信に使うものもあるので、フォームが動かなくなった場合はこのファイルも例外に加えるか検討します。
.htaccessに書く場合
共用サーバーなど設定ファイルを触れない環境では、.htaccess で同じことをします。Require を .htaccess で使うには、そのディレクトリに AllowOverride AuthConfig が許可されている必要があります。
# 公開ディレクトリ直下の .htaccess(# BEGIN WordPress の外に書く)
<Files "wp-login.php">
Require ip 203.0.113.10 198.51.100.0/24
</Files>
# wp-admin/.htaccess(新規作成)
Require ip 203.0.113.10 198.51.100.0/24
<Files "admin-ajax.php">
Require all granted
</Files>
ルートの .htaccess の # BEGIN WordPress から # END WordPress までの範囲は、パーマリンクの保存時に書き直されます。独自の設定はその範囲の外に置いてください。
IPv6を忘れない
サーバーとプロバイダーの両方がIPv6に対応していると、ブラウザはIPv6で接続することがあります。IPv4だけを許可していると、自宅や会社から管理画面が403になる原因になります。確認用のサービスなどで自分のIPv6アドレスを調べ、必要なら Require ip 2001:db8:1234::/48 のようにプレフィックスで許可に加えます。
CDN・ロードバランサーの背後では mod_remoteip を使う
Cloudflareなどのリバースプロキシ型CDNやロードバランサーを経由していると、Apacheから見える接続元(REMOTE_ADDR)はプロキシのIPになります。この状態で Require ip を書くと、全員が拒否されるか、プロキシ経由の全員が許可されるかのどちらかになり、制限として機能しません。
mod_remoteip を有効にすると、信頼できるプロキシから届いたヘッダーの値を本来の接続元IPとして扱えます。Require ip の判定やアクセスログにも、置き換え後のIPが使われます。
# Debian/Ubuntu: sudo a2enmod remoteip
RemoteIPHeader X-Forwarded-For
# 自社のロードバランサーなど、信頼するプロキシのIP範囲(例)
RemoteIPTrustedProxy 10.0.0.0/8
# CDNの場合は事業者が公開しているIP範囲を指定する
RemoteIPTrustedProxy を指定せずにヘッダーを信用すると、攻撃者が X-Forwarded-For に許可済みIPを書き込むだけで制限をすり抜けられます。信頼するのは自分が管理しているプロキシと、CDN事業者が公開している範囲だけにしてください。CDNによっては X-Forwarded-For ではなく独自のヘッダーで接続元を渡すので、事業者のドキュメントでヘッダー名とIP範囲を確認します。IP範囲は変わることがあるため、定期的な見直しも必要です(2026年10月現在)。
IPが固定できない場合の選択肢
自宅回線やモバイル回線のようにIPが変わる環境では、IP制限だけだと自分も締め出されます。その場合は、IPが一致するか、Basic認証に成功するかのどちらかで通す構成にできます。
<Files "wp-login.php">
AuthType Basic
AuthName "Restricted"
AuthUserFile /etc/apache2/.htpasswd-wp
<RequireAny>
Require ip 203.0.113.10
Require valid-user
</RequireAny>
</Files>
パスワードファイルは sudo htpasswd -c /etc/apache2/.htpasswd-wp 管理者名 で作成し、公開ディレクトリの外に置きます。Basic認証の情報はHTTPSでなければ平文で流れるため、常時HTTPSのサイトで使ってください。
設定後の確認と、締め出されたときの戻し方
反映前に構文チェックを行います。
sudo apachectl configtest && sudo systemctl reload apache2
# 許可していない回線(スマートフォンのテザリングなど)から
curl -sI https://example.com/wp-login.php | head -n 1 # 403 になればOK
curl -sI https://example.com/wp-admin/admin-ajax.php | head -n 1 # 403 にならないこと
拒否されたアクセスは、エラーログに「client denied by server configuration」という行で記録されます。自分が拒否されている場合は、この行に出ている接続元IPを見ると、許可リストとどこが違うのか(IPv6だった、プロキシのIPだった等)が分かります。
万一自分が締め出された場合は、SSHかFTP(ファイルマネージャー)で対象の設定を外します。
- VirtualHostに書いた場合: 該当ブロックをコメントアウトし、configtest のあと reload。
- .htaccess に書いた場合:
wp-admin/.htaccessの名前を変える、またはルートの .htaccess から追記部分を削除する。
作業前に元のファイルをコピーしておけば、戻す作業は数分で済みます。IP制限はあくまで入口を絞る対策なので、強いパスワードや二段階認証、ログイン試行回数の制限と組み合わせて使ってください。
まとめ
- Apache 2.4では
Require ip/Require all granted|deniedを使い、Order/Allow/Denyからは移行する。 - 拒否リストは
<RequireAll>の中でRequire all grantedとRequire not ipを組み合わせる。 - WordPressは
wp-login.phpとwp-adminを制限し、admin-ajax.php(必要に応じてadmin-post.php)は例外にする。IPv6の許可も忘れない。 - CDNやロードバランサーの背後では
mod_remoteipとRemoteIPTrustedProxyで本来の接続元を判定する。 - 締め出しに備え、元の設定のコピーとSSH/FTPでの戻し方を用意してから反映する。