📡 محدودسازی نرخ کاربران بر اساس آدرس IP
رویکردی که پیشتر نشان داده شد، یک مشکل دارد - سیاست محدودسازی نرخ سراسری (Global) است و بر همه کاربران اعمال میشود. ❌
اغلب اوقات، شما نمیخواهید این کار را انجام دهید. محدودسازی نرخ باید جزئی (Granular) باشد و بر تکتک کاربران اعمال شود. 👤
خوشبختانه، میتوانید با ایجاد یک RateLimitPartition به این هدف برسید.
🧱 اجزای RateLimitPartition
RateLimitPartition دو جزء دارد:
🔹️ کلید پارتیشن (Partition key)
🔹️ سیاست محدودسازی نرخ (Rate limiter policy)
💻 پیادهسازی محدودسازی با IP Address
در اینجا نحوه تعریف یک Rate Limiter با سیاست Fixed Window آمده است، که در آن کلید پارتیشن، آدرس IP کاربر است:
builder.Services.AddRateLimiter(options =>
{
options.AddPolicy("fixed-by-ip", httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.Connection.RemoteIpAddress?.ToString(),
factory: _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 10,
Window = TimeSpan.FromMinutes(1)
}));
});
محدودسازی نرخ بر اساس آدرس IP میتواند یک لایه امنیتی خوب برای کاربران احراز هویت نشده (unauthenticated users) باشد. 🔐 شما نمیدانید چه کسی به سیستم شما دسترسی دارد و نمیتوانید محدودسازی نرخ جزئیتری اعمال کنید. این روش میتواند به محافظت از سیستم شما در برابر کاربران مخربی که سعی در انجام حمله DDoS دارند، کمک کند.
🔗 ایجاد محدودکنندههای زنجیرهای (Chained Limiters)
شما همچنین میتوانید با استفاده از API با نام CreateChained، محدودکنندههای زنجیرهای ایجاد کنید. این API به شما اجازه میدهد تا چندین PartitionedRateLimiter را ارسال کنید که در یک PartitionedRateLimiter ترکیب میشوند. محدودکننده زنجیرهای، تمام محدودکنندههای ورودی را به صورت متوالی (Sequence) (یکی پس از دیگری) اجرا میکند. 🔄
🛡 ملاحظات Reverse Proxy
اگر برنامه شما پشت یک Reverse Proxy در حال اجراست، باید مطمئن شوید که آدرس IP خود پروکسی را محدود نکنید. ⚠️ Reverse Proxyها معمولاً آدرس IP اصلی کاربر را با استفاده از هدر X-Forwarded-For ارسال میکنند. بنابراین، میتوانید از این هدر به عنوان کلید پارتیشن استفاده کنید:
builder.Services.AddRateLimiter(options =>
{
options.AddPolicy("fixed-by-ip", httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
httpContext.Request.Headers["X-Forwarded-For"].ToString(), // استفاده از هدر
factory: _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 10,
Window = TimeSpan.FromMinutes(1)
}));
});