2016年8月18日木曜日

Apache2.4ではまったのでメモ

Apache2.4ではまったのでメモ

検証環境はCentOS7+Apache2.4です。

Apache2.4のアクセス権限回りは、従来のOrder Deny,Allow形式から、
Require All grantedのような形式に変わりました。

そんな中でApache2.4のアクセス権限回りを設定していて、不可解な現象に会いました。

自分はDirectoryディレクティブとLocationディレクティブの違いは、
サーバ内のリアルパスでの制御か、URIの仮想パスかの違い程度としか理解していなかったのですが、
設定する上では注意が必要なようです。参考


では検証していきます。
まずはサクッとバーチャルホストの設定をします。

<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Location />
    Require all granted
  </Location>
</VirtualHost>

まぁ普通に見れます。


ではここで、アクセス制限をかけます。

<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Location />
    Require all granted
  </Location>
  #管理ページにアクセス制限
  <Location /admin>
    Require all denied
  </Location>
</VirtualHost>

かかりました。

ではここで、特定のファイルだけアクセス禁止にしたいと思います。
FilesMatchディレクティブはLocationディレクティブの中では使えないようなので、
Directoryディレクティブを使用します。

<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Location />
    Require all granted
  </Location>
  #管理ページにアクセス制限
  <Location /admin>
    Require all denied
  </Location>
  #ブログのReadme.htmlはアクセス拒否
  #それ以外は参照可能にする。
  <Directory /var/www/virtual/blog>
    <FilesMatch "^readme\.html">
      Require all denied
    </FilesMatch>
  </Directory>
</VirtualHost>


なんと見えてしまいました。

設定を間違えたのでしょうか?確認のため、旧来の書き方で書いてみましょう。

<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Location />
    Require all granted
  </Location>
  #管理ページにアクセス制限
  <Location /admin>
    Require all denied
  </Location>
  #ブログのReadme.htmlはアクセス拒否
  #それ以外は参照可能にする。
  <Directory /var/www/virtual/blog>
    <FilesMatch "^readme\.html">
      #Require all denied
      Order Deny,Allow
      Deny from All
    </FilesMatch>
  </Directory>
</VirtualHost>

ちゃんと弾かれるので、あっているようです。


これずいぶん悩んだのですが、どうも最初に設定している
<Location />
の設定が優先されるようです。
Apacheのドキュメントによると、
<Location> セクションは、 <Directory> セクションと .htaccess の読み込みの後、 <Files> セクションを 適用した後に、設定ファイルに現れた順に処理されます。
とありますので、優先順位としては
Directory -> .htaccess -> Files -> Location
のようです。
しかし旧来の設定では有効なのはよくわかりませんが・・・

試しにLocationのほうを旧設定にしてみます。
<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Location />
    #Require all granted
    Order Allow,Deny
    Allow from All
  </Location>
  #管理ページにアクセス制限
  <Location /admin>
    Require all denied
  </Location>
  #ブログのReadme.htmlはアクセス拒否
  #それ以外は参照可能にする。
  <Directory /var/www/virtual/blog>
    <FilesMatch "^readme\.html">
      Require all denied
      #Order Deny,Allow
      #Deny from All
    </FilesMatch>
  </Directory>
</VirtualHost>

ちゃんと動きます。


ファイル名で識別できています。

しかし、動くとはいえ、新旧設定が混在するのは気持ち悪い。
ということでいろいろ試した結果、
Location設定をDirectoryにすれば動作するようです。

<VirtualHost *:80>
  ServerName localhost.localdomain
  DocumentRoot /var/www/virtual
  <Directory />
    Require all granted
  </Directory>
  #管理ページにアクセス制限
  <Location /admin>
    Require all denied
  </Location>
  #ブログのReadme.htmlはアクセス拒否
  #それ以外は参照可能にする。
  <Directory /var/www/virtual/blog>
    <FilesMatch "^readme\.html">
      Require all denied
      #Order Deny,Allow
      #Deny from All
    </FilesMatch>
  </Directory>
</VirtualHost>
なお、最初のLocation /にアクセス許可与えている奴ですが、
これをすると、FilesMatchでRequire all deniedが有効にならないので・・・

むむむむ・・・・・