摘要
在 ASP.NET Core 应用的生产部署中,虽然 Kestrel 是一个高性能的 Web 服务器,但通常不建议直接暴露给公网。本文将详细介绍如何利用 IIS (Internet Information Services) 作为反向代理服务器,将来自客户端的请求安全、高效地转发给后端的 Kestrel 服务器,并处理相关的配置和注意事项。
目录
- 为何需要 IIS 作为反向代理?
- 准备工作:安装 Application Request Routing (ARR)
- 配置 IIS:启用代理功能
- 配置 URL 重写规则:实现请求转发
- 配置 ASP.NET Core:处理转发的头信息
- 部署与验证
- 常见问题与最佳实践
- 总结
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) 模块来实现。
步骤:
-
下载 ARR:
- 打开浏览器,访问 Microsoft 官方下载中心。
- 搜索 "Application Request Routing" 或直接访问下载页面(例如,搜索 "Microsoft Application Request Routing 3.0")。
- 下载适用于你的 Windows 版本和系统架构(通常是 x64)的安装程序,例如
Application Request Routing x.x.x-x64.msi。
-
安装 ARR:
- 双击下载的
.msi文件。 - 遵循安装向导提示,一路点击 "Next" 或 "Accept" 直至完成安装。通常不需要修改任何设置。
- 安装完成后,建议重启 IIS 管理器或执行
iisreset命令以确保模块正确加载。
- 双击下载的
注意: 安装 ARR 通常还依赖于 URL Rewrite Module。如果安装过程中提示缺少 URL Rewrite,也需要先安装它。
3. 配置 IIS:启用代理功能
-
打开 IIS 管理器:
- 在 Windows 服务器上,以管理员身份打开 "Internet Information Services (IIS) Manager"。
-
选择服务器节点:
- 在左侧的连接树中,点击顶层的服务器名称(例如
WIN-SERVERNAME)。
- 在左侧的连接树中,点击顶层的服务器名称(例如
-
打开 Application Request Routing Cache:
- 在中央的"功能视图"中,找到并双击 "Application Request Routing Cache" 图标。
-
配置服务器代理设置:
- 在右侧的"操作"面板中,点击 "Server Proxy Settings..."。
- 在弹出的窗口中:
- 勾选 "Enable proxy" 复选框。 这是启用反向代理功能的核心步骤!
- 取消勾选 "Reverse rewrite host in response headers" (推荐)。 这个选项会修改后端服务器返回的响应头中的
Location或Set-Cookie等字段中的主机名。通常,我们希望这些响应头保持与客户端请求的主机名一致,所以取消勾选它。如果勾选,可能会导致重定向或 Cookie 问题。 - 取消勾选 "Enable SSL offloading" (除非明确需要)。 如果 IIS 和 Kestrel 之间使用 HTTPS,或者你不希望 IIS 处理 SSL 终止,应取消勾选此项。通常,IIS 和 Kestrel 之间使用 HTTP。
- 点击 "Apply" 按钮保存设置。
此时,IIS 已经具备了代理功能,但还没有具体的规则来指导它如何转发请求。
4. 配置 URL 重写规则:实现请求转发
现在需要为你的网站创建一个 URL 重写规则,告诉 IIS 将哪些请求转发给 Kestrel。
-
选择目标网站:
- 在 IIS 管理器的左侧连接树中,展开服务器节点,找到并点击你想要配置反向代理的网站(例如
Default Web Site或你创建的自定义站点)。
- 在 IIS 管理器的左侧连接树中,展开服务器节点,找到并点击你想要配置反向代理的网站(例如
-
打开 URL Rewrite:
- 在该网站的"功能视图"中,双击 "URL Rewrite" 图标。
-
添加规则:
- 在右侧的"操作"面板中,点击 "Add Rule(s)..."。
-
选择规则类型:
- 在弹出的对话框中,选择 "Inbound Rules" 下的 "Blank rule"(空白规则)。这允许我们手动配置规则。
-
配置规则详情:
- Name: 为规则起个名字,例如
ProxyToKestrel或KestrelBackendRule。 - Match URL:
- Requested URL: 选择
Matches the Pattern。 - Using: 选择
Regular Expressions(正则表达式)或Wildcards(通配符),正则表达式更灵活。 - Pattern: 输入
.*(这是一个正则表达式,表示匹配任何字符组成的任意长度的字符串,即匹配所有传入的 URL 路径)。如果你想只为特定路径(如/api)配置代理,可以将模式改为^api/(.*)(注意,如果使用通配符,可能是api/*)。 - Ignore case: 通常勾选。
- Requested URL: 选择
- 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 监听localhost或0.0.0.0,通常127.0.0.0.1或localhost都可以。如果你的 Kestrel 在另一台机器上,填入那台机器的 IP。:5000: Kestrel 服务器监听的端口。请根据你的 Kestrel 应用实际监听的端口进行修改。/{R:0}: 这是占位符,{R:0}表示匹配到的整个 URL 路径(即 Pattern.*匹配的部分)。这确保了原始请求的路径被完整地转发给 Kestrel。如果你的 Pattern 是^api/(.*),那么/{R:1}会捕获括号内的部分(即(.*)),你可以根据需要调整。
- Action Type: 选择
- Name: 为规则起个名字,例如
-
保存规则:
- 点击 "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. 部署与验证
-
部署 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"。或者,依赖环境变量或命令行参数来指定端口。
- 构建你的 ASP.NET Core 应用(例如
-
启动 Kestrel 应用:
-
访问 IIS 站点:
- 打开浏览器,访问你的 IIS 站点地址(例如
https://yourdomain.com或http://yoursite.local)。 - 如果一切配置正确,IIS 会接收请求,通过 URL 重写规则将其转发给 Kestrel (
http://127.0.0.1:5000),Kestrel 处理请求并返回响应,响应再通过 IIS 返回给客户端。
- 打开浏览器,访问你的 IIS 站点地址(例如
-
验证:
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。
- 原因:
-
最佳实践:
- 安全: 严格配置
KnownProxies或KnownNetworks。 - 性能: 启用 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 应用的推荐方式。