In websites or API applications, we often want to block high-frequency requests in a short period of time for an IP to prevent boring people or malicious attacks. In ASP.NET Core, limiting the request rate of IP is now super easy, let's see.

AspNetCoreRateLimit

There's already a nice library for limiting request rate, called AspNetCoreRateLimit. GitHub: https://github.com/stefanprodan/AspNetCoreRateLimit 

My application is an ASP.NET Core 2.2 MVC website, I can use NuGet to install this package, either in Visual Studio:

Install-Package AspNetCoreRateLimit

or from .NET CLI:

dotnet add package AspNetCoreRateLimit

And then, modify Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // needed to load configuration from appsettings.json
    services.AddOptions();

    // needed to store rate limit counters and ip rules
    services.AddMemoryCache();

    //load general configuration from appsettings.json
    services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));

    // inject counter and rules stores
    services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
    services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

    // Add framework services.
    services.AddMvc();

   // https://github.com/aspnet/Hosting/issues/793
   // the IHttpContextAccessor service is not registered by default.
   // the clientId/clientIp resolvers use it.
   services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

   // configuration (resolvers, counter key builders)
   services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseIpRateLimiting();
    app.UseMvc();
}

Code reference: https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware#setup

Setup IP Limit Rules

My website has a URL (/fw/{token}) and I want to limit it for maximum 30 requests in one minute for a single IP. But for other URLs, I don't want to impose any restrictions. The MVC Action for that URL is:

[Route("/fw/{token}")]
public async Task<IActionResult> Forward(string token)

To setup the IP limit, add the following code to appsettings.json:

"IpRateLimiting": {
  "EnableEndpointRateLimiting": true,
  "StackBlockedRequests": false,
  "RealIpHeader": "X-Real-IP",
  "ClientIdHeader": "X-ClientId",
  "HttpStatusCode": 429,
  "GeneralRules": [
    {
      "Endpoint": "*:/fw/*",
      "Period": "1m",
      "Limit": 30
    }
  ]
}

EnableEndpointRateLimiting must set to true, meaning that IP limits are applied to specific endpoints like "*:/fw/*" rather than all endpoints (*).

HttpStatusCode is set to 429, which means the HTTP status code returned to the client after the limit is triggered.

I only configured one rule in GeneralRules for the limit /fw URL. In which, the beginning "*:" means any HTTP VERB, such as GET/POST, and the ending "/*" indicates that the parameters after/fw need to be considered, that is, the route parameter in my MVC Action parameter, in my case, the parameter is "token"

There are different counts for different tokens. For example, a user with an IP of 127.0.0.1 requested /fw/abcd 10 times in 1 minute, /fw/qwer 25 times, and /fw/996icu 32 times. So for the user, the remaining chance of /fw/abcd is still 20, /fw/qwer has 5 left, and /fw/996icu returns 429 at the 31st request.

Please be careful, any Action with parameters must add "/*", or the IP limit won't work.

Testing IP Rate Limit

We can test IP limits via browser or CRUL.

For the convenience of the test, I temporarily limited the request frequency of 1 minute to 3 times. First request https://localhost:5001/fw/{token}:

You'll find three more things in the header returned by the server:

X-Rate-Limit-Limit: 1m, indicating that the limit is for 1 minute

X-Rate-Limit-Remaining: 2, indicating 2 chances left

X-Rate-Limit-Reset indicates a limited reset time.

For the third time the URL is accessed in 1 minute, the limit is triggered and server returns 429

More Advanced Configurations

AspNetCoreRateLimit has many other advanced scenarios. Such as limit based on Client ID not IP, white list, distributed counter store, customize limit message, etc. You can check these at the official Wiki:

https://github.com/stefanprodan/AspNetCoreRateLimit/wiki