歡迎光臨
每天分享高質量文章

IIS作為ASP.NET Core2.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

         以上能力,可以參考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


 

受蘋果公司新規定影響,微信 iOS 版的贊賞功能被關閉,可通過二維碼轉賬支持公眾號。

    閱讀原文

    赞(0)

    分享創造快樂