Implementing IP Rate Limiting in ASP.NET Core MVC

Introduction

IP rate limiting is a crucial aspect of web application security that helps prevent abuse, protect against brute force attacks, and ensure fair resource usage. In this article, we will walk through the process of implementing IP rate limiting in an ASP.NET Core MVC application using middleware and the AspNetCoreRateLimit library.

Prerequisites

  1. Visual Studio installed
  2. ASP.NET Core MVC project created

Step 1. Install the AspNetCoreRateLimit NuGet Package

Open your project in  Visual Studio and install the AspNetCoreRateLimit NuGet package using the Package Manager Console.

Install-Package AspNetCoreRateLimit

Step 2. Configure Rate Limiting in appsettings.json

Add the rate-limiting configuration to your appsettings.json file.

{
  "IpRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "StackBlockedRequests": false,
    "RealIpHeader": "X-Real-IP",
    "ClientIdHeader": "X-ClientId",
    "HttpStatusCode": 429,
    "QuotaExceededMessage": "API rate limit exceeded.",
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "1s",
        "Limit": 5
      },
      {
        "Endpoint": "*",
        "Period": "1m",
        "Limit": 50
      }
    ]
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

This configuration limits each IP to 5 requests per second for all endpoints.

Step 3. Configure Rate Limiting Middleware

In your Startup.cs file, configure the rate-limiting middleware in the ConfigureServices method.

using AspNetCoreRateLimit;

var builder = WebApplication.CreateBuilder(args);

var configuration = builder.Configuration;

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddMemoryCache();
builder.Services.Configure<IpRateLimitOptions>(configuration.GetSection("IpRateLimiting"));
builder.Services.Configure<IpRateLimitPolicies>(configuration.GetSection("IpRateLimitPolicies"));
builder.Services.AddInMemoryRateLimiting();
builder.Services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
builder.Services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
var app = builder.Build();

// Configure the HTTP request pipeline.
if(!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // 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.UseHttpsRedirection();
app.UseStaticFiles();

app.UseIpRateLimiting();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Step 4. Use Rate Limiting Middleware in the Pipeline

In the same Startup.cs file, in the Configure method, add the rate-limiting middleware.

using AspNetCoreRateLimit;

var builder = WebApplication.CreateBuilder(args);

var configuration = builder.Configuration;

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddMemoryCache();
builder.Services.Configure<IpRateLimitOptions>(configuration.GetSection("IpRateLimiting"));
builder.Services.Configure<IpRateLimitPolicies>(configuration.GetSection("IpRateLimitPolicies"));
builder.Services.AddInMemoryRateLimiting();
builder.Services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
builder.Services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
var app = builder.Build();

// Configure the HTTP request pipeline.
if(!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // 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.UseHttpsRedirection();
app.UseStaticFiles();

app.UseIpRateLimiting();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

like this.

app.UseIpRateLimiting();

Step 5. Test the Implementation

Run your ASP.NET Core MVC application and test the rate-limiting by sending requests from different IPs. Verify that the rate-limiting is working as expected.

GitHub Project URL

Conclusion

Implementing IP rate limiting in an ASP.NET Core MVC application is a crucial step toward enhancing security and preventing abuse or unauthorized access. The use of the AspNetCoreRateLimit library provides a straightforward and effective solution, allowing you to configure rate limits for specific endpoints or across the entire application.

By following the steps outlined in this case study, you have successfully integrated IP rate limiting into your application, providing a defense mechanism against potential threats such as brute force attacks. It's essential to regularly monitor and adjust rate limits based on your application's traffic patterns and specific security requirements.

Remember that security is an ongoing process, and staying informed about the latest best practices and updates in the field is crucial. As you continue to develop and maintain your ASP.NET Core MVC application, consider additional security measures and keep abreast of any advancements in the security landscape. This proactive approach will help ensure the continued safety and reliability of your web application.