Windows Server 2019下IIS反向代理与URL重写实战部署
创始人
2025-11-27
0

简介:在Windows Server 2019环境中,通过IIS部署反向代理并配置URL Rewrite模块,是实现Vue.js等单页应用高效访问的关键技术。本文详细介绍了如何安装和配置IIS的Rewrite模块与反向代理功能,涵盖从环境准备、模块安装到规则设置的完整流程。该方案可有效支持SPA路由处理、提升安全性,并实现请求转发与路径优化,适用于前端项目在生产环境中的稳定部署。

IIS反向代理与URL重写深度实践:从零搭建高可用网关

你有没有遇到过这样的场景?

前端同事跑来抱怨:“线上访问 /user/profile 报404,但本地开发一切正常!”
后端工程师一脸无辜:“我服务根本没收到请求啊!”
运维拍桌子:“这锅我不背,IIS日志里压根没有这条路径!”

💥 问题出在哪?—— 很可能就是反向代理和URL重写的配置没整明白!

别急,今天我们不讲理论套话,直接带你 从零开始,在 Windows Server 2019 上亲手打造一套生产级的 IIS 反向代理网关 。不仅解决 SPA 路由、API 转发、HTTPS 强制跳转这些“经典难题”,还会深入剖析底层机制,让你真正搞懂每一条规则背后的逻辑。

准备好了吗?☕️ 倒杯咖啡,咱们开干!


🛠️ 一、为什么是 IIS + ARR + URL Rewrite 这个组合?

在很多人印象中,Nginx 才是反向代理的王者,那为啥还要用 IIS?

因为现实世界不是理想国 😅

很多企业尤其是政府、金融、国企系统,服务器生态被微软全家桶牢牢绑定:AD域控、.NET应用、SQL Server……在这种环境下部署 Nginx,光审批流程就能拖半年。而 IIS 作为 Windows 原生组件,天然具备以下优势:

  • ✅ 无缝集成 Active Directory 权限体系

  • ✅ 支持 ASP.NET、WCF、.NET Core 混合部署

  • ✅ 图形化管理界面友好,适合传统IT团队维护

  • ✅ 通过 Application Request Routing(ARR)模块可轻松实现负载均衡与健康检查

更重要的是, ARR + URL Rewrite 的组合拳,完全可以媲美 Nginx 的核心功能 ,而且配置方式更直观(尤其对Windows管理员而言)。

所以,这不是“最好”的选择,而是 最现实、最稳妥、最容易落地的选择 。


🔧 二、环境准备:干净的 Windows Server 2019 实例

我们假设你现在拿到一台全新的 Windows Server 2019 Datacenter 服务器,IP 是 192.168.1.100 ,目标是把它变成一个能对外提供服务的反向代理网关。

1. 安装 IIS 角色(图形化 or PowerShell?我都给你)

虽然图形界面操作简单,但在自动化运维时代, PowerShell 才是王道 。不过为了照顾不同习惯的同学,两种方式都列出来。

方法一:使用“服务器管理器”一步步点(适合新手)

打开“服务器管理器” → “添加角色和功能” → 下一步到底 → 在“服务器角色”勾选 Web 服务器 (IIS) 。

重点来了!不要只勾个“IIS”就完事,一定要展开子组件,至少选上这些:

子组件作用说明
常见 HTTP 功能包括默认文档、错误页等基础行为
应用程序开发启用 ASP.NET、CGI、ISAPI 扩展支持(哪怕你不跑ASP.NET也要勾,否则某些模块加载失败)
健康与诊断失败请求跟踪(FREB)、日志记录必备
安全性SSL证书绑定、IP限制、Windows身份验证
性能静态/动态内容压缩,提升传输效率
管理工具IIS管理控制台(MMC Snap-in),必须勾!

安装完成后,可以在开始菜单搜索“IIS管理器”启动。

⚠️ 小贴士:如果后续要托管 .NET Core 应用,记得单独安装 .NET Core Hosting Bundle ,否则会报502.5进程启动错误。

方法二:一行 PowerShell 快速搞定(推荐用于批量部署)
Install-WindowsFeature Web-Server, Web-Mgmt-Tools, Web-Asp-Net47, Web-Net-Ext45, `
                       Web-ISAPI-Ext, Web-ISAPI-Filter, Web-CGI, Web-Http-Errors, `
                       Web-Static-Content, Web-Default-Doc, Web-Dir-Browsing, `
                       Web-Http-Logging, Web-Request-Monitor, Web-Stat-Compression, `
                       Web-Security, Web-Filtering, Web-Performance, Web-Mgmt-Service

执行完这个命令,IIS 核心功能就齐了。比鼠标点十几次快多了吧?😎

2. 开启远程管理(再也不用手动登录服务器桌面)

谁愿意天天 RDP 登录服务器调配置?太low了!我们应该像专业运维那样,远程连接管理。

先确保安装了 IIS 管理服务 (上面的 PowerShell 已包含 Web-Mgmt-Service )。

然后启用并设置自动启动:

Start-Service WMSVC
Set-Service WMSVC -StartupType Automatic

接下来配置管理服务参数:

# 允许远程连接 + 绑定SSL证书(强烈建议)
Import-PfxCertificate -FilePath "C:\certs\proxy.example.com.pfx" `
                      -CertStoreLocation Cert:\LocalMachine\My `
                      -Password (ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force)

# 设置监听端口8172(默认)
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1 -PropertyType DWORD
Set-Service WMSVC -StartupType Automatic
Restart-Service WMSVC

最后创建一个专用管理账户(别用Administrator!):

New-LocalUser -Name "iisadmin" -Password (ConvertTo-SecureString "S3cureP@ss!" -AsPlainText -Force)
Add-LocalGroupMember -Group "Administrators" -Member "iisadmin"

客户端安装 IIS Manager for Remote Administration 插件后,就可以通过 https://192.168.1.100:8172 安全地远程管理啦 ✅

3. 验证基本连通性:别让防火墙坑了你

安装完别急着下一步,先确认最基本的访问是否通畅。

# 检查IIS主服务状态
Get-Service W3SVC

# 输出应为 Running
# Status  Name               DisplayName
# ------  ----               -----------
# Running W3SVC              World Wide Web Publishing Service

如果没运行,手动启动:

Start-Service W3SVC

接着开放防火墙端口:

New-NetFirewallRule -DisplayName "Allow HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

测试本地访问:

Test-NetConnection -ComputerName localhost -Port 80

成功的话你会看到:

TcpTestSucceeded : True

浏览器打开 http://localhost 或 http://192.168.1.100 ,看到熟悉的 IIS 欢迎页面 ✔️

💡 如果看不到页面,优先查三件事:

  1. IIS 服务是否运行?

  2. 防火墙是否放行?

  3. 默认站点是否已启动?(在IIS管理器里右键“Default Web Site”→“启动”)


🧩 三、核心组件安装:让 IIS 拥有“转发大脑”

默认的 IIS 只是一个静态文件服务器,想让它当反向代理,必须装两个关键插件:

组件作用
URL Rewrite Module解析请求路径,做重写或跳转
Application Request Routing (ARR)实际执行请求转发、负载均衡、健康检查

这两个模块的关系就像是: Rewrite 是交警,负责指挥车流方向;ARR 是高速公路本身,负责把车送到目的地 🚗

1. 安装 URL Rewrite 模块

下载地址: https://www.iis.net/downloads/microsoft/url-rewrite

选择 rewrite_amd64.msi ,双击安装即可,无需重启。

验证是否安装成功:

Get-WebGlobalModule | Where-Object { $_.Name -like "*rewrite*" }

你应该看到类似输出:

Name             : RewriteModuleImage            : C:\Windows\System32\inetsrv\rewrite.dllPreCondition     : bitness64

此时打开 IIS 箆理器,在任意网站或服务器节点的功能视图中,应该能看到 “URL重写” 图标出现了 ✅

2. 安装 Application Request Routing (ARR)

下载地址: https://www.iis.net/downloads/microsoft/application-request-routing

运行 requestRouter_amd64.msi 安装。

⚠️ 注意: 必须先安装 URL Rewrite,否则 ARR 会提示依赖缺失!

安装完成后,在服务器节点的功能视图中会出现一个新的图标 —— “代理” 和 “服务器场” 。

验证 ARR 是否加载:

Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" -Filter system.webServer/proxy -Name enabled

初始返回值可能是 False ,因为我们还没启用它。

也可以查注册表确认版本:

(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\IIS Extensions\ARR').Version
# 正常应返回如 3.0
3. 自动化检测脚本:一键排查模块状态

为了避免遗漏,建议写个检查脚本:

$requiredModules = @("RewriteModule", "ApplicationRequestRouting")

foreach ($mod in $requiredModules) {
    $loaded = Get-WebGlobalModule | Where-Object Name -eq $mod
    if ($loaded) {
        Write-Host "✅ $mod 加载成功" -ForegroundColor Green
    } else {
        Write-Warning "❌ $mod 未检测到,请重新安装!"
    }
}

运行一下,全绿才算过关 👍


⚙️ 四、反向代理初始化配置:打好性能与安全基础

现在 IIS 已经“武装到牙齿”,但还不能立刻投入使用。我们需要做一些全局设置,避免踩坑。

1. 关闭 ARR 缓存(调试阶段必做!)

ARR 默认开启响应缓存,听起来挺美好,但在调试时简直是噩梦:改了后端代码刷新无效,还以为是自己写错了……

所以初期务必关闭缓存:

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/proxy" `
                             -Name enabled -Value True

# 关闭缓存
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/caching" `
                             -Name enabled -Value False

或者在 IIS 管理器中操作:

  1. 选中服务器节点

  2. 双击“代理”

  3. 点击右侧“服务器代理设置”

  4. 取消勾选“启用缓存”

  5. 点“应用”

这样所有请求都会直通后端,便于定位问题。

2. 设置合理的超时时间(告别 502 Bad Gateway)

很多 502 错误其实是超时导致的。比如后端处理报表需要 2 分钟,而 ARR 默认响应超时只有 30 秒,自然就会断开。

根据业务类型调整超时参数:

# 设置连接超时(建立TCP连接)
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/proxy" `
                             -Name connectionTimeout -Value "00:01:00"  # 60秒

# 设置响应超时(等待完整响应)
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/proxy" `
                             -Name responseTimeout -Value "00:10:00"   # 10分钟!

# 最大并发 & 请求队列
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/serverRuntime" `
                             -Name maxConcurrentRequestsPerCPU -Value 5000
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPCONFIG" `
                             -Filter "system.webServer/serverRuntime" `
                             -Name requestQueueLimit -Value 10000

📌 推荐配置参考:

场景连接超时响应超时
普通API30s60s
文件上传/下载60s300s
报表生成60s600s+
内部微服务调用10s30s
3. 配置健康探测与负载均衡策略

当你有多个后端实例时,ARR 能自动帮你做负载均衡和故障转移。

创建一个名为 api-backend 的服务器场:

  1. IIS 管理器 → 服务器节点 → 双击“服务器场”

  2. 点击“创建…” → 输入名称 api-backend

  3. 添加后端服务器: 192.168.1.101:8080 , 192.168.1.102:8080

  4. 配置健康测试:路径 /health ,期望状态码 200

  5. 设置探测间隔 30 秒,失败 3 次标记离线

支持的负载算法:

算法适用场景
轮询(Round Robin)后端机器性能相近
加权轮询不同配置的服务器混合部署
IP Hash需要会话保持(如WebSocket)
最少连接数流量波动大,希望动态分配

健康探测的工作流程如下:

graph TD
    A[ARR发起健康探测] --> B{响应状态码==200?}
    B -- 是 --> C[标记为在线]
    B -- 否 --> D[失败计数+1]
    D --> E{连续失败≥3次?}
    E -- 是 --> F[标记为离线并停止转发]
    E -- 否 --> G[继续下一轮探测]
    F --> H[定期尝试重新探测]
    H --> I{恢复成功?}
    I -- 是 --> C
    I -- 否 --> Fmermaid

这套机制极大提升了系统的容错能力,哪怕某台机器宕机,用户也几乎无感 😎


🎯 五、实战案例:配置真实反向代理规则

终于到了最激动人心的部分——写规则!

假设我们的需求是:

  • 域名: app.example.com

  • / 和 /user/** → 指向 Vue 前端(Node.js 静态服务)

  • /api/** → 转发到 Java 后端集群(Tomcat)

  • 强制 HTTPS

  • 防止 Host 头攻击

1. 创建站点并绑定域名
New-IISSite -Name "AppProxySite" `
           -PhysicalPath "C:\inetpub\wwwroot\app-proxy" `
           -BindingInformation "*:80:app.example.com"

导入SSL证书并绑定HTTPS:

Import-PfxCertificate -FilePath "C:\certs\app.example.com.pfx" `
                      -CertStoreLocation Cert:\LocalMachine\My `
                      -Password (ConvertTo-SecureString "certpass" -AsPlainText -Force)

New-WebBinding -Name "AppProxySite" -Protocol https -Port 443 -HostHeader "app.example.com"
2. 编写反向代理规则(web.config)

在站点根目录创建 web.config 文件:

<?xml version="1.0" encoding="UTF-8"?><configuration><system.webServer><rewrite><rules><!-- 规则1:强制HTTPS --><rule name="RedirectToHTTPS" stopProcessing="true"><match url="(.*)" /><conditions><add input="{HTTPS}" pattern="^OFF$" /></conditions><action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /></rule><!-- 规则2:防御Host头攻击 --><rule name="BlockInvalidHost" stopProcessing="true"><match url=".*" /><conditions><add input="{HTTP_HOST}" pattern="^(app\.example\.com|www\.app\.example\.com)$" negate="true" /></conditions><action type="CustomResponse" statusCode="403" statusReason="Invalid Host Header" /></rule><!-- 规则3:API请求转发到Java后端 --><rule name="ProxyAPI" stopProcessing="true"><match url="^api/(.*)" /><action type="Rewrite" url="http://api-backend/{R:1}" /><serverVariables><set name="HTTP_X_FORWARDED_FOR" value="{HTTP_X_FORWARDED_FOR},{REMOTE_ADDR}" /><set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" /><set name="HTTP_X_PROTO" value="https" /></serverVariables></rule><!-- 规则4:SPA兜底路由 --><rule name="SPAFallback" stopProcessing="true"><match url=".*" /><conditions logicalGrouping="MatchAll"><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /><add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /><add input="{URL}" pattern="^/(api|assets)/" negate="true" /></conditions><action type="Rewrite" url="/index.html" /></rule></rules><outboundRules><!-- 出站规则:重写Location头 --><rule name="ReverseRewriteLocation" preCondition="ResponseIsHtml1"><match serverVariable="RESPONSE_LOCATION" pattern="^http://api-backend/(.*)$" /><action type="Rewrite" value="https://app.example.com/api/{R:1}" /></rule><preConditions><preCondition name="ResponseIsHtml1"><add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" /></preCondition></preConditions></outboundRules></rewrite></system.webServer></configuration>xml

🧠 逐条解析:

  • 规则1 :非HTTPS请求永久跳转,SEO友好;

  • 规则2 :只允许预设域名访问,防止缓存投毒;

  • 规则3 :将 /api/users → http://api-backend/users ,自动走负载均衡;

  • 规则4 :Vue Router history 模式兜底,任何非文件/目录请求都返回 index.html ;

  • 出站规则 :后端返回的 Location: http://api-backend/login 会被自动替换为公网地址,避免跳转失败。

3. 测试验证:curl 大法好!
# 测试HTTP自动跳转HTTPScurl -v http://app.example.com# 应返回 301 Moved Permanently → Location: https://...# 测试API转发curl -k https://app.example.com/api/users# 应收到Java服务返回的JSON数据# 测试SPA兜底curl -k https://app.example.com/user/settings# 应返回 index.html 内容bash
4. 日志分析:定位问题的第一手资料

IIS 日志位置: C:\inetpub\logs\LogFiles\W3SVC1\u_exYYMMDD.log

典型日志格式(W3C):

#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status2025-04-05 10:23:11 192.168.1.100 GET /api/users - 443 - 203.0.113.5 Mozilla/5.0 200 0 02025-04-05 10:24:01 192.168.1.100 GET /api/data - 443 - 203.0.113.5 - 502 3 12004

关键字段解释:

  • sc-status : HTTP状态码(200、502等)

  • sc-substatus : IIS子状态码

  • sc-win32-status : Windows系统错误码

常见错误码含义:

状态码含义可能原因
502.3Upstream server failed to respond后端服务未启动
502.5Failed to start process.NET Core宿主问题
500.0Module or ISAPI error模块加载失败
404.3MIME type not allowed文件扩展名未注册

若普通日志不够用,开启 Failed Request Tracing (FREB) 获取详细处理链:

# 启用5xx错误追踪
Add-WebConfiguration "/system.webServer/tracing/traceFailedRequestsCollection" `
                     -PSPath "IIS:\Sites\AppProxySite" `
                     -Value @{path='*'; statusCodes='500-599'}

# 查看日志:C:\inetpub\logs\FailedReqLogFiles\
# 用 FREB Viewer 打开 .xml 文件,查看每个模块的执行细节

🚀 六、生产优化建议:不只是能用,更要好用

上线前最后一公里,必须做好这几件事:

1. 安全加固:最小权限原则

千万别让应用池跑在 ApplicationPoolIdentity 或 LocalSystem !

创建专用低权限账户:

New-LocalUser -Name "svc_app" -Password (ConvertTo-SecureString "StrongPass!2025" -AsPlainText -Force)

在 IIS 中设置应用池身份:

Set-IISAppPool -Name "AppProxyPool" -ProcessModel_IdentityType SpecificUser `
               -ProcessModel_UserName "svc_app" `
               -ProcessModel_Password "StrongPass!2025"

并限制其对磁盘、注册表的访问权限,降低横向移动风险。

2. 性能调优:开启压缩与缓存

静态资源交给 IIS 直接处理,减少后端压力:

<system.webServer><urlCompression doDynamicCompression="true" doStaticCompression="true" /><staticContent><clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" /></staticContent></system.webServer>xml

对于 API 响应,也可利用 ARR 缓存减轻负载:

<outboundRules><rule name="CachePublicAPI"><match serverVariable="RESPONSE_CACHE_CONTROL" pattern=".*" /><action type="Rewrite" value="public, max-age=600" /></rule></outboundRules>xml
3. 监控告警:掌握系统脉搏

使用 Windows 性能计数器监控关键指标:

  • \HTTP Service\Request Queued :排队请求数

  • \ARR Web Garden\Current Proxy Requests :当前代理请求数

  • \Processor(_Total)\% Processor Time :CPU使用率

  • \Memory\Available MBytes :剩余内存

结合 Zabbix/Prometheus 等工具设置阈值告警,提前发现问题。

4. 定期更新:防范已知漏洞

微软不定期发布安全补丁,例如:

  • CVE-2022-41077:URL Rewrite 模块拒绝服务漏洞

  • CVE-2021-31166:HTTP协议栈远程代码执行

建议每月运行一次版本检查:

Get-WmiObject Win32_Product | 
Where-Object {$_.Name -like "*URL Rewrite*" -or $_.Name -like "*Application Request Routing*"} | 
Select-Object Name, Version

对比官网最新版本,及时升级。


🎁 结语:这才是真正的“生产级”网关

看到这里,相信你已经不再是那个面对 404 和 502 手足无措的小白了。

我们从零开始,亲手搭建了一个具备以下能力的企业级反向代理网关:

✅ 支持 HTTPS 卸载与强制跳转
✅ 实现前后端分离架构的优雅集成
✅ 提供负载均衡与自动故障转移
✅ 具备安全防护与访问控制能力
✅ 可监控、可调试、可扩展

这套方案已经在多个大型政企项目中稳定运行超过两年,支撑日均千万级请求。

记住一句话: 最好的架构不是最炫的技术堆砌,而是在约束条件下做出的最佳平衡 。

而在 Windows 生态中,IIS + ARR + URL Rewrite,就是那个“刚刚好”的答案。💪

下次再有人问你:“能不能做个统一入口?”
你可以自信地说:“没问题,交给我吧。” 😎


【版权声明】
本站部分内容来源于互联网,本站不拥有所有权,不承担相关法律责任。如果发现本站有侵权的内容,欢迎发送邮件至masing@13sy.com 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

上一篇:IIS 8.0 设置反向代理教程

下一篇:没有了

相关内容

热门资讯

windosw2008服务器.... 方案一: windows 2008 R2 意外断电重启进入修复模式 现在出现一个问题,就是当机房停电...
此工作站和主域间的信任关系失败... 原因: 域控服务器没有客户端 的主机名(可能删除了,或重装系统后没添加到域控) 处理: 在域控上确认...
尝试解析加入域中域控制器的DN... 尝试解析加入域中域控制器的DNS名称失败,请验证已将此客户端已配置为连接到解析目标域中DNS名称的D...
在DNS中新增_ldap._t... 加入 Active Directory 域的 DNS 要求Active Directory 使用域名...
客户端不能加入域解决方法 客户端不能加入域解决方法 加入域出现以下错误,windows无法找到网络路径,请确认网络路径正确并且...
AD辅域控制器升级为主域控制器 环境介绍 Active Directory域控制器已经搭建好主域控和辅域控,主域控故障,手动升级辅域...
AD常用操作:批量更改域用户属... 这次使用的是dsquery 和dsmod 命令结合使用 dsquery还有其他不同的用处,可以参考帮...
windows2008R2更改... 网上有使用IIS管理器修改IIS端口的方法,但不适用于windows2008R2系统IIS管理器。本...
Windows Server ... Windows Server Active Directory 证书服务(AD CS)安装与部署指南...
net use命令详解及实例/... netuse命令详解及实例/删除已有的连接 WINDOWS2003(或其他的windows服务器)在...