Apache 2.4 を含むバージョンの XAMPP に変更して、ローカルネットワーク上のコンピュータからアクセスできなくなった原因を探った

**Access forbidden!**

**要求されたディレクトリへのアクセス権限がありません。 インデックスドキュメントが存在しないか、 ディレクトリの読み込みが許可されていません。**

---
XAMPP のバージョンアップ後、localhost （サーバー機）以外のローカルネットワーク上のコンピュータやスマホからアクセスできなくなりました。面倒だったので、長らく古いバージョンを使っていましたが、そろそろ...というわけで、

最初はファイヤーウォールを疑っていたが全然改善せず、
上のメッセージを `"C:\xampp\apache"` フォルダで grep 検索したところ、
`"C:\xampp\apache\error\HTTP_FORBIDDEN.html.var"`
に含まれていることがわかりました。

ということは、どうやら XAMPP からのエラーメッセージだろう...
つまり.....Apache からメッセージが送られている！
＝ファイヤーウォールではなく、Apache の設定？.....

あれこれ情報を探し回った挙げ句、何時間も費やした愚行をくり返さないためにメモを残します。

この作業の結果、ネットワーク上の**パソコンとスマホ１台からアクセス成功！**
~~（他のスマホ２台はアクセス失敗だが、こちらは別の問題があるのかな、と）~~
**全てアクセスできるようになりました！**

#[１． Apache 2.4の設定（conf系）](https://httpd.apache.org/docs/2.4/ja/upgrading.html#run-time "run-time")

>**認証・許可設定のところで重大な変更がいくつかあったため、Apache 2.2向けの設定ファイルを 2.4 に転用する前に、変更が必要になる場合がある。**

（Apache 2.4 のドキュメントには、こう書かれていました！）

　※ ここでいう「設定ファイル」とは、「httpd.conf」系のファイルや「.htaccess」などのこと。つまり、「**ノーチェックで転用するな**」ということ。

　最初の失敗は、ここでした。2.2 用の設定を、ノーチェックで 2.4 に転用していました。

#[２．Order,Deny,Allow型と、Require型の混在](https://httpd.apache.org/docs/2.4/ja/upgrading.html#access "access")

mod_access_compat モジュールが従来の `Order,Deny,Allow`型のアクセスコントロールを引き続き可能にするが、2.4 で導入された mod_authz_core モジュール等で提供される「 `Require`型と混在」させることは、予期せぬ動作を引き起こす恐れがあるので、技術的には可能ではあるものの、おすすめできないらしい。

Why httpd denies access ..... Because mod_access_compat directives take precedence over the mod_authz_host one in this configuration merge scenario.
**mod_access_compat モジュールのディレクティブ（`Order,Deny,Allow`）は、mod_authz_host のそれ(`Require`)に優先する）**

　第２の失敗はここでした。ネットの情報を見て、やみくもに`Require all granted`を付け足しても解決しなかったのはそのせいです。しかし、どこにも`Order`,`Deny`,`Allow`が見当たらないのです！（これは後で解決します。）

参考までに、`Require` ディレクティブの例を置いておきます。
[mod_authz_core モジュールによる、Require ディレクティブの用法](https://httpd.apache.org/docs/2.4/ja/mod/mod_authz_core.html#require)
[mod_authz_host モジュールによる、Require ディレクティブの用法](https://httpd.apache.org/docs/2.4/en/mod/mod_authz_host.html#requiredirectives)

失敗例も書いておきます。

```ruby:ダメな例
Require local ip 192.168
```

```ruby:動作した例
Require local
Require ip 192.168
```

#[３． .htaccess ファイルが読み込まれない場合がある](https://httpd.apache.org/docs/2.4/ja/upgrading.html#commonproblems)

 .htaccess による設定変更を可能にする `AllowOverride` ディレクティブの既定値（デフォルト）が、2.4（正確には2.3.9以降） では「None」に変更されたので、適切な `<Directory>` セクション内で上書きしてやる必要がある。

　※ XAMPP では `<Directory "C:/xampp/htdocs">` セクション内で、
「`AllowOverride All`」と上書きされているようだが、念のため、各バージョンごとに再確認する必要があろう。

#４．ノーチェックで転用された古い httpd.conf 系ファイルや、古い .htaccess ファイル、あるいはノーチェックで上書きされたそれらの設定が悪さをしている場合がある

　第３の失敗は、ここでした。Apache 2.2 用の古い .htaccess ファイルを `"C:/xampp/htdocs"` にノーチェックでコピーしていました。

　しかも、ここに「`Order` 系のディレクティブ」が書き込まれていたため、そのサブディレクトリに `Require all granted` を書いても、親ディレクトリである `"C:/xampp/htdocs"` からの「`Order`」系の子ディレクトリへの継承が優先されていたのです！

　関連するディレクティブの注意点を書いておきます。

##4.1. `AllowOverride` ディレクティブを置くセクション
`AllowOverride` ディレクティブによって、アクセスコントロールを .htaccess ファイルで上書きできるようにできるが、この `AllowOverride` ディレクティブは、各`<Directory>` セクション内でしか設定することができないので、`<DirectoryMatch>`, `<Location>`, `<Files>` などのセクションでは無効になってしまう。

##4.2. `AllowOverride` ディレクティブの設定値
`AllowOverride` ディレクティブの設定値によっては、.htaccess ファイル内で使えるディレクティブを限定することができる。
-[`AllowOverride AuthConfig` … `Require` 系のディレクティブを .htaccess ファイルで使えるようにできる。](https://httpd.apache.org/docs/2.4/en/mod/overrides.html#override-authconfig)
-[`AllowOverride Limit` 　　 … `Order`, `Deny`, `Allow` ディレクティブを .htaccess ファイルで使えるようにできる。](https://httpd.apache.org/docs/2.4/en/mod/overrides.html#override-limit)

##4.3. `AuthMerging` ディレクティブによる統合[^1]
`AuthMerging` ディレクティブにより、上位セクションから継承された許可設定と、そのセクションでの新たな許可設定とを、「一時的に統合」させることができる。（デフォルトは、`AuthMerging Off` = 統合させない＝上書きする）
(https://httpd.apache.org/docs/2.4/ja/mod/mod_authz_core.html#authmerging)
-`AuthMerging And` … 上位セクションから継承された許可設定と、そのセクションでの新たな許可設定とを、あたかも `<RequireAll> ～ </RequireAll>` で囲ったようになる。
-`AuthMerging Or` … 上位セクションから継承された許可設定と、そのセクションでの新たな許可設定とを、あたかも `<RequireAny> ～ </RequireAny>` で囲ったようになる。

※
[`<RequireAll> ～ </RequireAll>`](https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#RequireAll) 　…　全てが満たされれば「ＯＫ」
[`<RequireAny> ～ </RequireAny>`](https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#RequireAny) 　…　いずれか１つが満たされれば「ＯＫ」
[`<RequireNone> ～ </RequireNone>`](https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#RequireNone) …　いずれか１つが満たされれば「ＮＧ」＝全てがＮＧなら「ＯＫ」

なお、これらで囲われていないのに複数の `Require` ディレクティブが１つのセクションで使われた場合、暗黙のうちに、`<RequireAny>` の中に入れられる。（いずれか１つが満たされれば「ＯＫ」となる。）

> When multiple Require directives are used in a single configuration section and are not contained in another authorization directive like `<RequireAll>`, they are implicitly contained within a `<RequireAny>` directive. （https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#Require）


下記の例（Apacheのドキュメントから丸写しです）では、アクセスできるのは、次の通り。

| デイレクトリ|アクセスできるユーザー |
|--------------------|----------------------------------|
| /www/docs          | グループ alpha    |
| /www/docs/ab       | グループ alpha か beta      |
| /www/docs/ab/gamma | グループ gamma （デフォルトで上書きされる）|

```ruby:AuthMergingの例
<Directory "/www/docs">
    AuthType Basic
    AuthName Documents
    AuthBasicProvider file
    AuthUserFile "/usr/local/apache/passwd/passwords"
    Require group alpha
</Directory>

<Directory "/www/docs/ab">
    AuthMerging Or
    Require group beta
</Directory>

<Directory "/www/docs/ab/gamma">
    Require group gamma
</Directory>
```

##4.4.（重要）各セクション（における設定）が、どのように統合[^1]されるか
(https://httpd.apache.org/docs/2.4/en/sections.html#merging)

[^1]: ここでは、「merge（マージ）」の訳語に「統合」を使っています。「２つ以上のものをまとめて１つにする」といった意味です。

CSSのカスケード順位と同様かそれ以上に、
**ディレクティブが適用される優先順位は大変重要です。**
なぜなら、アクセス可否＝サーバーのセキュリティに関わるからです。
そういうわけで、少しややこしいですが、なるべく詳しく書いておきます。

1.`<Directory>` セクション
最初に、`<Directory>` （正規表現を含まないもの）と、.htaccess （このファイルが置かれているディレクトリが `AllowOverride` によって許可されていれば、`<Directory>` の設定を上書きする）が同時に統合される。

※`<Directory>` ～ `</Directory>` で囲まれたセクションの中にあるディレクティブは、そのディレクトリ、そのサブディレクトリ、とそれらに含まれるファイルに適用される。（ただし、ディレクトリのコンテキストで使うことを許可されているディレクティブに限る。）(https://httpd.apache.org/docs/2.4/en/mod/core.html#directory)

2.`<DirectoryMatch>`（正規表現）セクション
次に、`<DirectoryMatch>` と `<Directory "~">`（正規表現を含むもの）が統合される。

3.`<Files>` セクション
その次に、`<Files>` と `<FilesMatch>` が同時に統合される。

※`<Files>` セクション中のディレクティブは、そのファイルがどのディレクトリ中にあるかにかかわらず、同じ名前のファイルすべてに適用されるが、特定のディレクトリ中のファイルだけに適用するために、`<Directory>` セクションの中に `<Files>` セクションを入れ子にすることができる。
(https://httpd.apache.org/docs/2.4/en/mod/core.html#files)

4.`<Location>` セクション
さらにその次に、`<Location>` と `<LocationMatch>` が同時に統合される。

※`<Location>` セクション中のディレクティブは、マッチするＵＲＬにだけ適用される。`<Location>` セクションは、完全にファイルシステムの外で動作する。（そのため、）`<Location>` セクションをファイルシステムへのアクセスコントロールに使うべきではない。異なるＵＲＬがファイルシステムの同じ場所にたどり着く可能性があるため、そのようなアクセスコントロールはすり抜けられる可能性がある。
(https://httpd.apache.org/docs/2.4/en/mod/core.html#location)

　Locationセクションの例1（下記）

| 結果 | URL |
|------|--------------------|
| ○   | /private1          |
| ○   | /private1/         |
| ○   | /private1/file.txt |
| ×   | /private1other     |

```ruby:Locationセクションの例1
<Location "/private1">
    #  ...
</Location>
```

　Locationセクションの例2（下記）…スラッシュが後につく

| 結果 | URL |
|------|--------------------|
| ×   | /private2          |
| ○   | /private2/         |
| ○   | /private2/file.txt |
| ×   | /private2other     |

```ruby:Locationセクションの例2（スラッシュが後につく）
<Location "/private2/">
    # ...
</Location>
```

5.`<If>` セクション
最後に、`<If>` セクションに含まれるものが統合される。

【注意点】
● `<Directory>` セクションと異なり、上の各1~5のグループの内部では、設定ファイル中に出てきた順番によってセクションが処理される。例えば、`/foo/bar` へのリクエストが `<Location "/foo/bar">` と `<Location "/foo">` の２つのセクションにマッチする時、この２つのセクションが設定ファイルに現れる順に評価される。
● `<Directory>` セクションは、ディレクトリの最も短い構成要素から、最も長いものへという順に処理される。
例えば、`<Directory "/var/web/dir">` は、 
`<Directory "/var/web/dir/subdir">` の前に処理される。
●多数の `<Directory>` セクションが、同じディレクトリに適用される場合は、設定ファイルの順に処理される。（訳注：「設定ファイルに現れる順に処理される。」ということでしょう。）
● `Include` ディレクティブによってインクルードされた設定は、あたかも、`Include` ディレクティブの場所にそれらがあるかのように扱われる。
● `<VirtualHost>` セクションの中は、バーチャルホストの外の対応するセクションの後で適用される。これによって、バーチャルホストがメインサーバーの設定を上書きできるようになる。
●サーバーへのリクエストが mod_proxy によって提供される時は、`<Proxy>` コンテナは、処理順に `<Directory>` に取って代わる。

##4.5.モジュールと設定セクションの関係
(https://httpd.apache.org/docs/2.4/en/sections.html#relationship-module-configuration)
　 この項目のリンクには、mod_rewrite のようなモジュールが及ぼす影響について、書かれてあります。`<Location>` セクションを使わなければ特に必要無いでしょう。

##4.6.有用な例
(https://httpd.apache.org/docs/2.4/en/sections.html#merge-examples)

次の例では、各ディレクティブの適用順は、Ａ→Ｂ→Ｃ→Ｄ→Ｅ の順です。

```ruby:例
<Location "/">
    E
</Location>

<Files "f.html">
    D
</Files>

<VirtualHost *>
    <Directory "/a/b">
        B
    </Directory>
</VirtualHost>

<DirectoryMatch "^.*b$">
    C
</DirectoryMatch>

<Directory "/a/b">
    A
</Directory>
```

次の例では、`<Location>` セクション（の設定）が最後に適用されるため、すべてのアクセスが許可されてしまいます。
**セクション（の設定）が統合される順番はと～っても重要です。**

```ruby:統合の順序
<Location "/">
    Require all granted
</Location>

# おっと！  この後の <Directory> セクションは何の効果もありません。
# なぜなら、<Location> セクションが最後に適用され、すべてのアクセスが許可されてしまうからです！

<Directory "/">
    <RequireAll>
        Require all granted
        Require not host badguy.example.com
    </RequireAll>
</Directory>
```

#5.終わりに
**新バージョンのドキュメントは、ちゃんと読まないとダメですね。**

##5.1. 最終結果
さて、こうした奮闘の結果、
他のパソコン１台と、古いスマホ１台がXAMPPサーバーにアクセスできました。

~~しかし、同じルーターへ同じWi-Fi接続している
残り２台のスマホについては、どうやら各端末の「名前解決（ＤＮＳ）」が問題との感触です。　←　*「サーバーが見つかりません」*
どちらも、インターネットには接続できるので、通信はできるようです。
どうしたものかなあ...~~
**全て、アクセスできるようになりました！**

##5.2. DNSサーバーの設定
残りのスマホがアクセスできなかった原因は、
DNSサーバーの設定でした。

今回のXAMPPバージョンアップは、「Windowsパソコンのリカバリー」に伴うものでした。
そのため、XAMPPの設定はコピペをしたのが原因でしたが、DNSサーバーの設定は保存していなかったため、一からテキトーに入力したのが災いしました。

DNSサーバーは、「簡易版（BlackJumboDog）」を使っているためか、設定の仕方がよくわかりませんでした。

Before - After をまとめると、こうなります。

| 結果 | サブドメインを設定 | 登録ドメイン | 備考 |
|:----:|--------------------|---------------:|-------|
|   ×   | www    | private.test  | 単独 |
|   ○  | private | test             |
|   ○  | www    | private.test  |

ちなみに、Windowsパソコンからアクセスできたのは、「hosts」ファイルを使っていたからDNSサーバーは無関係だったのでしょう。
古いスマホからアクセスできたのは、「古かったから」？