Proxy reverso com Reescrita de URL v2 e o Application Request Routing

por Ruslan Yakushev

Este passo a passo orientará você sobre como usar o Módulo de Reescrita de URL e o Application Request Routing (ARR) para implementar um servidor proxy reverso para vários aplicativos de back-end.

Pré-requisitos

Para executar este passo a passo, você deve ter o seguinte:

  1. IIS 7 ou superior com serviço de função do ASP.NET habilitado.
  2. Módulo de Reescrita de URL instalado (a versão 2.0 é necessária se você quer concluir a parte sobre reescrita de resposta)
  3. Application Request Routing versão 1.0 ou versão 2.0 instalado

Introdução

Usando o Módulo de Reescrita de URL e o Application Request Routing, você pode implementar configurações complexas e flexíveis de balanceamento de carga e proxy reverso. Um cenário de proxy reverso muito comum é disponibilizar vários aplicativos Web internos pela Internet. Um servidor Web acessível pela Internet é usado como um servidor proxy reverso que recebe solicitações da Web e, em seguida, as encaminha para vários aplicativos da intranet para processamento: a figura a seguir ilustra uma configuração típica para um cenário de proxy reverso:

Diagram of a typical configuration for a reverse proxy scenario.

Supondo que o servidor ARR tenha um nome de domínio http://contoso.com, cada aplicativo Web pode ser acessado usando estas URLs:

  • http://contoso.com/webmail/
  • http://contoso.com/payroll/

Quando uma solicitação é feita para o http://contoso.com/webmail/default.aspx, o ARR encaminha essas solicitações para um servidor interno usando a URL http://webmail/default.aspx. Da mesma forma, os pedidos a http://contoso.com/payroll/ são encaminhados para http://payroll/default.aspx.

Além disso, se o aplicativo interno insere links em seu HTML de resposta que se vinculam a outro lugar nesses aplicativos, esses links devem ser modificados antes que a resposta seja retornada ao cliente. Por exemplo, uma página de http://webmail/default.aspx pode conter um link como este:

<a href="/default.aspx?id=1">link</a>

Em seguida, o servidor ARR deve alterar esse link para o seguinte:

<a href="/webmail/default.aspx?id=1">link</a>

Criando o site de exemplo

Para simplificar, o cenário de proxy reverso com o qual você trabalhará neste passo a passo será implementado em um único servidor, com o "Site Padrão" do IIS atuando como um site de proxy reverso e aplicativos de email e folha de pagamento hospedados em sites IIS separados no mesmo servidor.

Para criar os sites de exemplo:

  1. Crie duas pastas chamadas "email" e "folha de pagamento" na seguinte pasta:

    %SystemDrive%\inetpub\ folder.
    
  2. Crie dois sites do IIS chamados "email" e "folha de pagamento" que apontem para as pastas correspondentes em %SystemDrive%\inetpub\. Use portas IP diferentes para cada site.
    Você pode usar os seguintes comandos para criar os sites:

    %windir%\System32\inetsrv\appcmd.exe add site /name:"webmail" /bindings:http/*:8081: /physicalPath:"%SystemDrive%\inetpub\webmail"
    
    %windir%\System32\inetsrv\appcmd.exe add site /name:"payroll" /bindings:http/*:8082: /physicalPath:"%SystemDrive%\inetpub\payroll"
    
  3. Crie um arquivo chamado default.aspx na seguinte pasta:

    %SystemDrive%\inetpub\webmail
    
  4. Copie a seguinte marcação ASP.NET, cole-a no arquivo e salve o arquivo:

    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Reverse Proxy Test - WebMail Application</title>
    </head>
    <body>
        <h1>Reverse Proxy Test Page - WebMail Application</h1>
        <p>Requested URL path is <%= Request.ServerVariables["SCRIPT_NAME"] %><p>
        <p><a href="<%= Request.ServerVariables["SCRIPT_NAME"] %>">Here</a> is the link to this page.</p>
    </body>
    </html>
    
  5. Crie um arquivo chamado default.aspx na seguinte pasta:

    %SystemDrive%\inetpub\payroll
    
  6. Copie a seguinte marcação ASP.NET, cole-a no arquivo e salve o arquivo:

    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Reverse Proxy Test - Payroll Application</title>
    </head>
    <body>
        <h1>Reverse Proxy Test Page - Payroll Application</h1>
        <p>Requested URL path is <%= Request.ServerVariables["SCRIPT_NAME"] %><p>
        <p><a href="<%= Request.ServerVariables["SCRIPT_NAME"] %>">Here</a> is the link to this page.</p>
    </body>
    </html>
    
  7. Para verificar se os sites estão funcionando corretamente, abra uma navegação na Web e solicite os seguintes URLs:

    http://localhost:8081/default.aspx
    
    http://localhost:8082/default.aspx
    

Configurando regras para o proxy reverso

Nesta seção do passo a passo, você configurará a funcionalidade de proxy reverso para trabalhar com os sites de exemplo que você criou.

Habilitando a funcionalidade de proxy reverso

A funcionalidade de proxy reverso está desabilitada por padrão, portanto, você deve começar habilitando-a.

  1. Abra o Gerenciador do IIS
  2. Selecione um nó de servidor no modo de exibição de árvore no lado esquerdo e clique no recurso "Application Request Routing":
    Screenshot of the I I S Manager. Different icons are shown. The Application Request Routing icon is highlighted.
  3. Marque a caixa de seleção "Habilitar Proxy". Deixe os valores padrão para todas as outras configurações nesta página:
    Screenshot of the Application Request Routing page. Enable proxy is highlighted and selected.

Criando uma regra para o aplicativo de email

Você criará duas regras de reescrita:

  • Uma regra de reescrita que fará o proxy de qualquer solicitação para o aplicativo de email em http://localhost:8081/ desde que o caminho da URL solicitada comece com "email".
  • Uma regra de reescrita que fará o proxy de qualquer solicitação para o aplicativo de folha de pagamento em http://localhost:8082/ desde que o caminho da URL solicitada comece com "folha de pagamento".

Para adicionar as regras de reescrita de proxy reverso:

  1. Abra o arquivo web.config que fica no seguinte local:

    %SystemDrive%\inetpub\wwwroot\
    
  2. No elemento /configuration/system.webServer, adicione o seguinte e salve o arquivo:

    <rewrite>
        <rules>
            <rule name="Reverse Proxy to webmail" stopProcessing="true">
                <match url="^webmail/(.*)" />
                <action type="Rewrite" url="http://localhost:8081/{R:1}" />
            </rule>
            <rule name="Reverse Proxy to payroll" stopProcessing="true">
                <match url="^payroll/(.*)" />
                <action type="Rewrite" url="http://localhost:8082/{R:1}" />
            </rule>
        </rules>
    </rewrite>
    

Para saber mais sobre como criar regras de reescrita, consulte Criando regras de reescrita para o Módulo de Reescrita de URL.

Testando a funcionalidade de proxy reverso

Abra um navegador da Web e faça uma solicitação para http://localhost/webmail/default.aspx. Você deve ver a resposta da página de teste de email. Além disso, faça uma solicitação para http://localhost/payroll/default.aspx. Você deve ver a resposta da página de teste de folha de pagamento.

Screenshot of the Reverse Proxy Test Page Web Mail Application. At the bottom the U R L h t t p colon slash local host slash default dot a s p x is highlighted.

Observe que, em ambos os casos, o link dentro da resposta aponta para http://localhost/default.aspx. Se você clicar neste link, isso resultará na resposta 404 (Arquivo não encontrado) do servidor. Na próxima seção, você aprenderá a criar uma regra de saída para corrigir os links da resposta HTML gerada pelo aplicativo.

Configurando regras para reescrita de resposta

Esta seção da documentação se aplica à versão 2.0 do Módulo de Reescrita de URL do IIS 7.

Você definirá uma regra de saída que substituirá todos os links dentro do HTML de resposta da seguinte maneira:

<a href="/default.aspx">...</a>

será substituído por:

<a href="/webmail/default.aspx">...</a>

(se a resposta veio do aplicativo de email)

e

<a href="/payroll/default.aspx">...</a>

(se a resposta veio do aplicativo de folha de pagamento)

Aviso

Quando os cabeçalhos de resposta ou o conteúdo da resposta são modificados por uma regra de reescrita de saída, um cuidado extra deve ser tomado para garantir que o texto inserido na resposta não contenha nenhum código executável do lado do cliente, o que pode resultar em vulnerabilidades de script entre sites. Isso é especialmente importante quando a regra de reescrita usa dados não confiáveis, como cabeçalhos HTTP ou a cadeia de caracteres de consulta, para criar a cadeia de caracteres que será inserida na resposta HTTP. Nesses casos, a cadeia de caracteres de substituição deve ser codificada em HTML usando a função HtmlEncode, por exemplo:

<action type="Rewrite" value="{HtmlEncode:{HTTP_REFERER}}" />

Para criar a regra, siga estas etapas:

  1. Vá para o Gerenciador do IIS
  2. Selecione "Site Padrão"
  3. No Modo de Exibição de Recurso, clique em "Reescrita de URL".
    Screenshot of the I I S Manager. The Connections pane shows an expanded navigation tree. Default Web Site is highlighted. In the Default Web Site Home pane, the U R L Rewrite icon is selected.
  4. No painel Ações, no lado direito, clique em "Adicionar Regras...". Na caixa de diálogo "Adicionar Regras", selecione a "Regra em Branco" na categoria "Regras de Saída" e clique em OK:
    Screenshot of the Add rule dialog. Blank Rule under the Outbound Rules category is selected. Add Rules in the Actions pane is highlighted.

Agora você deve definir a regra de saída real. No Módulo de Reescrita de URL 2.0, uma regra de reescrita de saída é definida especificando as seguintes informações:

  • Nome da regra.
  • Uma pré-condição opcional que controla se essa regra deve ser aplicada a uma resposta.
  • O padrão a ser usado para corresponder à cadeia de caracteres na resposta.
  • Um conjunto opcional de condições.
  • A ação a ser executada se um padrão for correspondido e todas as verificações de condição forem bem-sucedidas.

Nomeando a regra

Na caixa de texto "Nome", insira um nome que identificará exclusivamente a regra, por exemplo: "Adicionar prefixo de aplicativo".

Definindo uma pré-condição

Uma pré-condição é usada para avaliar se a avaliação de regras de saída deve ser executada em uma resposta. Por exemplo, se uma regra que modifica o conteúdo HTML, somente as respostas HTTP com o cabeçalho do tipo conteúdo definido como "texto/html" devem ser avaliadas em relação a essa regra. A avaliação de regras de saída e a reescrita de conteúdo são uma operação intensiva de CPU que pode afetar negativamente o desempenho de um aplicativo Web. Portanto, use pré-condições para restringir os casos em que as regras de saída são aplicadas.

Como a regra que você está criando deve ser aplicada somente em respostas HTML, você definirá uma pré-condição que verifica se o tipo de conteúdo do cabeçalho de resposta HTTP é equial para "texto/html".

Para definir uma pré-condição:

  1. Na lista de pré-condições, selecione "<Criar Pré-condição...>".

  2. Isso levará você à caixa de diálogo do editor de pré-condição, na qual você precisará definir a pré-condição. Especifique as configurações de pré-condição da seguinte maneira:

    • Nome: "IsHTML"

    • Usando: "Expressões regulares"

    • Clique em "Adicionar" para abrir a caixa de diálogo "Adicionar condição". Nesta caixa de diálogo, especifique:

      • Entrada de condição: "{RESPONSE_CONTENT_TYPE}"

      • Verificar se a cadeia de caracteres de entrada: "Corresponde ao padrão"

      • Padrão: "^texto/html"

        Screenshot of the Add Pre condition dialog box. RESPONSE CONTENT TYPE is written in the Input column. Matches the pattern is written in the Type column. Text slash h t m l is written in the Pattern column.

  3. Clique em OK para salvar a pré-condição e retornar à página "Editar Regra".

Definindo um escopo correspondente

A regra de reescrita de saída pode operar no conteúdo de um cabeçalho HTTP ou no conteúdo do corpo da resposta. Essa regra precisa substituir links no conteúdo da resposta para que na lista suspensa Escopo Correspondente escolha Resposta.

Definindo um filtro de marca

Os filtros de marca são usados para definir o escopo do padrão correspondente somente a determinados elementos HTML, em vez de avaliar toda a resposta em relação ao padrão da regra. A correspondência de padrões é uma operação com uso muito intensivo de CPU e, se uma resposta inteira for avaliada em relação a um padrão, ela poderá diminuir significativamente o tempo de resposta do aplicativo Web. Os filtros de marca permitem especificar que a correspondência de padrões deve ser aplicada somente dentro do conteúdo de determinadas marcas HTML, reduzindo significativamente a quantidade de dados que precisam ser avaliados em relação ao padrão da expressão regular.

Para definir um filtro de marca, expanda a lista suspensa "Corresponder ao conteúdo dentro de:" e marque a caixa de seleção "Um (atributo href)".

Isso configura a regra para aplicar o padrão somente ao valor do atributo href do hiperlink, como no seguinte exemplo:

<a href="this string will be used for pattern matching">Some link</a>

Definindo um padrão

Na caixa de texto "Padrão", insira a seguinte cadeia de caracteres:

^/(.*)

Essa cadeia de caracteres é uma expressão regular que especifica que o padrão corresponderá a qualquer cadeia de caracteres do caminho de URL que começa com o símbolo "/".

Observe o uso de parênteses dentro do padrão. Esses parênteses criam um grupo de captura, que podem ser referenciados posteriormente na regra usando referências retroativas.

Definindo uma condição

Você precisará alterar os links no HTML de resposta somente se a resposta for do aplicativo de email ou folha de pagamento. Para verificar isso, você usará uma condição que analisa o caminho da URL solicitado pelo cliente. Além disso, você definirá um padrão de condição que captura a pasta do aplicativo da URL solicitada, para que essa regra possa reutilizá-la ao reescrever os links na resposta.

  1. Expanda a caixa do grupo de condições.
  2. Clique em "Adicionar..." para abrir a caixa de diálogo para definir condições.
  3. Em "Entrada de condição:" digite essa cadeia de caracteres: "{URL}". Isso configura o módulo de reescrita de URL para usar o caminho de URL que foi solicitado pelo cliente Web.
  4. Na caixa de combinação suspensa, selecione "Corresponde ao padrão".
  5. Insira ^/(webmail|payroll)/.* na caixa de texto Padrão. Essa expressão regular é usada para corresponder aos caminhos de URL que começam com /webmail ou /payroll. O parêntese dentro do padrão captura a parte da cadeia de caracteres de URL correspondente, de modo que ela possa ser utilizada ao construir a URL de substituição.
  6. Clique em OK para salvar a condição e retornar à interface do usuário "Adicionar Regra".

Definindo uma ação

Escolha o tipo de ação "Reescrever" listado na caixa de grupo "Ação". Na caixa de texto "Valor", insira a seguinte cadeia de caracteres:

/{C:1}/{R:1}

Essa cadeia de caracteres especifica o novo valor para o qual o endereço do link deve ser reescrito. O {C:1} é uma referência ao grupo de captura do padrão de condição e será substituído pelas cadeias de caracteres "email" ou "folha de pagamento". {R:1} é uma referência ao grupo de captura de padrão da regra e, neste caso específico, será substituído pelo caminho de URL original que foi usado no hiperlink.

Deixe valores padrão para todas as outras configurações. A página de propriedades "Editar Regra de Saída" deve ter a seguinte aparência:

Screenshot of the Edit Outbound Rule property page. The Match, Conditions, and Action categories are shown.

Salve a regra clicando na ação "Aplicar" no lado direito.

Para verificar a configuração das regras que acabamos de criar, abra um arquivo web.config localizado em %SystemDrive%\inetput\wwwroot\. Nesse arquivo, você deverá ver a seção <rewrite> que contém a definição da regra:

<rewrite>
    <rules>
        <rule name="Reverse Proxy to webmail" stopProcessing="true">
            <match url="^webmail/(.*)" />
            <action type="Rewrite" url="http://localhost:8081/{R:1}" />
        </rule>
        <rule name="Reverse Proxy to payroll" stopProcessing="true">
            <match url="^payroll/(.*)" />
            <action type="Rewrite" url="http://localhost:8082/{R:1}" />
        </rule>
    </rules>
    <outboundRules>
        <rule name="Add application prefix" preCondition="IsHTML">
            <match filterByTags="A" pattern="^/(.*)" />
            <conditions>
                <add input="{URL}" pattern="^/(webmail|payroll)/.*" />
            </conditions>
            <action type="Rewrite" value="/{C:1}/{R:1}" />
        </rule>
        <preConditions>
            <preCondition name="IsHTML">
                <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
            </preCondition>
        </preConditions>
    </outboundRules>
</rewrite>

Testando a regra

Para testar se a regra reescreve corretamente as URLs na resposta, abra um navegador da Web e faça uma solicitação para http://localhost/webmail/default.aspx ou http://localhost/payroll/default.aspx. Você deve ver que a regra de reescrita de saída alterou o link dentro da resposta HTML:

Screenshot of the Reverse Proxy Test Page Web Mail Application. The link at the bottom is h t t p colon slash slash local host slash web mail slash default dot a s p x.

Resumo

Neste passo a passo, você aprendeu a configurar o Módulo de Reescrita de URL e o Application Request Routing para implementar um cenário de proxy reverso. Além disso, você aprendeu a usar o novo recurso de reescrita de saída do Módulo de Reescrita de URL 2.0 para corrigir os links nas respostas dos aplicativos antes de servi-los ao cliente Web.

Observe que, ao usar o proxy reverso, muitas vezes também é necessário reescrever os cabeçalhos de resposta HTTP. Para saber como usar o Módulo de Reescrita de URL 2.0 para modificar o cabeçalho HTTP de resposta, consulte Modificando Cabeçalhos de Resposta HTTP.