Apache2.4で特定のURLだけアクセス制限の対象から除外する
一生覚えられる気がしないので自分のためにメモします。
やりたかったこと
- サイト全体についてIP指定許可でアクセス制限
- ただし、特定のURL(例としてここでは
/public*
とする)だけは制限なしでアクセス可能に - サイトはフレームワークを使って実装されていて、
/index.php
がフロントコントローラーである (←ここポイント)
/index.php
がフロントコントローラーである」とは
「<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* index.php [L]
</IfModule>
こういう .htaccess
が設置されている状態です。
パターン1
❌最初に試したけど期待どおり動作しなかった例
<Location />
Require ip xxx.xxx.xxx.xxx
</Location>
<Location /public>
Require all granted
</Location>
これで行けるだろうと思ったら、すべてのURLが403になってしまいました。
パターン2
❌次に試したけど期待どおり動作しなかった例
<Location />
SetEnvIf REQUEST_URI "/public" public
<RequireAny>
Require env public
Require ip xxx.xxx.xxx.xxx
</RequireAny>
</Location>
こんな方法も試してみましたが、
-
/index.php/public*
はアクセス可能 -
/public*
はアクセス不可
となってしまいました。
パターン3
⭕最終的に期待どおり動作した例
<Location />
Require ip xxx.xxx.xxx.xxx
</Location>
<Location /public>
Require all granted
</Location>
<Location ~ ^/index.php$>
Require all granted
</Location>
これで(ほぼ)期待どおり動作しました。
つまり、フロントコントローラーである/index.php
にアクセス制限が掛かってしまっていたのが原因だった ということですね。
なので、パターン2の方法でも、
<Location />
SetEnvIf REQUEST_URI "/public" public
<RequireAny>
Require env public
Require ip xxx.xxx.xxx.xxx
</RequireAny>
</Location>
<Location ~ ^/index.php$>
Require all granted
</Location>
や
<Location />
SetEnvIf REQUEST_URI "/public" public
SetEnvIf REQUEST_URI "^/index.php$" public
<RequireAny>
Require env public
Require ip xxx.xxx.xxx.xxx
</RequireAny>
</Location>
とすれば、同様に動作します。
ちなみに
この方法だと、/index.php
へのアクセスだけは無用に許可されてしまいます 😓
これを回避する方法をご存知の方いらっしゃいましたら教えていただけると嬉しいです。。(リバースプロキシで別のvhostに飛ばす、とか??)
再現用Docker環境
(せっかく作ったので)実験に使ったDocker環境を上げてあります。
https://github.com/ttskch/docker-apache2.4-test
その他雑多なメモ
<Location>
は最後にマッチしたものが適用される
<Location />
Require ip xxx.xxx.xxx.xxx
</Location>
<Location /public>
Require all granted
</Location>
<Location ~ ^/index.php$>
Require all granted
</Location>
は期待どおりに動作しましたが、
<Location /public>
Require all granted
</Location>
<Location ~ ^/index.php$>
Require all granted
</Location>
<Location />
Require ip xxx.xxx.xxx.xxx
</Location>
だと(<Location />
を最後に移動)すべてのURLが403になりました。
REQUEST_URI
にはクエリパラメータは含まれない
ので、要注意です。
https://httpd.apache.org/docs/2.4/ja/mod/mod_rewrite.html
REQUEST_URI
The path component of the requested URI, such as "/index.html". This notably excludes the query string which is available as its own variable named QUERY_STRING.
REQUEST_URI
の中身を知りたいときは
Apacheが REQUEST_URI
をどう認識しているのか知りたい!というときは、環境変数 REQUEST_URI
を出力するLogFormatを作って、CustomLogとして出力するとよいです。
LogFormat "%{REQUEST_URI}e" request_uri
CustomLog ${APACHE_LOG_DIR}/hoge.request_uri.log request_uri
Discussion