IIS作为ASP.NETCore2.1反向代理服务器未说的秘密

--以下内容针对 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

         以上能力,可以参考?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() 拿到环境变量进行一系列配置:

           ① 服务器在:{指定端口}上监听

           ② 根据 token检查请求是否来自AspNet Core Module(非ASPNE TCore Module转发的请求会被拒绝) 

           ③ 保持原始请求信息 :利用ForwardedHeaderMiddleware中间件保存原始请求信息,存储在Header

      在IIS部署时, UseIISIntegration()会默认为你配置并启用ForwardedHeaderMiddleware 中间件; 在linux平台部署需要你手动启用ForwardedHeader middleware

?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社区新闻,深度好文,欢迎访问文章汇总