--以下内容针对 ASP.NET Core2.1,2.2出现IIS进程内寄宿 暂不展开讨论---
相比ASP.NET,出现了3个新的组件:ASP.NET Core Module、Kestrel、dotnet.exe, 后面我们会理清楚这三个组件的作用和组件之间的交互原理。
ASP.NET Core 设计的初衷是开源跨平台、高性能web服务器,跨平台特性是ASP.NET Core相对于早期ASP.NET 是一个显著的飞跃,.NET程序可以理直气壮与JAVA同台竞技,而ASP.NET Core的高性能特性更是成为致胜法宝。
1. ASP.NET Core宏观梳理
为实现跨平台部署.Net程序,微软为ASP.NET Core重新梳理了部署架构:
① 由于各平台都有特定web服务器, 为解耦差异,采用HTTP通信的方式,将web服务器的请求转发到 ASP.NET Core 程序处理
② ASP.NET Core Web进程(dotnet.exe)会使用一个进程内HTTP服务器:Kestrel, 处理转发过来的请求
③ Web服务器现在定位成 反向代理服务器, ASP.NET Core Module组件负责转发请求到内网Kestrel服务器
常规代理服务器,只用于代理内部网络对外网的连接需求,客户机必须指定代理服务器将本来要直接发送到外网web服务器上的http请求发送到代理服务器,常规的代理服务器不支持外部对内部网络的访问请求;
当一个代理服务器能够代理外部网络的主机,访问内部网络,这种代理服务器的方式称为反向代理服务器 。
④ web进程(dotnet.exe)是IIS网站工作进程w3wp.exe 创建出来的子进程, 正因为如此,ASP.NET Core Module对网站工作进程 w3wp.exe 设定的进程内环境变量可以被 dotnet.exe 子进程继承。
验证:
- 任务管理器或 tasklist /fi "imagename eq dotnet.exe" 命令 找到dotnet.exe进程ID:22792
- wmic process where ProcessId=22972 get ParentProcessId 返回父进程ID:8232
- 任务管理器或 tasklist /fi "pid eq 8232" 命令找到 父进程是 w3wp.exe
2. Kestrel: 进程内HTTP服务器
与老牌web服务器解耦,实现跨平台部署
- 进程内Http服务器,ASP.NET Core 保持独立运作一个Http服务器的能力,可将 ASP.NET Core 网站当可执行程序启动, 在内网部署和开发环境中我们完全可以使用Kestrel来充当web服务器。
- 客观上Kestrel还是作为Http服务器,功能还比不上老牌的web服务器, 可以说在生产部署现状上要求使用老牌web服务器反向代理请求
Kestrel自诞生之日起还有一些网络安全方面的缺陷,这些缺陷包括一个合适的timeouts,Size limits,和并发数量等
3. ASP.NET Core Module
反向代理服务器的作用是将请求转发给内网的Http服务器,IIS上使用ASP.NET Core Module组件将请求转发到Kestrel Http服务器(注意该组件只在IIS上有效)。
从整个拓扑图上看,请求首先到达内核态Http.sys Driver,该驱动将请求路由到IIS上指定网站;然后Asp.Net Core Module将请求转发给Kestrel服务器。
3.1 组件能力
作为企业级转发组件ASP.NET Core Module需要完成:
① 进程管理: 控制web启动进程内Kestrel服务器在某端口上启动,并监听转发请求
② 故障恢复: 控制web在1min内崩溃重启
③ 请求转发
④ 启动日志记录: web启动失败,可通过配置将日志输出到指定目录
⑤ 请求头信息转发:dotnet.exe程序需要收到原始的请求信息
代理服务器转发请求时可能丢失的信息:
- 源IP地址丢失
- scheme:原始请求的scheme:https/http丢失(反向代理服务器和Kestrel之间通过Http交互,并不直接记录原始请求的scheme)
- IIS/nginx等代理服务器可能修改原始请求的Host消息头
⑥ 转发windiws认证token
以上能力,可以参考https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-2.1
给出的AspNetCore Module配置参数
3.2 ASP.NET Core Module组件与dotnet.exe 进程结合
自然可以猜想ASP.NET Core Module与UseIISIntegration()关系很密切:
- Web启动的时候,ASP.NET Core Module会通过进程内环境变量指定kestrel监听的端口
- UseIISIntegration() 拿到环境变量进行一系列配置:
① 服务器在http://localhost:{指定端口}上监听
② 根据 token检查请求是否来自AspNet Core Module(非ASPNE TCore Module转发的请求会被拒绝)
③ 保持原始请求信息 :利用ForwardedHeaderMiddleware中间件保存原始请求信息,存储在Header
在IIS部署时, UseIISIntegration()会默认为你配置并启用ForwardedHeaderMiddleware 中间件; 在linux平台部署需要你手动启用ForwardedHeader middleware
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2
通过 UseIISIntegration() 源码快速验证:
ASP.NET Core程序生成源码:
IISSetupFilter 内容:
着重理解下UseIISIntegration第②点配置: 怎样拒绝非ASP. NET Core Module 转发的请求?
① AspNetCore Module 为w3wp.exe 工作进程设置进程内环境变量 ASPNETCORE_TOKEN=******
② dotnet.exe进程继承了父进程 ASPNETCORE_TOKEN=****** 环境变量
③ AspNetCore Module转发请求到kestrel时,会在Request里面加上一个 MS-ASPNETCORE-TOKEN:****** 的请求头;非AspNetCore Module自然没有该请求头
④ IISMiddleware中间件:请求头中匹配该ASPNETCORE_TOKEN=******的请求是有效的。
附:部署在IIS后面的Kestrel 也是一个web服务器,怎样Hack访问搭配ASP.NET Core Module的Kestrel服务器?
按照上文的理论,部署在IIS后面的dotnet.exe程序是依靠 AspNetCore Module 设定的进程内环境变量ASPNETCORE-TOKEN来识别【非AspNetCore Module转发的请求】。
因此,理论上将该PairToken拷贝到请求头,可访问部署在IIS后面的Kestrel 服务器(这是一个hack行为,对于理解部署图很有帮助)。
操作方式如下:
① 在任务管理器中找到你要分析的dotnet进程,tasklist /fi "imagename eq dotnet.exe" ,找到要分析{ pid }
② 找到该进程占用port : netstat -ano | findstr {pid}
③ 利用输出的port: curl localhost:{port} --verbose: 会提示400 badrequest,这与源码的返回一致
④ 从error log 中拷贝出该环境变量:ASPNETCORE_TOKEN
'MS-ASPNETCORE-TOKEN' does not match the expected pairing token '4cdaf1fd-66d5-4b64-b05f-db6cb8d5ebe5', request rejected.
⑤ 在request中添加 MS-ASPNETCORE-TOKEN:****** 请求头
【实际上 ,可以在ASP.NET Core dotnet.exe程序内写日志输出 ASPNETCORE_TOKEN 环境变量值。】
原文地址:https://www.cnblogs.com/mi12205599/p/10334506.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com