DNSとApacheについての問題

### Apache HTTP Server

# DNS と Apache にまつわる注意事項

本文書の内容は次の一言に尽きます。Apache が設定ファイルを読み込むときに DNS を使用する必要がないようにして下さい。Apache が設定ファイルを読み込むときに DNS を使用する必要がある場合、信頼性の問題(起動しないかもしれません) やサービス拒否、盗用アタック(他のユーザからヒットを盗むことを含みます) の問題に直面するかもしれません。

### 簡単な例

この設定例を考えてみます:

>         <VirtualHost www.abc.dom>
>         ServerAdmin webgirl@abc.dom
>         DocumentRoot /www/abc
>         </VirtualHost>

Apache が正常に機能するには、バーチャルホストごとに必ず二つの 情報が必要になります。それは、 `ServerName` と、そのサーバが応答するための IP アドレス(最低一つ) です。 この例では IP アドレスを含んでいませんので、Apache は DNS を使用して `www.abc.dom` を見つけなければなりません。 設定ファイルを読み込んでいるときに何らかの理由で DNS が利用できなかった場合、 バーチャルホストは設定されません。 そして、そのバーチャルホストに対するヒットには応答がなされません (Apache 1.2 以前では起動すらしません)。

`www.abc.dom` のアドレスが 10.0.0.1 だとします。では、次の設定について考えてみましょう。

>         <VirtualHost 10.0.0.1>
>         ServerAdmin webgirl@abc.dom
>         DocumentRoot /www/abc
>         </VirtualHost>

現在 Apache は DNS 逆引きを使用してこのバーチャルホストの `ServerName` を見つけます。 その逆引きが失敗した場合は部分的にバーチャルホストを無効にします (Apache 1.2 より前では起動すらしません)。 バーチャルホストが名前ベースであれば完全に無効になりますが、 IP ベースであれば概ね動作します。しかしながら、サーバ名を含む完全な URL を生成しなければならない場合は、正しい URL の生成ができません。

次の例は上記の問題を解決しています。

>         <VirtualHost 10.0.0.1>
>         ServerName www.abc.dom
>         ServerAdmin webgirl@abc.dom
>         DocumentRoot /www/abc
>         </VirtualHost>

### サービス拒否

サービス拒否が起こる場合、(少なくとも) 二つのケースがあります。 Apache 1.2 より前を実行している場合、バーチャルホストのための 上記の二つの DNS 検索のうち一つでも失敗すれば起動すらしません。 またこの DNS 検索が自分の制御下にすらない場合もありえます。 例えば、`abc.dom` が顧客のサーバの一つで、 DNS は顧客自身で管理している場合、顧客は単に `www.abc.dom` レコードを削除するだけで、 (1.2 より前の) サーバを起動不能にすることができます。

もう一つのケースは、より気付きにくいものです。 次の設定について考えてみましょう。

>         <VirtualHost www.abc.dom>
>         ServerAdmin webgirl@abc.dom
>         DocumentRoot /www/abc
>         </VirtualHost>

>         <VirtualHost www.def.dom>
>         ServerAdmin webguy@def.dom
>         DocumentRoot /www/def
>         </VirtualHost>

10.0.0.1 を `www.abc.dom` に、10.0.0.2 を `www.def.dom` に割り当てているとします。また、 `def.com` は顧客自身の DNS の制御下にあるとします。この設定で、`abc.com` に向けられたトラフィックすべてを奪うことができる位置に `def.com` を設置できています。後は単に `www.def.dom` が 10.0.0.1 を参照するように設定するだけです。DNS は顧客側でコントロールされているので、`www.def.com` レコードが好きな場所を指すように設定するのを止めることができません。

10.0.0.1 に対するリクエスト (`http://www.abc.dom/whatever` 形式の URL を入力したユーザからのものすべてを含みます) は、`def.dom` バーチャルホストで応答されます。 このようなことが何故起こるかもっとよく知るためには、 応答の必要なバーチャルホストへのリクエストに対して、 Apache がどのように整合性を確保するかについて、 深い議論が必要になります。おおまかな説明はこちらに記述されています。

### 「主要なサーバ」のアドレス

Apache 1.1 で追加された 名前ベースのバーチャルホストのサポートにより、httpd が動作しているホストの IP アドレスを、Apache が知っている必要があります。このアドレスを得るために、 (もしあれば)グローバルの `ServerName` や C の `gethostname` ファンクションコール (これはコマンドプロンプトで "hostname" と打ち込むのと同じ結果を返します。) を使用します。 それからこのアドレスの DNS 検索を行ないます。 現時点では、この検索の回避方法は何もありません。

DNS サーバのダウンが原因でこのルックアップが失敗するのを恐れる場合、 `/etc/hosts` に hostname を挿入することができます。 (マシンが正常に起動できるように、これはおそらく既に存在します。) それから、DNS が失敗したときに確実に `/etc/hosts` を使用するように設定します。どんな OS を使っているかによりますが、 `/etc/resolv.conf` や `/etc/nsswitch.conf` を編集することによって完成できます。

もしサーバが他の理由により DNS を実行する必要が何もなければ、 Apache を `HOSTRESORDER` 環境変数を "local" に設定して 実行することで問題を避けることができるかもしれません。これは使用している OS とリゾルバライブラリに依存します。 これは `mod_env` を使って環境変数を制御していない限り、CGI にも影響します。 OS の man ページや FAQ を参照するようにしてください。

### これらの問題を避ける秘訣

- `<VirtualHost>` 中に IP アドレスを使う
- `Listen` 中に IP アドレスを使う
- `BindAddress` 中に IP アドレスを使う
- すべてのバーチャルホストに対し明示的な `ServerName` を確実に与える
- 応答するページのない `<VirtualHost _default_:*>` サーバを作成する

### 付録： 将来的な方向性

DNS に関して、現状は全く宜しくありません。Apache 1.2 で、 DNS のイベントが失敗しても少なくとも起動プロセスが続くようにしましたが、 これが最高の解決方法ではないでしょう。アドレスの再割り当てが 必要不可避 となっている今日のインターネットにおいては、 設定ファイルの中で明示的な IP アドレスを要求する仕様は、 全く宜しくありません。

上で説明したサービス盗用攻撃に対して可能な対策は、 DNS の正引きにより返された IP アドレスから DNS の逆引きを実行し、 その二つの名前を比較することです。一致しない場合バーチャルホストは無効にされます。 これには、DNS の逆引きが適切に設定されている必要があります。(DNS の「二重の逆引き」は FTP サーバや TCP ラッパーにより一般的に使われているため、 ほとんどの管理者には馴染みのあるものでしょう)。

IP アドレスが使用されていなくて DNS が失敗した場合は、 どうしてもバーチャルホストウェブサーバを信頼性を確保して 起動させることは不可能のようです。設定の一部を無効にするというような 部分的な解決は、サーバの目的にもよりますが 起動しないよりも悪いかもしれません。

HTTP/1.1 が開発され、ブラウザやプロキシが `Host` ヘッダを発行するようになったので、IP ベースのバーチャルホストを 全く使用しなくても済むようになるかもしれません。 この場合、ウェブサーバは設定中に DNS 参照をしなくても済みます。 しかし 1997 年 3 月時点の状況では、 商用レベルのウェブサーバで使用できるほどには、 これらの機能は広く開発が進んでいません。

### Apache HTTP Server