使用 URL 重写 v2 和应用程序请求路由的反向代理

作者:Ruslan Yakushev

本演练指导你使用 URL 重写模块和应用程序请求路由 (ARR) 来为多个后端应用程序实现反向代理服务器

先决条件

若要运行本演练,必须满足以下要求:

  1. 启用了 ASP.NET 角色服务的 IIS 7 或更高版本。
  2. 已安装 URL 重写模块(如果你要完成有关响应重写的部分,则需要安装版本 2.0)
  3. 已安装应用程序请求路由版本 1.0 或版本 2.0

介绍

使用 URL 重写模块和应用程序请求路由,可以实现复杂且灵活的负载均衡和反向代理配置。 一种很常见的反向代理方案是通过 Internet 提供多个内部 Web 应用程序。 可通过 Internet 访问的 Web 服务器用作反向代理服务器,它接收 Web 请求,然后将其转发给多个 Intranet 应用程序进行处理:下图演示了反向代理方案的典型配置:

Diagram of a typical configuration for a reverse proxy scenario.

假设 ARR 服务器具有域名 http://contoso.com,可以使用以下 URL 访问每个 Web 应用程序:

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

http://contoso.com/webmail/default.aspx 发出请求时,ARR 会使用 URL http://webmail/default.aspx 将这些请求转发到内部服务器。 同样,对 http://contoso.com/payroll/ 的请求将转发到 http://payroll/default.aspx

此外,如果内部应用程序在其响应 HTML 中插入链接到这些应用程序中其他位置的链接,则应在响应返回到客户端之前修改这些链接。 例如,http://webmail/default.aspx 中的页面可能包含如下链接:

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

然后 ARR 服务器应将此链接更改为以下内容:

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

创建示例网站

为简单起见,将在单个服务器上实现要在本演练中使用的反向代理方案,IIS 的“默认网站”充当反向代理站点及 webmail 和 payroll 应用程序(托管在同一服务器上的单独 IIS 网站中)。

若要创建示例网站,请执行以下操作:

  1. 在以下文件夹中创建名为“webmail”和“payroll”的两个文件夹

    %SystemDrive%\inetpub\ folder.
    
  2. 创建名为“webmail”和“payroll”的两个 IIS 网站,它们指向 %SystemDrive%\inetpub\ 下的相应文件夹。 为每个站点使用不同的 IP 端口。
    可使用以下命令来创建站点:

    %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. 在以下文件夹中创建一个名为 default.aspx 的文件:

    %SystemDrive%\inetpub\webmail
    
  4. 复制以下 ASP.NET 标记,将其粘贴到文件中,并保存该文件:

    <%@ 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. 在以下文件夹中创建一个名为 default.aspx 的文件:

    %SystemDrive%\inetpub\payroll
    
  6. 复制以下 ASP.NET 标记,将其粘贴到文件中,并保存该文件:

    <%@ 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. 若要确保站点正常工作,请打开 Web 浏览并请求以下 URL:

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

为反向代理配置规则

在本演练部分,你将配置反向代理功能以使用创建的示例网站。

启用反向代理功能

默认情况下,反向代理功能处于禁用状态,因此必须首先启用它。

  1. 打开 IIS 管理器
  2. 在左侧树视图中选择一个服务器节点,然后单击“应用程序请求路由”功能:
    Screenshot of the I I S Manager. Different icons are shown. The Application Request Routing icon is highlighted.
  3. 选中“启用代理”复选框。 将此页上的所有其他设置保留默认值:
    Screenshot of the Application Request Routing page. Enable proxy is highlighted and selected.

为 Webmail 应用程序创建规则

创建两个重写规则:

  • 只要请求的 URL 路径以“webmail”开头,其中一个重写规则就会通过代理将任何请求中转到 http://localhost:8081/ 处的 webmail 应用程序。
  • 只要请求的 URL 路径以“payroll”开头,另一个重写规则就会通过代理将任何请求中转到 http://localhost:8082/ 处的 payroll 应用程序。

若要添加反向代理重写规则,请执行以下操作:

  1. 打开位于以下位置的 web.config 文件:

    %SystemDrive%\inetpub\wwwroot\
    
  2. /configuration/system.webServer 元素下添加以下内容,然后保存文件:

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

有关创建重写规则的详细信息,请参阅为 URL 重写模块创建重写规则

测试反向代理功能

打开 Web 浏览器并向 http://localhost/webmail/default.aspx 发出请求。 应会看到来自 webmail 测试页的响应。 另外,请向 http://localhost/payroll/default.aspx 发出请求。 应会看到来自 payroll 测试页的响应。

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.

请注意,在这两种情况下,响应内部的链接都指向 http://localhost/default.aspx。 如果你单击此链接,服务器将返回 404(找不到文件)响应。 在下一部分,你将了解如何创建出站规则来修复应用程序生成的响应 HTML 的链接。

为响应重写配置规则

本文档部分适用于 IIS 7 的 URL 重写模块版本 2.0

你将定义一个出站规则来替换响应 HTML 中的所有链接,如下所示:

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

将被替换为:

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

(如果响应来自 webmail 应用程序)

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

(如果响应来自 payroll 应用程序)

警告

当响应头或响应内容被出站重写规则修改时,应格外小心,以确保插入响应中的文本不包含任何客户端可执行代码,否则可能会导致跨站点脚本漏洞。 当重写规则使用不受信任的数据(例如 HTTP 标头或查询字符串)来生成要插入到 HTTP 响应中的字符串时,这一点尤其重要。 在这种情况下,替换字符串应使用 HtmlEncode 函数进行 HTML 编码,例如:

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

若要创建规则,请执行以下步骤:

  1. 转到 IIS 管理器
  2. 选择“默认网站”
  3. 在功能视图中,单击“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. 在右侧的操作窗格中,单击“添加规则...”。 在“添加规则”对话框中,选择“出站规则”类别下的“空白规则”,然后单击“确定”:
    Screenshot of the Add rule dialog. Blank Rule under the Outbound Rules category is selected. Add Rules in the Actions pane is highlighted.

现在必须定义实际的出站规则。 在 URL 重写模块 2.0 中,出站重写规则是通过指定以下信息来定义的:

  • 规则名称。
  • 用于控制是否应将此规则应用于响应的可选前提条件。
  • 用于匹配响应中的字符串的模式。
  • 一组可选条件。
  • 当模式匹配并且所有条件检查都成功时要执行的操作。

为规则命名

在“名称”文本框中输入用于唯一标识规则的名称,例如:“添加应用程序前缀”。

定义前提条件

前提条件用于评估是否应对响应执行出站规则评估。 例如,如果修改 HTML 内容的规则,则仅应根据此规则评估内容类型标头设置为“text/html”的 HTTP 响应。 出站规则评估和内容重写是 CPU 密集型操作,可能会对 Web 应用程序的性能产生负面影响。 因此,在应用出站规则时,请使用前提条件来缩小范围。

由于创建的规则应仅应用于 HTML 响应,因此需要定义一个前提条件来检查 HTTP 响应头 content-type 是否等于“text/html”。

若要定义前提条件,请执行以下操作:

  1. 在“前提条件”列表中,选择“<创建新的前提条件...>”。

  2. 随即你会转到“前提条件编辑器”对话框,需要在其中定义前提条件。 如下所述指定前提条件设置:

    • 名称:“IsHTML”

    • 使用:“正则表达式”

    • 单击“添加”以显示“添加条件”对话框。 在此对话框中,指定:

      • 条件输入:“{RESPONSE_CONTENT_TYPE}”

      • 检查输入字符串:“匹配模式”

      • 模式:“^text/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. 单击“确定”保存前提条件并返回到“编辑规则”页。

定义匹配范围

出站重写规则可以对 HTTP 标头的内容或响应正文内容进行操作。 该规则需要替换响应内容中的链接,因此请在“匹配范围”下拉列表中选择“响应”

定义标记筛选器

标记筛选器用于将模式匹配范围限定为仅与特定 HTML 元素匹配,而不是根据规则的模式评估整个响应。 模式匹配是一项非常消耗 CPU 资源的操作,如果根据模式评估整个响应,可能会显著减慢 Web 应用程序的响应速度。 标记筛选器允许指定仅在某些 HTML 标记的内容中应用模式匹配,从而显著减少必须根据正则表达式模式进行评估的数据量。

若要定义标记筛选器,请展开下拉列表“匹配以下范围的内容:”,然后选中复选框“A (href 属性)”

这会将规则设置为仅将模式应用于超链接的 href 属性值,如以下示例所示:

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

定义模式

在“模式”文本框中输入以下字符串:

^/(.*)

此字符串是一个正则表达式,指定模式将匹配任何以“/”符号开头的 URL 路径字符串。

请注意模式中括号的用法。 这些括号创建一个捕获组,稍后可以使用反向引用在规则中引用该捕获组。

定义条件

仅当响应来自 webmail 或 payroll 应用程序时,才需要更改响应 HTML 中的链接。 检查是否要使用分析客户端所请求 URL 路径的条件。 另外定义一个条件模式,用于从请求的 URL 捕获应用程序文件夹,以便规则在重写响应中的链接时可以重用该模式。

  1. 展开条件组框。
  2. 单击“添加...”按钮,显示用于定义条件的对话框的。
  3. 对于“条件输入:”,请输入以下字符串:“{URL}”。 这会将 URL 重写模块配置为使用 Web 客户端请求的 URL 路径。
  4. 在下拉列表组合框中,选择“匹配模式”
  5. 在“模式”文本框中输入 ^/(webmail|payroll)/.*。 此正则表达式用于匹配以 /webmail/payroll 开头的 URL 路径。 模式中的括号捕获所匹配的 URL 字符串的一部分,以便可在构造替换 URL 时使用它。
  6. 单击“确定”保存条件并返回到“添加规则”UI。

定义操作

选择“操作”组框中列出的“重写”操作类型。 在“值”文本框中,输入以下字符串:

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

此字符串指定链接地址应重写为的新值。 {C:1} 是对条件模式捕获组的反向引用,它将由“webmail”或“payroll”字符串替换。 {R:1} 是对规则模式捕获组的反向引用,在这种特定的情况下,它将替换为超链接中使用的原始 URL 路径。

保留所有其他设置的默认值。 “编辑出站规则”属性页应如下所示:

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

单击右侧的“应用”操作保存规则。

若要检查我们刚刚创建的规则的配置,请打开位于 %SystemDrive%\inetput\wwwroot\ 中的 web.config 文件。 在此文件中,应会看到包含此规则定义的 <rewrite> 部分:

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

测试规则

若要测试规则是否在响应中正确重写 URL,请打开 Web 浏览器并向 http://localhost/webmail/default.aspxhttp://localhost/payroll/default.aspx 发出请求。 应会看到出站重写规则已更改 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.

总结

在本演练中,你已了解如何配置 URL 重写模块和应用程序请求路由来实现反向代理方案。 此外,你还了解了如何使用 URL 重写模块 2.0 的新出站重写功能来修复应用程序响应中的链接,然后将其提供给 Web 客户端。

请注意,使用反向代理时,通常还需要重写 HTTP 响应头。 若要了解如何使用 URL 重写模块 2.0 修改响应 HTTP 标头,请参阅修改 HTTP 响应头