Como usar erros detalhados HTTP no IIS 7.0

pela Equipe do IIS

Introdução

Todo administrador de site ou desenvolvedor Web já viu as mensagens '404 - Arquivo não encontrado', '401 - Não autorizado' ou '500 - Erro do servidor' em um navegador. Este artigo ajuda você a entender como e por que o IIS gera esses erros e como eles podem ser ajustados.

Muita gente pode achar que a geração de mensagens de erro não parece justificar um artigo completo. Mas há mais nesses erros do que o que está diante dos olhos. As mensagens de erro são um assunto delicado, porque cada erro revela mais sobre seu site do que você pode querer revelar. Quanto mais informações alguém puder coletar sobre seu site, mais provável é que você seja hackeado. Uma busca por "hackear no google" ou "scripts entre sites" revela uma riqueza de informações sobre este tema.

No entanto, as mensagens de erro também são uma ferramenta valiosa para solucionar problemas. Desenvolvedores e administradores de sites pedem o máximo de detalhes possível quando ocorre um erro. O ideal é que a mensagem de erro forneça recomendações sobre como corrigir o problema. Vejamos como o IIS aborda esses objetivos diametralmente opostos.

Erros? Que erros?

Este artigo fala sobre erros HTTP conforme especificado no HTTP RFC (RFC 2616 - seção 6.1.1). Um erro HTTP é sempre expresso enviando uma resposta com um código de status maior que 400 de volta ao cliente solicitante.

Erros do Cliente

Os códigos de status entre 400 e 500 especificam um erro que o cliente cometeu, por exemplo, sintaxe incorreta ou uma solicitação para um recurso que não existe. Você pode testar solicitando uma URL falsa do site de sua escolha, por exemplo: http://<IIS7Server>/this_resource_does_not_exist. O resultado é um erro “404 - Arquivo não encontrado”.

Erros do Servidor

Os códigos de status a partir de 500 são erros causados pelo servidor. As causas mais comuns de erros 500 em sistemas IIS são:

  • Uma página ASP ou ASPX que contém um erro de sintaxe
  • A configuração do servidor Web ou a configuração do aplicativo não podem ser lidas ou são inválidas
  • O site está parado

É importante observar que navegadores como o IE geralmente substituem erros retornados de um servidor web por seus próprios erros. Isso dificulta a solução de problemas. No IE, você pode desativar esse recurso. Acesse o menu "Ferramentas", selecione "Opções da Internet", clique na guia "Avançado", localize a caixa de seleção "Mostrar mensagens de erro HTTP amigáveis" e desmarque-a. Para ver a resposta bruta, use ferramentas HTTP como WFETCH no IIS 6.0 Resource Kit (consulte "Links relacionados").

Erros HTTP no IIS

Há duas situações que podem acontecer quando o módulo httpError (custerr.dll) encontra um erro:

  • É gerado um erro personalizado
  • É gerado um erro detalhado

Erros personalizados são páginas de erro que os usuários regulares do seu site veem. Eles contêm uma breve descrição de erro com o motivo do erro, mas nada mais. Este é o erro personalizado que é exibido quando você solicita um recurso que não existe, por exemplo: http://< IIS7Server>/this_resource_does_not_exist

Screenshot of the the H T T P Error 404 file or directory not found webpage in Internet Explorer.

Os erros detalhados destinam-se a administradores e desenvolvedores locais. Eles devem fornecer informações que ajudem a corrigir imediatamente o problema. Aqui está um exemplo da mesma solicitação, mas agora retornando um erro detalhado:

Screenshot of the Server Error in Default Web Site Application webpage, showing a Cause and Solution section for the error.

Temos aqui uma situação perigosa, porque os erros detalhados contêm informações sobre o funcionamento interno do seu site. Somente pessoas de confiança devem ver um erro detalhado. A única maneira de garantir isso é gerar um erro detalhado apenas se a solicitação vier de uma máquina local. Assim que a solicitação não for local, será gerado um erro personalizado. Confira o diagrama de fluxo a seguir:

Diagram of the Status Substatus, Entity Body, and Set Error's path of creating a detailed error.

Fluxo de dados

Primeiro: Verificação de erros

O módulo httpError recebe uma notificação se uma resposta estiver prestes a ser enviada (notificação RQ_SEND_RESPONSE). O módulo httpError verifica o código de status dessa resposta e retorna imediatamente se o código de status não for maior que 400.

Segundo: Erro personalizado ou erro detalhado

A próxima verificação é determinada pela origem da solicitação (se é uma solicitação local ou remota) e pela configuração da propriedade errorMode. A propriedade errorMode é definida como DetailedLocalOnly, o que significa que são gerados erros personalizados para toda solicitação remota. Se errorMode estiver definido como "Custom", todas as respostas de erro serão erros personalizados. Se errorMode estiver definido como "Detailed", todas as respostas de erro serão erros detalhados. A tabela a seguir esclarece esse comportamento:

errorMode Origem da solicitação Ação
DetailedLocalOnly (padrão) Local Erro detalhado
DetailedLocalOnly (padrão) Remoto Erro personalizado
Personalizado Local Erro personalizado
Personalizado Remoto Erro personalizado
Detalhado Local Erro detalhado
Detalhado Remoto Erro detalhado

Se o módulo httpError determinar que deve ser gerado um erro Personalizado, ele examinará sua configuração para ver se pode encontrar um erro correspondente. Se for encontrada uma correspondência, ele enviará o arquivo estático, redirecionará a solicitação ou executará a URL especificada. Se nenhuma correspondência for encontrada, o IIS enviará uma mensagem básica de uma linha contendo o código de status. A próxima seção explica a configuração de erro personalizado em detalhes.

Se custerr.dll determinar que deve ser gerado um erro detalhado, será necessária outra verificação. O IIS não interferirá na resposta se um módulo substituir a entidade da resposta com sua própria descrição de erro. Ele pode conter informações valiosas. ASP.NET é um bom exemplo. A entidade de uma resposta de erro ASP.NET pode conter a pilha de exceções e sua própria descrição de erro. Um erro detalhado só será gerado se o corpo da entidade da resposta estiver vazio.

<httpErrors> Configuração

Esta é a seção de erro personalizado do IIS obtida em uma instalação limpa:

<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>

Você verá que, se o código de status de uma resposta for 401, o IIS retornará um arquivo chamado 401.htm.

Códigos de substatus

Muitos erros HTTP têm um substatus. A configuração de erros personalizados padrão do IIS não diferencia códigos de substatus com base no erro. Ela envia a mesma página de erro personalizado se você inserir as credenciais erradas (401.1) ou se tiver acesso negado com base em direitos inválidos para acessar um arquivo (401.3). Você pode ver os diferentes códigos de substatus nos arquivos de log ou em erros detalhados. Aqui está uma lista dos diferentes códigos de substatus 404 que o IIS produz:

Status Descrição
404,1 Site não encontrado
404,2 Negado pela Política. A solicitação ISAPI ou o programa CGI não são permitidos pela Lista de Restrição.
404,3 O manipulador de arquivo estático não tinha o arquivo em seu MimeMap e, portanto, rejeitou a solicitação.
404,4 Nenhum manipulador foi encontrado para atender à solicitação.
404,5 O Módulo de Filtragem de Solicitações rejeitou uma sequência de URL na solicitação.
404,6 O módulo de Filtragem de Solicitações negou o verbo HTTP da solicitação.
404,7 O módulo de Filtragem de Solicitações rejeitou a extensão de arquivo da solicitação.
404,8 O módulo de Filtragem de Solicitações rejeitou um segmento de URL específico (caracteres entre duas barras).
404,9 O IIS rejeitou servir um arquivo oculto.
404,11 O módulo de Filtragem de Solicitações rejeitou uma solicitação com escape duplo.
404,12 O módulo Filtragem de Solicitações rejeitou uma solicitação que continha caracteres de bit alto.
404,14 O módulo Filtragem de Solicitações rejeitou uma solicitação com uma URL muito longa.
404,15 O módulo Filtragem de Solicitações rejeitou uma solicitação com uma cadeia de caracteres de consulta muito longa.
413.1 O módulo Filtragem de Solicitações rejeitou uma solicitação muito longa (solicitação + corpo da entidade).
431 O módulo Filtragem de Solicitações rejeitou um cabeçalho muito longo.

Você pode configurar a seção httpErrors para mostrar um erro personalizado para códigos de substatus específicos. Se você adicionar a seguinte linha à seção de configuração httpErrors, o IIS retornará 404_3.htm se for solicitado um arquivo com uma extensão de arquivo que não estiver incluído no MimeMap do IIS (seção de configuração <staticContent>).

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

É esta a forma de fazer o exemplo funcionar:

  1. Adicione a entrada acima à sua seção de configuração httpErrors.
  2. Crie um arquivo chamado 404_3.htm em seu diretório c:\inetpub\custerr\en-us.
  3. Crie um arquivo chamado test.yyy em seu diretório c:\inetpub\wwwroot.
  4. Agora, solicite http://localhost/test.yyy.

A extensão de arquivo .yyy não faz parte do MimeMap do IIS e o manipulador de arquivos estático não a servirá.

Novo no IIS: Erros personalizados específicos a um idioma

Todo navegador mais recente inclui o idioma do cliente como um cabeçalho de solicitação. Aqui está um exemplo de como esse cabeçalho pode ser:

Accept-Language: en-us

A sintaxe e o registro dos idiomas aceitos são especificados em RFC1766.

Ao gerar um erro, o IIS leva esse cabeçalho em consideração quando procura o arquivo de erro personalizado a retornar. Ele gera o caminho para o erro personalizado usando a seguinte lógica:

definição de configuração prefixLanguageFilePath (por exemplo, c:\inetpub\custerr)+
cabeçalho Accept-Language enviado pelo cliente (por exemplo, en-us) +
Definição de configuração de caminho (por exemplo, 404.htm)

Exemplo:

Se o navegador enviar uma solicitação para um recurso não existente e o cabeçalho "Accept-Language" tiver o valor de "en-us", o arquivo retornado será c:\inetpub\custerr\en-us\404.htm.

Por exemplo, se você é da Alemanha, você prefere receber mensagens de erro em alemão. Para isso, você deve instalar o pacote de idioma do Windows Vista para alemão. Isso cria o diretório c:\inetpub\custerr\de-DE com arquivos de erro personalizados nele. Agora, se o navegador enviar o cabeçalho "Accept-Language" com o valor de "de-DE, o arquivo retornado será c:\inetpub\custerr\de-DE\404.htm.

O IIS sempre retornará ao idioma do sistema se o diretório "de-DE" não existir.

Observação

O Internet Explorer permite configurar o cabeçalho Accept-Language. Acesse "Ferramentas" - "Opções da Internet", selecione a aba "Geral" e clique no botão "Idiomas".

Opções de erros personalizados

Nos exemplos acima, o IIS envia o conteúdo do arquivo como a resposta de erro personalizado. O IIS tem duas outras maneiras de responder a um erro: executando uma URL ou redirecionando a solicitação.

ExecuteUrl

Se você quiser incluir mais ações em seu erro personalizado, por exemplo, enviar um e-mail ou registrar o erro em um banco de dados, você pode executar uma URL. Isso permite que você execute conteúdo dinâmico como uma página ASP.NET. O exemplo abaixo substitui o erro personalizado 404. Agora, o IIS executa /404.aspx sempre que ocorre um erro 404.

<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>

Considerações sobre segurança

Atenção: por motivos de arquitetura, o IIS só pode executar a URL se ela estiver localizada no mesmo pool de aplicativos. Use o recurso de redirecionamento para executar um erro personalizado em um pool de aplicativos diferente.

O IIS também pode retornar um redirecionamento 302 para o navegador quando ocorre um erro específico. O redirecionamento é bom se você tiver uma farm de servidores. Por exemplo, você pode redirecionar todos os seus erros para um local central que você monitora de perto.

No entanto, há um risco: responseMode="File" (que é o padrão) permite que você especifique cada arquivo no disco. Isso não dá certo se você for muito preocupado com a segurança.

Um cenário viável pode ser apenas permitir a delegação da configuração errorMode. Isso permite que um desenvolvedor receba erros detalhados para seu aplicativo, mesmo se ele estiver usando um cliente remoto. Tudo o que é necessário é definir errorMode="Detailed". Veja como configurar esse cenário:

Permita a delegação da seção httpErrors:

<section name="httpErrors" overrideModeDefault="Allow" />

Em segundo lugar, vá para a seção <httpErrors> em applicationHost.config e altere-a para que somente errorMode seja delegado:

<httpErrors lockAllAttributesExcept="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>

Resumo

Erros personalizados e detalhados são recursos poderosos do IIS. Eles ajudam a solucionar problemas sem comprometer a segurança do servidor IIS. Muitas opções de configuração ajudam você a personalizar a experiência de seus usuários. E o mais importante: experimentar com elas é proveitoso.

Confira também