IIS 7.0 で HTTP の詳細エラーを使用する方法

作成者 : iisteam
発行日 : 2007 年 12 月 12 日 (作業者 : IIS Team(英語))
更新日 : 2008 年 5 月 23 日 (作業者 : IIS Team(英語))

はじめに

Web サイト管理者または Web 開発者なら誰でも、ブラウザーで "404 - ファイルが見つかりません"、"401 - 権限がありません"、"500 - サーバー エラー" などのエラー メッセージを見たことがあるでしょう。この記事では、IIS 7.0 でこれらのエラーが生成されるしくみと理由、およびこれらを構成する方法について説明します。

多くの方は、エラー メッセージの生成のためにわざわざ 1 つの記事を充てる必要はないと考えるかもしれません。しかし、エラーの扱いは想像以上に奥が深いものです。エラー メッセージはデリケートなトピックです。エラーによって、Web サイトについて公開したくない多くのことが露呈してしまうからです。サイトに関する情報を多く入手できるほど、サイトに侵入される可能性が高まります。"Google ハッキング" や "クロスサイト スクリプティング" を検索すると、このトピックに関する情報が数多く表示されます。

しかし、エラー メッセージは問題をトラブルシューティングするための有用なツールでもあります。エラー発生時には、開発者や Web サイトの管理者は可能な限り詳細な情報を必要とします。エラー メッセージによって、問題の修正方法が示されるようにするのが理想的です。ここでは、これらの根本的に相反する目的に、IIS 7.0 がどのように取り組んでいるかについて説明します。

何のエラーか

ここでは、HTTP RFC で指定されている HTTP エラーについて説明します (RFC 2616 (英語) - セクション 6.1.1)。HTTP エラーは常に、要求側クライアントに 400 より大きい状態コードの応答を返すことによって表されます。

クライアント エラー

400 ~ 500 の範囲の状態コードは、無効な構文または存在しないリソースに対する要求など、クライアントのエラーを示します。これは、任意の Web サイトに対して http://<IIS7Server>/this_resource_does_not_exist などのでたらめな URL を要求することで試すことができます。"404 - ファイルが見つかりません" エラーが表示されます。

サーバー エラー

500 以降の状態コードは、サーバーのエラーです。IIS システムでの 500 エラーの最も一般的な原因は、次のとおりです。

  • ASP ページまたは ASPX ページに構文エラーがある
  • Web サーバー構成またはアプリケーション構成が読み取れないか、または無効である
  • サイトが停止している

IE などのブラウザーは多くの場合、Web サーバーから返されたエラーを自身のエラーに差し替えてしまいます。これがトラブルシューティングを難しいものにしています。IE では、この機能をオフにできます。[ツール] メニューで [インターネット オプション] を選択し、[詳細設定] タブをクリックして [HTTP エラー メッセージを簡易表示する] チェックボックスをオフにします。未加工の応答を参照するには、IIS 6.0 Resource Kit の WFETCH などの HTTP ツールを使用します (「関連リンク」を参照)。

IIS 7.0 の HTTP エラー

httpError モジュール (custerr.dll) でエラーが発生すると、次の処理が行われます。

  • カスタム エラーの生成
  • 詳細エラーの生成

カスタム エラーは、Web サイトの一般ユーザーに表示されるエラー ページです。エラーの理由に関する簡単な説明が示され、他には何も示されません。次に、存在しないリソースを要求した際に生成されるカスタム エラーの例を示します。http://<IIS7Server>/this_resource_does_not_exist

Ee175754.iis7_1(ja-jp,TechNet.10).gif 

詳細エラーは、ローカルの管理者や開発者を対象としています。問題を速やかに修正するのに役立つ情報を提供します。次に、同じ要求で詳細エラーが返された例を示します。

Ee175754.iis7_2(ja-jp,TechNet.10).gif
 

これには危険が伴います。詳細エラーには Web サイトの内部のしくみに関する情報が含まれるためです。詳細エラーは、信頼できる担当者だけが参照できるようにする必要があります。これを確実に行うための唯一の方法は、要求がローカル コンピューターから生成された場合にのみ詳細エラーを表示することです。要求がローカルから生成されていない場合は、カスタム エラーが生成されるようにします。次の流れ図を見てみましょう。

Ee175754.iis7_3(ja-jp,TechNet.10).gif 

 

データ フロー

1 番目 : エラー チェック

応答を送信しようとする場合、httpError モジュールは通知を受信します (RQ_SEND_RESPONSE 通知)。httpError モジュールはこの応答の状態コードをチェックし、状態コードが 400 よりも小さい場合は直ちに返します。

2 番目 : カスタム エラーまたは詳細エラー

次のチェックは要求の発生元 (要求がローカル要求かリモート要求か) および errorMode プロパティの設定によって判断されます。errorMode プロパティが DetailedLocalOnly に設定されている場合、すべてのリモート要求に対してカスタム エラーが生成されます。errorMode が Custom に設定されている場合、すべてのエラー応答はカスタム エラーになります。errorMode が Detailed に設定されている場合、すべてのエラー応答は詳細エラーになります。次の表に、この動作をわかりやすく示します。

errorMode 要求の発生元 動作

DetailedLocalOnly (既定)

ローカル

詳細エラー

DetailedLocalOnly (既定)

リモート

カスタム エラー

Custom

ローカル

カスタム エラー

Custom

リモート

カスタム エラー

Detailed

ローカル

詳細エラー

Detailed

リモート

詳細エラー

 

httpError モジュールは、カスタム エラーを生成すべきであると判断すると、構成内に対応するエラーがあるかどうかを検索します。対応するエラーが見つかった場合、静的なファイルの送信、要求のリダイレクト、指定された URL の実行のいずれかの処理を行ないます。対応するエラーが見つからなかった場合、IIS 7.0 は状態コードを含む基本的な 1 行メッセージを送信します。次のセクションでは、カスタム エラー構成について詳しく説明します。

custerr.dll が詳細エラーを生成すべきであると判断した場合、さらに別のチェックが必要になります。モジュールが応答のエンティティを自身のエラー情報で上書きした場合、IIS 7.0 は応答には関わりません。このメッセージには有用な情報が含まれることがあります。ASP.NET が良い例です。ASP.NET のエラー応答のエンティティには、例外スタックと独自のエラー情報が含まれることがあります。詳細エラーは、応答のエンティティ ボディが空白の場合のみ生成されます。

<httpErrors> の構成

次に、新規インストール時の IIS 7.0 のカスタム エラー セクションを示します。

                      
<httpErrors>
            <error statusCode="401"prefixLanguageFilePath="c:\inetpub\custerr"path="401.htm" />            
            <error statusCode="403"prefixLanguageFilePath="c:\inetpub\custerr"path="403.htm" />
            <error statusCode="404"prefixLanguageFilePath="c:\inetpub\custerr"path="404.htm" />            
            <error statusCode="405"prefixLanguageFilePath="c:\inetpub\custerr"path="405.htm" />
            <error statusCode="406"prefixLanguageFilePath="c:\inetpub\custerr"path="406.htm" />            
            <error statusCode="412"prefixLanguageFilePath="c:\inetpub\custerr"path="412.htm" />
            <error statusCode="500"prefixLanguageFilePath="c:\inetpub\custerr"path="500.htm" />            
            <error statusCode="501"prefixLanguageFilePath="c:\inetpub\custerr"path="501.htm" />
            <error statusCode="502"prefixLanguageFilePath="c:\inetpub\custerr"path="502.htm" />
</httpErrors>

 

応答の状態コードが 401 の場合、IIS 7.0 は 401.htm というファイルを返します。

副状態コード

多くの HTTP エラーには副状態があります。IIS 7.0 の既定のカスタム エラー構成では、基になる副状態コードは区別されません。不適切な資格情報を入力した場合 (401.1)、ファイルへのアクセス権が無効なためアクセス拒否された場合 (401.3) のいずれも、同じカスタム エラー ページが送信されます。副状態コードはログ ファイルまたは詳細エラーで確認できます。次に、IIS 7.0 で生成されるさまざまな 404 副状態コードの一覧を示します。

状態 説明

404.1

サイトが見つかりません

404.2

ポリシーによって拒否されました。要求の ISAPI または CGI プログラムは、制限一覧で許可されていません。

404.3

静的ファイル ハンドラーの MimeMap にファイルがないため、要求は拒否されました。

404.4

要求を処理するハンドラーが見つかりません。

404.5

要求フィルター モジュールで要求の URL シーケンスが拒否されました。

404.6

要求フィルター モジュールで要求の HTTP 動詞が拒否されました。

404.7

要求フィルター モジュールで要求のファイル拡張子が拒否されました。

404.8

要求フィルター モジュールで特定の URL セグメント (2 つのスラッシュ間の文字) が拒否されました。

404.9

IIS で非表示ファイルの処理が拒否されました。

404.10

要求フィルター モジュールで長すぎるヘッダーが拒否されました。

404.11

要求フィルター モジュールでダブルエスケープを含む要求が拒否されました。

404.12

要求フィルター モジュールでハイビット文字を含む要求が拒否されました。

404.13

要求フィルター モジュールで長すぎる要求が拒否されました (要求 + エンティティ ボディ)。

404.14

要求フィルター モジュールで長すぎる URL を含む要求が拒否されました。

404.15

要求フィルター モジュールで長すぎるクエリ文字列を含む要求が拒否されました。

 

特定の副状態コードに対してカスタム エラーを表示するように httpErrors セクションを構成できます。httpErrors 構成セクションに次の行を追加すると、IIS 7.0 MimeMap に含まれていないファイル拡張子を持つファイルが要求された場合、IIS 7.0 は 404_3.htm を返します (<staticContent> 構成セクション)。

                      
  
<error statusCode="404"subStatusCode="3"prefixLanguageFilePath="c:\inetpub\custerr"path="404_3.htm" />

 

この例を実行する方法を以下に示します。

  1. 上記のエントリを httpErrors 構成セクションに追加します。
  2. c:\inetpub\custerr\ja-jp ディレクトリに 404_3.htm というファイルを作成します。
  3. c:\inetpub\wwwroot ディレクトリに test.yyy というファイルを作成します。
  4. https://localhost/test.yyy を要求します。

ファイル拡張子 yyy は IIS 7.0 MimeMap に含まれないため、静的ファイル ハンドラーはこの拡張子を処理しません。

IIS 7.0 の新機能 : 言語固有のカスタム エラー

最新のブラウザーには、クライアントの言語が要求ヘッダーとして含まれています。このヘッダーの例を次に示します。

Accept-Language: ja-jp

使用できる言語の構文およびレジストリは、RFC1766 (英語) で指定されています。

エラーを生成する際、IIS 7.0 はこのヘッダーを考慮に入れて、返すカスタム エラー ファイルを探します。次のロジックを使用して、カスタム エラーのパスを生成します。

prefixLanguageFilePath 構成設定 (c:\inetpub\custerr など) +
クライアントにより送信された Accept-Language ヘッダー (ja-jp など) +
Path 構成設定 (404.htm など)

例 :

ブラウザーが存在しないリソースを要求し、Accept-Language ヘッダーの値が ja-jp の場合、c:\inetpub\custerr\ja-jp\404.htm というファイルが返されます。

たとえば、ドイツ語のエラー メッセージを返したいとします。それには、Windows Vista のドイツ語用言語パックをインストールする必要があります。これにより、カスタム エラー ファイルが含まれた c:\inetpub\custerr\de-DE ディレクトリが作成されます。次にブラウザーによって Accept-Language ヘッダーの値が de-DE である要求が送信された場合、返されるファイルは c:\inetpub\custerr\de-DE\404.htm になります。

ディレクトリ de-DE が存在しない場合、IIS 7.0 は常にシステム言語を使用します。

: Internet Explorer では Accept-Language ヘッダーを構成できます。[ツール][インターネット オプション] の順にクリックして [全般] を選択し、[言語] ボタンをクリックします。

カスタム エラーのオプション

上記の例では、IIS 7.0 は、カスタム エラー応答としてファイルのコンテンツを送信しています。IIS 7.0 には他にもエラーに応答する 2 つの方法があります。URL を実行する方法と、要求をリダイレクトする方法です。

ExecuteUrl

電子メールの送信やエラーのデータベースへのログ記録など、カスタム エラーでより多くの操作を行う場合、URL を実行できます。これにより、ASP.NET ページのような動的なコンテンツを実行できます。次の例では、404 カスタム エラーを置き替えています。これにより、404 エラーが発生すると、IIS 7.0 は /404.aspx を実行するようになります。

                      
<httpErrors>
            <!-- default custom error for 401 errors -->
            <!-- <error statusCode="404" prefixLanguageFilePath="c:\inetpub\custerr" path="404.htm" />-->

            <!-- ExecuteURL replaces default file response mode -->
            <error statusCode="404"path=/404.aspx" responseMode="ExecuteURL"/>                    
            <error statusCode="403"prefixLanguageFilePath="c:\inetpub\custerr"path="403.htm" />            
            <error statusCode="404"prefixLanguageFilePath="c:\inetpub\custerr"path="404.htm" />
            <error statusCode="405"prefixLanguageFilePath="c:\inetpub\custerr"path="405.htm" />            
            <error statusCode="406"prefixLanguageFilePath="c:\inetpub\custerr"path="406.htm" />
            <error statusCode="412"prefixLanguageFilePath="c:\inetpub\custerr"path="412.htm" />            
            <error statusCode="500"prefixLanguageFilePath="c:\inetpub\custerr"path="500.htm" />
            <error statusCode="501"prefixLanguageFilePath="c:\inetpub\custerr"path="501.htm" />            
            <error statusCode="502"prefixLanguageFilePath="c:\inetpub\custerr"path="502.htm" />
</httpErrors>

セキュリティの考慮事項

注意 : アーキテクチャ上の理由により、IIS 7.0 で URL を実行できるのは、その URL が同じアプリケーション プールに配置されている場合だけです。カスタム エラーを別のアプリケーション プールで実行するには、リダイレクト機能を使用します。

IIS 7.0 では、特定のエラーが発生した場合に、ブラウザーに 302 リダイレクトを返すこともできます。サーバー ファームを使用している場合、リダイレクトは有用です。たとえば、すべてのエラーを中央にリダイレクトして厳重に監視できます。

ただし、リスクもあります。responseMode="File" (既定) では、ディスク上のすべてのファイルを指定できます。セキュリティに対する意識が非常に高い場合、これは採用できません。

現実的なシナリオでは、errorMode 設定の委任のみを許可します。これにより、開発者はリモート クライアントを使用している場合であっても、アプリケーションの詳細エラーを受信できます。必要な操作は errorMode="Detailed" を設定することだけです。次に、このシナリオを構成する方法を示します。

httpErrors セクションの委任を許可します。

                        
  
<sectionname="httpErrors"overrideModeDefault="Allow" />

 

次に、applicationHost.config の <httpErrors> セクションに移動して、errorMode のみを委任するように変更します。

<httpErrorslockAllAttributesExcept="errorMode"lockElements="error">
            <error statusCode="404"prefixLanguageFilePath="E:\inetpub\custerr"path="404.htm" />            
            <error statusCode="401"prefixLanguageFilePath="E:\inetpub\custerr"path="401.htm" />
            <error statusCode="403"prefixLanguageFilePath="E:\inetpub\custerr"path="403.htm" />            
            <error statusCode="405"prefixLanguageFilePath="E:\inetpub\custerr"path="405.htm" />
            <error statusCode="406"prefixLanguageFilePath="E:\inetpub\custerr"path="406.htm" />
            <error statusCode="412"prefixLanguageFilePath="E:\inetpub\custerr"path="412.htm" />
            <error statusCode="500"prefixLanguageFilePath="E:\inetpub\custerr"path="500.htm" />            
            <error statusCode="501"prefixLanguageFilePath="E:\inetpub\custerr"path="501.htm" />
            <error statusCode="502"prefixLanguageFilePath="E:\inetpub\custerr"path="502.htm" />
</httpErrors>

まとめ

カスタム エラーおよび詳細エラーは IIS 7.0 の強力な機能です。これらは、IIS 7.0 サーバーのセキュリティを損なわずに問題をトラブルシューティングするのに役立ちます。多くの構成オプションにより、ユーザーのエクスペリエンスをカスタマイズできます。最も重要なのは、楽しみながら行うことです。