—以下內容針對 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 版的贊賞功能被關閉,可透過二維碼轉賬支援公眾號。