Apache 2.4 の Require ディレクティブのマージとか

Apache 2.4 の `Require` ディレクティブのマージについてのメモ（＋α）が出てきたので置いときます。

- CentOS 7.1.1503
- Apache 2.4.6

## デフォルト

Require はデフォルトは許可です。

ただし CentOS 7 だと、最初から httpd.conf に次のように設定されています。

```
<Directory />
    Require all denied
</Directory>

<Directory "/var/www">
    Require all granted
</Directory>

<Directory "/var/www/html">
    Require all granted
</Directory>

<Files ".ht*">
    Require all denied
</Files>

<Directory "/var/www/cgi-bin">
    Require all granted
</Directory>
```

## セクションのマージ

Apache では複数の `<Directory>` などのセクションに書かれたディレクティブは、下記のようにマージされます。

- [How the sections are merged - Apache HTTP Server Version 2.4][section-merge-en]
- [セクションのマージ方法 - Apache HTTP サーバ バージョン 2.4][section-merge-ja]

[section-merge-en]: http://httpd.apache.org/docs/2.4/en/sections.html#merging
[section-merge-ja]: http://httpd.apache.org/docs/2.4/ja/sections.html#mergin

ただし、`Require` ディレクティブは複数のセクションに記述されていてもマージされません（後述の通りマージさせることもできる）。
下記の例だと `/var/www/html` には、セクションの優先度が高い `Require ip 10.` のみ適用されます。

```
<Directory /var/www>
    Require ip 192.168.
</Directory>
<Directory /var/www/html>
    Require ip 10.
</Directory>
```

`Require ip` と `Require method` のように条件が異なっていてもマージされません。
下記の例だと、`/var/www/html` には任意の宛先からの POST メソッドだけが許可されます。

```
<Directory /var/www>
    Require ip 192.168.
</Directory>
<Directory /var/www/html>
    Require method POST
</Directory>
```

もし、`<Directory /var/www/html>` に `Require` が無ければ、（優先度が）直前のセクションの設定がそのまま適用されます。
下記の例だと `/var/www/html` にも `Require ip 192.168.` が適用されます。

```
<Directory /var/www>
    Require ip 192.168.
</Directory>
<Directory /var/www/html>
    Options none
</Directory>
```

なお、同じディレクトリでもセクションが異なれば別セクションなので `Require` はマージされません。

```
<Directory /var/www/html>
    Require ip 192.168.
</Directory>
<Directory /var/www/html>
    Require ip 10.
</Directory>
```

# マージを有効にする

`AuthMerging` で複数セクションの `Require` のマージを有効にすることができます。

`AuthMerging Or` なら、（優先度が）直前のセクションと OR でマージされます。
下記の例では `127.` と `10.` の両方が許可されます。

```
<Directory /var/www>
    Require ip 127.
</Directory>
<Directory /var/www/html>
    AuthMerging Or
    Require ip 10.
</Directory>
```

`AuthMerging And` なら、（優先度が）直前のセクションと And でマージされます。
下記の例では `10.` からの GET のみが許可されます。

```
<Directory /var/www>
    Require method GET
</Directory>
<Directory /var/www/html>
    AuthMerging And
    Require ip 10.
</Directory>
```

デフォルトは `AuthMerging Off` なので、前述の通りマージされません。

なお、`AuthMerging` はマージされないので、下記の例だと `/var/www/html` には `Require ip 10.` しか適用されません。

```
<Directory /var>
    Require ip 192.168.
</Directory>

<Directory /var/www>
    AuthMerging Or
    Require ip 127.
</Directory>

<Directory /var/www/html>
    Require ip 10.
</Directory>
```

# 暗黙の `<RequireAny>`

下記の２つは同じです。つまり、`<Directory>` などのセクションの直下に `Require` を記述すると、暗黙的に `<RequireAny>` で囲われます。

```
<Directory /var/www/html>
    Require ip 127.
    Require ip 10.
</Directory>
```

```
<Directory /var/www/html>
    <RequireAny>
        Require ip 127.
        Require ip 10.
    </RequireAny>
</Directory>
```

# 特定のアドレスだけ拒否

次のように `<RequireAll>` を使います。下記の例では `127.0.0.1` が拒否されます。

```
<Directory /var/www/html>
    <RequireAll>
        Require all granted
        Require not ip 127.0.0.1
    </RequireAll>
</Directory>
```

これは次のように `<RequireNone>` を使っても同じです。

```
<Directory /var/www/html>
    <RequireAll>
        Require all granted
        <RequireNone>
            Require ip 127.0.0.1
        </RequireNone>
    </RequireAll>
</Directory>
```

なお、`<RequireAll>` に `Require all granted` が無いとエラーになります。

```
AH01624: <RequireAll> directive contains only negative authorization directives
```

`<RequireAll>` の中身を not だけにすることはできないようです（なぜ？）。