Apache 2.4のアクセス制御をもうちょっとマジメに見てみた

nogajun
nogajun

_ おとといのエントリ「Apache 2.4にしたらコンテンツがForbiddenになった。そして直した」で「直した」と書いたけれど適当すぎたのでマジメに見なおしてみた。

参考

まず「Upgrading to 2.4 from 2.2 - Apache HTTP Server」を見ると2.2から2.4の変更で

2.2 configuration:
Order deny,allow
Deny from all

2.4 configuration:
Require all denied

になったり、

2.2 configuration:
Order allow,deny
Allow from all

2.4 configuration:
Require all granted

は分かったけれど、この場合はどういうことなんだろう。

2.2 configuration:
Order Deny,Allow
Deny from all
Allow from example.org

2.4 configuration:
Require host example.org

特定のIPアドレスやホストのアクセスを許可する事は分かったけれど、たとえばこういう感じで書いていた特定のIPアドレスやホストのアクセスを許可しない場合はどうしたらいいのだろう。

2.2 configuration:
Order Allow,Deny
Allow from all
Deny from example.org

Require Directiveを見ると、

Require [not] entity-name [entity-name] ...

否定は「not」とつければいいのかーということで、こういう風に書いてみた。

Require all granted
Require not host example.org

しかし、設定ファイルをチェックするとSyntax Errorが出る。

# apachectl configtest
AH00526: Syntax error on line 34 of /etc/apache2/sites-enabled/hoge.conf:
negative Require directive has no effect in <RequireAny> directive
Action 'configtest' failed.
The Apache error log may have more information.

どういう意味なのかな?と考えたけれど、<RequireAll|Any|None>のディレクティブを省略した場合は<RequireAny>ディレクティブで囲まれた状態とみなされるそう。で、Anyだとどれかの選択になるので all grantedとnotだとnotの意味がなくって条件が成り立たない。ということだそう。

ということで上のアクセス制限を<RequireAll>できちんと囲んで書くとこうなる。

<RequireAll>
    Require all granted
    Require not host example.org
</RequireAll>

拒否の判定をする<RequireNone>ディレクティブと組み合わせた書き方だとこんな感じ。<RequireNone>ディレクティブの中に書くときは、拒否の否定になるのでnotは不要。

<RequireAll>
    Require all granted
    <RequireNone>
        Require host example.org
    </RequireNone>
</RequireAll>

面倒だなーと思ったけど、振り返ってみると<RequireAny>がデフォルトということはマッチするものだけアクセスを許可、それ以外はアクセス拒否になるので、特定のホストやIPアドレスのみの許可だとこんな風に書ける。

Require host example.org

おおー!例に戻ってきた! なるほど、こういう意味だったのか!

まとめてみるとこんな感じ。

  • 特定のホストやIPのみのアクセスを許可する場合は、 RequireだけでOK。
  • 特定のホストやIPのアクセスを拒否する場合は、きちんと < RequireAll> ディレクティブを書いてから書く。
Require 意味
<RequireAny> このディレクティブの条件どれかにマッチすればアクセス許可。ディレクティブがない場合のデフォルト。
<RequireAll> ディレクティブの条件全てにマッチすれば真。否定の判定のみの場合は使えない。
<RequireNone> Anyとは逆にこのディレクティブの条件どれかにマッチすればアクセス拒否。