IIS 作为反向代理:为 ASP.NET Core Kestrel 应用保驾护航

摘要

ASP.NET Core 应用的生产部署中,虽然 Kestrel 是一个高性能的 Web 服务器,但通常不建议直接暴露给公网。本文将详细介绍如何利用 IIS (Internet Information Services) 作为反向代理服务器,将来自客户端的请求安全、高效地转发给后端的 Kestrel 服务器,并处理相关的配置和注意事项。

目录
  1. 为何需要 IIS 作为反向代理?
  2. 准备工作:安装 Application Request Routing (ARR)
  3. 配置 IIS:启用代理功能
  4. 配置 URL 重写规则:实现请求转发
  5. 配置 ASP.NET Core:处理转发的头信息
  6. 部署与验证
  7. 常见问题与最佳实践
  8. 总结

1. 为何需要 IIS 作为反向代理?

虽然 Kestrel 性能卓越,但在生产环境中,直接将 Kestrel 暴露给互联网通常不是一个好主意,原因如下:

  • 安全性增强: IIS 作为前端代理,可以提供额外的安全层,例如防火墙规则、IP 地址筛选、请求过滤、DDoS 缓解(配合其他工具)等。它能处理一些恶意请求,保护后端的 Kestrel 应用免受直接攻击。
  • SSL 终止 (SSL Offloading): IIS 可以集中管理和终止 HTTPS 连接,卸载 SSL 握手和加密/解密的计算负担,然后将解密后的 HTTP 请求转发给 Kestrel。这可以提高 Kestrel 的处理效率。
  • 静态文件服务: IIS 在服务静态文件(如 CSS、JavaScript、图片)方面通常比 Kestrel 更高效。IIS 可以直接处理这些请求,而不必将其传递给 Kestrel,从而节省后端资源。
  • 负载均衡: 如果需要部署多个 Kestrel 实例,IIS (或 ARR) 可以作为负载均衡器,将请求分发到不同的后端实例。
  • 缓存: IIS 可以配置缓存规则,缓存响应内容,减少后端 Kestrel 的压力。
  • 成熟稳定的生态: IIS 是 Windows 平台下非常成熟和稳定的 Web 服务器,拥有丰富的管理工具和社区支持。

因此,在 Windows 服务器上,使用 IIS 作为反向代理,将请求转发给 Kestrel,是一种标准且推荐的部署模式。


2. 准备工作:安装 Application Request Routing (ARR)

IIS 本身并不具备反向代理功能,需要安装 Application Request Routing (ARR) 模块来实现。

步骤:

  1. 下载 ARR:

    • 打开浏览器,访问 Microsoft 官方下载中心。
    • 搜索 "Application Request Routing" 或直接访问下载页面(例如,搜索 "Microsoft Application Request Routing 3.0")。
    • 下载适用于你的 Windows 版本和系统架构(通常是 x64)的安装程序,例如 Application Request Routing x.x.x-x64.msi
  2. 安装 ARR:

    • 双击下载的 .msi 文件。
    • 遵循安装向导提示,一路点击 "Next" 或 "Accept" 直至完成安装。通常不需要修改任何设置。
    • 安装完成后,建议重启 IIS 管理器或执行 iisreset 命令以确保模块正确加载。

注意: 安装 ARR 通常还依赖于 URL Rewrite Module。如果安装过程中提示缺少 URL Rewrite,也需要先安装它。


3. 配置 IIS:启用代理功能

  1. 打开 IIS 管理器:

    • 在 Windows 服务器上,以管理员身份打开 "Internet Information Services (IIS) Manager"。
  2. 选择服务器节点:

    • 在左侧的连接树中,点击顶层的服务器名称(例如 WIN-SERVERNAME)。
  3. 打开 Application Request Routing Cache:

    • 在中央的"功能视图"中,找到并双击 "Application Request Routing Cache" 图标。
  4. 配置服务器代理设置:

    • 在右侧的"操作"面板中,点击 "Server Proxy Settings..."。
    • 在弹出的窗口中:
      • 勾选 "Enable proxy" 复选框。 这是启用反向代理功能的核心步骤
      • 取消勾选 "Reverse rewrite host in response headers" (推荐)。 这个选项会修改后端服务器返回的响应头中的 LocationSet-Cookie 等字段中的主机名。通常,我们希望这些响应头保持与客户端请求的主机名一致,所以取消勾选它。如果勾选,可能会导致重定向或 Cookie 问题。
      • 取消勾选 "Enable SSL offloading" (除非明确需要)。 如果 IIS 和 Kestrel 之间使用 HTTPS,或者你不希望 IIS 处理 SSL 终止,应取消勾选此项。通常,IIS 和 Kestrel 之间使用 HTTP。
    • 点击 "Apply" 按钮保存设置。

此时,IIS 已经具备了代理功能,但还没有具体的规则来指导它如何转发请求。


4. 配置 URL 重写规则:实现请求转发

现在需要为你的网站创建一个 URL 重写规则,告诉 IIS 将哪些请求转发给 Kestrel。

  1. 选择目标网站:

    • 在 IIS 管理器的左侧连接树中,展开服务器节点,找到并点击你想要配置反向代理的网站(例如 Default Web Site 或你创建的自定义站点)。
  2. 打开 URL Rewrite:

    • 在该网站的"功能视图"中,双击 "URL Rewrite" 图标。
  3. 添加规则:

    • 在右侧的"操作"面板中,点击 "Add Rule(s)..."。
  4. 选择规则类型:

    • 在弹出的对话框中,选择 "Inbound Rules" 下的 "Blank rule"(空白规则)。这允许我们手动配置规则。
  5. 配置规则详情:

    • Name: 为规则起个名字,例如 ProxyToKestrelKestrelBackendRule
    • Match URL:
      • Requested URL: 选择 Matches the Pattern
      • Using: 选择 Regular Expressions(正则表达式)或 Wildcards(通配符),正则表达式更灵活。
      • Pattern: 输入 .* (这是一个正则表达式,表示匹配任何字符组成的任意长度的字符串,即匹配所有传入的 URL 路径)。如果你想只为特定路径(如 /api)配置代理,可以将模式改为 ^api/(.*) (注意,如果使用通配符,可能是 api/*)。
      • Ignore case: 通常勾选。
    • Conditions: (可选) 如果需要根据请求头、查询字符串等添加更复杂的条件,可以在此处添加。对于简单的全站代理,通常留空。
    • Server Variables: (通常留空)。
    • Action:
      • Action Type: 选择 Rewrite。虽然名称是 "Rewrite",但由于 ARR 已启用代理,这里配置的 URL 实际上会被转发(Proxy)到后端服务器。注意:如果只是想重写 URL 而不是代理,会选择 Rewrite;如果想重定向,会选择 Redirect
      • Rewrite URL: 输入后端 Kestrel 服务器的地址。例如 http://127.0.0.1:5000/{R:0}
        • http://: 协议,通常是 http (因为 IIS 和 Kestrel 之间通常是 HTTP)。
        • 127.0.0.1: Kestrel 服务器监听的 IP 地址。如果你的 Kestrel 监听 localhost0.0.0.0,通常 127.0.0.0.1localhost 都可以。如果你的 Kestrel 在另一台机器上,填入那台机器的 IP。
        • :5000: Kestrel 服务器监听的端口。请根据你的 Kestrel 应用实际监听的端口进行修改。
        • /{R:0}: 这是占位符,{R:0} 表示匹配到的整个 URL 路径(即 Pattern .* 匹配的部分)。这确保了原始请求的路径被完整地转发给 Kestrel。如果你的 Pattern 是 ^api/(.*),那么 /{R:1} 会捕获括号内的部分(即 (.*)),你可以根据需要调整。
  6. 保存规则:

    • 点击 "OK" 保存规则。

现在,你为选定的网站创建了一个反向代理规则,它会将所有匹配 .* 的请求转发到 http://127.0.0.1:5000/


5. 配置 ASP.NET Core:处理转发的头信息

当 IIS 作为反向代理时,它会修改原始请求的一些信息,如 Host 头、协议 (HTTPS -> HTTP)、客户端真实 IP 地址 (X-Forwarded-For)。为了让 ASP.NET Core 应用能够感知到原始请求的真实信息(如客户端 IP、是否使用 HTTPS),需要在 ASP.NET Core 应用中配置 ForwardedHeaders 中间件。

在你的 ASP.NET Core 项目的 Program.cs 文件中:

复制代码
using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// ... 其他服务配置 ...

var app = builder.Build();

// --- 配置 Forwarded Headers ---
// 注意:必须在 UseRouting 之前调用
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    // 指定要转发的头信息
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost,

    // **安全重要**:指定哪些代理服务器是可信的。
    // 在生产环境中,必须明确列出 IIS 服务器的 IP 地址。
    // 如果不设置 KnownProxies/KnownNetworks,所有请求都会被认为是代理请求,这可能导致安全问题。
    // 如果 IIS 和 Kestrel 在同一台机器上,IIS 的 IP 就是 127.0.0.1
    // 如果在不同机器上,需要设置 IIS 服务器的 IP 地址。
    KnownProxies = { IPAddress.Parse("127.0.0.1") }, // 根据实际情况修改 IP
    // 或者,如果 IIS 在一个特定网段,可以使用 KnownNetworks
    // KnownNetworks = { new IPNetwork(IPAddress.Parse("192.168.1.0"), 24) } // 示例网段
});
// --------------------------

app.UseRouting();

// ... 其他中间件配置 ...

app.Run();
  • ForwardedHeaders: 指定要处理的转发头。XForwardedFor 用于客户端 IP,XForwardedProto 用于原始协议 (HTTP/HTTPS),XForwardedHost 用于原始 Host。
  • KnownProxies / KnownNetworks: 极其重要! 必须明确指定哪些 IP 地址或网络是可信的代理服务器。否则,任何客户端都可以伪造 X-Forwarded-* 头来欺骗应用,造成安全风险。在 IIS 作为代理的场景下,这里应该填入 IIS 服务器的 IP 地址。

6. 部署与验证

  1. 部署 ASP.NET Core 应用:

    • 构建你的 ASP.NET Core 应用(例如 dotnet publish -c Release -o ./publish)。
    • 将发布的文件部署到 IIS 站点指向的物理路径(或创建虚拟目录指向发布路径)。
    • 确保你的 appsettings.Production.json (或 appsettings.json) 中的 urls 设置为 Kestrel 监听的地址和端口,例如 "http://127.0.0.1:5000""http://localhost:5000"。或者,依赖环境变量或命令行参数来指定端口。
  2. 启动 Kestrel 应用:

    • 通常,当 IIS 站点第一次被访问时,如果配置了 ASP.NET Core 模块 (AspNetCoreModule),它会自动启动你的 ASP.NET Core 应用。确保 web.config 文件(发布时自动生成)正确配置了启动命令。
  3. 访问 IIS 站点:

    • 打开浏览器,访问你的 IIS 站点地址(例如 https://yourdomain.comhttp://yoursite.local)。
    • 如果一切配置正确,IIS 会接收请求,通过 URL 重写规则将其转发给 Kestrel (http://127.0.0.1:5000),Kestrel 处理请求并返回响应,响应再通过 IIS 返回给客户端。
  4. 验证:

    • 检查 ASP.NET Core 应用的日志,看是否有请求到达。
    • 检查 IIS 日志,看是否有请求记录。
    • ASP.NET Core 应用中,检查 HttpContext.Connection.RemoteIpAddress 是否反映了真实的客户端 IP(而不是 127.0.0.1)。
    • 检查 HttpContext.Request.Scheme 是否反映了原始请求的协议(HTTPS 或 HTTP)。

7. 常见问题与最佳实践

  • 问题:访问 IIS 站点时出现 502 Bad Gateway 错误。

    • 原因: 通常是 IIS 无法连接到后端 Kestrel 服务器。
    • 排查: 检查 URL 重写规则中的目标地址 (http://127.0.0.1:5000) 是否正确,Kestrel 应用是否正在该地址和端口上运行,防火墙是否阻止了内部连接。
  • 问题:应用无法获取客户端的真实 IP 地址。

    • 原因: ForwardedHeaders 中间件未配置或 KnownProxies 设置不正确。
    • 解决: 确保 Program.cs 中正确配置了 ForwardedHeaders,并设置了可信的代理 IP。
  • 问题:HTTPS 重定向或 URL 生成不正确。

    • 原因: ForwardedHeaders 未配置 XForwardedProto,导致应用不知道原始请求是 HTTPS。
    • 解决: 确保 ForwardedHeadersOptions 中包含 ForwardedHeaders.XForwardedProto
  • 最佳实践:

    • 安全: 严格配置 KnownProxiesKnownNetworks
    • 性能: 启用 IIS 的静态文件缓存功能。
    • 日志: 同时关注 IIS 和 ASP.NET Core 应用的日志,便于调试。
    • 健康检查: 考虑为 Kestrel 应用添加健康检查端点,并在 IIS/ARR 中配置健康探测。

8. 总结

通过安装 ARR 模块、启用代理功能、配置 URL 重写规则,并在 ASP.NET Core 应用中正确处理转发的头信息,我们可以成功地将 IIS 配置为 ASP.NET Core Kestrel 应用的反向代理。这种配置模式不仅提升了应用的安全性和性能,还充分利用了 IIS 作为成熟 Web 服务器的优势,是 Windows 服务器环境下部署 ASP.NET Core 应用的推荐方式。


相关推荐
麦兜*2 小时前
SpringBoot 3.x新特性全面解析:从Java 17支持到GraalVM原生镜像
java·spring boot·后端
你知道“铁甲小宝”吗丶2 小时前
【第2章】第一个Go程序
后端·go
小北方城市网3 小时前
Spring Boot 接口开发实战:RESTful 规范、参数校验与全局异常处理
java·jvm·数据库·spring boot·后端·python·mysql
千寻技术帮3 小时前
10399_基于SpringBoot的智慧养老院管理系统
java·spring boot·后端·源码·安装·代码
飞升不如收破烂~3 小时前
# Spring Boot 跨域请求未到达后端问题排查记录
java·spring boot·后端
短剑重铸之日4 小时前
《RocketMQ研读》面试篇
java·后端·面试·职场和发展·rocketmq
changzehai4 小时前
Rust + VSCode + probe-rs搭建stm32-rs嵌入式开发调试环境
vscode·后端·stm32·rust·嵌入式·probe-rs
终端域名4 小时前
如何选择有利于品牌宣传的网站域名
java·后端·struts·数字货币域名·网站域名
拽着尾巴的鱼儿4 小时前
Spring:定时任务@Scheduled cron 的实现原理
java·后端·spring