在網站或API應用中,我們為了防止無聊人士或惡意攻擊,通常希望遮蔽某一IP短時間的內高頻率請求。在ASP.NET Core中,限制IP請求頻率非常簡單,我們來看看吧。
輪子一個
.NET Core 目前的生態發展十分迅猛,輪子也越來越多。只要輪子不爆胎,本來就不需要996的.NET開發者就能繼續10 5 5!這不,為了限制IP請求頻率,我找到了一個不錯的輪子:
AspNetCoreRateLimit
GitHub連結:https://github.com/stefanprodan/AspNetCoreRateLimit
安裝輪子
我的應用目前一個ASP.NET Core 2.2 MVC的網站,我們可以透過NuGet安裝這個輪子,截至本文,它的最新版是3.0.5。
Install-Package AspNetCoreRateLimit
或 .NET Core CLI
dotnet add package AspNetCoreRateLimit
修改Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// 需要從appsettings.json中載入配置
services.AddOptions();
// 儲存IP計數器及配置規則
services.AddMemoryCache();
services.Configure(Configuration.GetSection(“IpRateLimiting”));
services.AddSingleton();
services.AddSingleton();
// 按照檔案,這兩個是3.x版的breaking change,要加上
services.AddSingleton();
services.AddSingleton();
}
以及
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// 註意順序,放在 UseMvc 上面
app.UseIpRateLimiting();
app.UseMvc();
}
配置輪子
我的網站有一個URL(/fw/{token}),我希望限制1分鐘內一個IP最多訪問30次。但是對於其他URL,我並不想做任何限制。
[Route(“/fw/{token}”)]
public async Task Forward(string token)
在 appsettings.json 裡加入
“IpRateLimiting”: {
“EnableEndpointRateLimiting”: true,
“StackBlockedRequests”: false,
“RealIpHeader”: “X-Real-IP”,
“ClientIdHeader”: “X-ClientId”,
“HttpStatusCode”: 429,
“GeneralRules”: [
{
“Endpoint”: “*:/fw/*”,
“Period”: “1m”,
“Limit”: 30
}
]
}
EnableEndpointRateLimiting設定為true,意思是IP限制會應用於單個配置的Endpoint上。如果是false的話,只會限制所有 * 的規則,而不能達到針對單個Endpoint配置的目的。
HttpStatusCode設定為429,意思是觸發限制之後給客戶端傳回的HTTP狀態碼。
GeneralRules裡我只配置了一條,針對/fw這URL的限制。其中,開頭的 *: 表示任何HTTP VERB,如GET/POST,而結尾的 /* 表示需要考慮/fw後面的引數,也就是我MVC Action引數裡的route引數。
針對不同token,會有不同的計數。比如IP為127.0.0.1的使用者在1分鐘內請求了 /fw/abcd 10次,又請求了 /fw/qwer 25次,也請求了 /fw/996icu 32次。那麼對於該使用者,/fw/abcd 的機會還剩下20次,/fw/qwer 的機會還剩下5次,而 /fw/996icu 在第31次請求時會傳回429。
這裡一定要註意,對於有引數的URL,如果不加結尾的 /* 那麼輪子就會爆胎,並且把.NET程式員炸進ICU!
測試輪子
我們可以透過瀏覽器或CRUL測試IP限制。為了方便測試,我暫時把1分鐘的請求頻率限製為3次。
第一次請求 https://localhost:5001/fw/某token:
會發現伺服器傳回的essay-header裡多了3個東西:
X-Rate-Limit-Limit: 1m,表示該限制是1分鐘以內
X-Rate-Limit-Remaining: 2,表示當前還剩2次機會
X-Rate-Limit-Reset 表示限制的重置時間
而1分鐘內第三次訪問該URL,就會觸發限制,並且傳回429
更多高階配置
AspNetCoreRateLimit 還有許多更高階的用法。比如針對Client ID而不是IP做限制、白名單、分散式計數器儲存、自定義傳回內容等等,可以參見官網檔案:
https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware#setup
朋友會在“發現-看一看”看到你“在看”的內容