開發者都知道系統上線後才是挑戰的開始,舉例來說像是每天不斷的有爬蟲程式來抓取網站資料,或是對外開放的 API 服務遭到攻擊事件,若沒有良好的防範機制很有可能造成 Server 因為攻擊無法正常服務,甚至引起雪崩效應影響到其他系統服務,在 ASP.NET Core 中可以透過 AspNetCoreRateLimit 框架根據 Request 的 IP 或是 ClientID 來達到限制流量的效果,這篇就來簡單分享一下有關 AspNetCoreRateLimit 的安裝與基本使用,若有問題或是錯誤的地方歡迎網路的高手大大給予指導。
首先,為了方便大家更容易了解,建立一個 ASP.NET Core Web Application 應用程式來作範例,接著開啟 Nuget Package Mnage 輸入 AspNetCoreRateLimit 搜尋,安裝目前最新版的 AspNetCoreRateLimit 套件
或是透過 Nuget Package Console 輸入下列指令
Install-Package AspNetCoreRateLimit -Version 3.0.5安裝完畢之後到專案檔底下確認是否有安裝成功
使用與設定
AspNetCoreRateLimit 可以根據 IP 或是客戶 ID 來作為限速依據,也可以指定 API 中某一個對外接口或是 Http Method 分別設定其限制,兩者皆是在中間件 ( Middleware) 判斷其請求率是否達到設定的上限,分別是 IpRateLimitMiddleware 與 ClientRateLimitMiddleware ,再來決定是否要讓此 Request 繼續下一步或是返回的動作,這裡以限制 IP 為範例,安裝完後接下來就是到 start.cs 中加入下列代碼
public void ConfigureServices(IServiceCollection services) { // 將速限計數器資料儲存在 Memory 中 services.AddMemoryCache(); // 從 appsettings.json 讀取 IpRateLimiting 設定 services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); // 從 appsettings.json 讀取 Ip Rule 設定 services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies")); // 注入 counter and IP Rules services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>(); services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); // Add framework services. services.AddMvc(); // the clientId/clientIp resolvers use it. services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // Rate Limit configuration 設定 services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseIpRateLimiting(); app.UseMvc(); }代碼中的 Code 都有加上註解跟說明,這裡就不在詳細說明,在上述代碼中可以看到 Policy 與 IP Rule 都是從 appSettings.json 設定檔中取得,因此下一步就是在設定檔中加上限流相關的設定資訊
IpRateLimiting
"IpRateLimiting": { "EnableEndpointRateLimiting": false, "StackBlockedRequests": false, "RealIpHeader": "X-Real-IP", "ClientIdHeader": "X-ClientId", "HttpStatusCode": 429, "IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ], "EndpointWhitelist": [ "get:/api/license", "*:/api/status" ], "ClientWhitelist": [ "dev-id-1", "dev-id-2" ], "GeneralRules": [ { "Endpoint": "*", "Period": "1s", "Limit": 2 }, { "Endpoint": "*", "Period": "15m", "Limit": 100 }, { "Endpoint": "*", "Period": "12h", "Limit": 1000 }, { "Endpoint": "*", "Period": "7d", "Limit": 10000 } ] }IpRateLimiting 區塊設定 :
IpRateLimitPolicics
在 appSettings.json 加入下列設定資訊
"IpRateLimitPolicies": { "IpRules": [ { "Ip": "84.247.85.224", "Rules": [ { "Endpoint": "*", "Period": "1s", "Limit": 10 }, { "Endpoint": "*", "Period": "15m", "Limit": 200 } ] }, { "Ip": "192.168.3.22/25", "Rules": [ { "Endpoint": "*", "Period": "1s", "Limit": 5 }, { "Endpoint": "*", "Period": "15m", "Limit": 150 }, { "Endpoint": "*", "Period": "12h", "Limit": 500 } ] } ] }備註 : 這裡 IP 支援 IPv4 & IPv6
限流規則
使用 Throttling 最重要的是了解限速的規則設定,才可以因應不同的情境調整需要的限速(流)設定,這裡直接來看一下官方說明文件提到的 Throttling 規則與 Rule,有 EndPoint Format、Period 與 Limit 等三種格式
廢話不多說直接看範例更容易了解
Sample 1 :
{ "Endpoint": "*", "Period": "1s", "Limit": 2 }目的 : 所有端點每秒鐘允許 2 次呼叫
使用 GET 方法發送 api / Values 一秒三個 Request,前 2 個 Request 會 pass,第 3 個 request 會無法使用,如果同時間使用 PUT 方法呼叫相同 api / values 則會 pass,因為 GET 與 PUT 分別加總不會混和計算。
Sample 2 :
{ "Endpoint": "*:/api/values", "Period": "15m", "Limit": 5 }目的 : api / Values 用 HTTP 所有 Method 的設定為每 15 分鐘允許呼叫 5 次
Sample 3 :
{ "Endpoint": "get:/api/values", "Period": "1h", "Limit": 5 }目的 : api / Values 用 HTTP GET Method 的設定為每小時允許呼叫 5 次
每小時呼叫 5 次,PASS
每小時呼叫 6 次,第六次則會正常取得正確資料
當超過我們定義的次數限制時會顯示
API calls quota exceeded! maximum admitted 2 per 10s.打開 Chrome 瀏覽器透過 Network 可以看到回傳的內容細節
可以從開發者工具看到 Response 的資訊,在 Response Header 中 StatusCode 為 429,retry-after 為 9,如果不希望在 Response Header 中顯示 retry 次數,可以在 appsettings.json 設定檔中加上 DisableRateLimitHeaders 為 true 隱藏 retry 資訊,如果想要自訂 Response 時的訊息內容可以參考官網的說明 : 傳送門
感想
除了在 ASP.NET Core 有限流以外,作者也有提供 .NET Framework 版本的限流框架 WebApiThrottle,可以省下自己開發時間,也可以快速地將限流機制套用在需要的專案上,另外在本篇中提到的都是以 IP 為出發作為限制,在 AspNetCoreRateLimit 也有提供使用 Client 作為設定的機制,如有需要可以參考 ClientRateLimitMiddleware 相關說明,希望這篇介紹可以有幫助到有需要的朋友,謝謝
參考
AspNetCoreRateLimit
Throttling your API in ASP.NET
除了在 ASP.NET Core 有限流以外,作者也有提供 .NET Framework 版本的限流框架 WebApiThrottle,可以省下自己開發時間,也可以快速地將限流機制套用在需要的專案上,另外在本篇中提到的都是以 IP 為出發作為限制,在 AspNetCoreRateLimit 也有提供使用 Client 作為設定的機制,如有需要可以參考 ClientRateLimitMiddleware 相關說明,希望這篇介紹可以有幫助到有需要的朋友,謝謝
參考
AspNetCoreRateLimit
Throttling your API in ASP.NET
0 意見:
張貼留言