How to rate limit requests in Blazor / ASP.NET Core

Contents

If you are creating an API or a public web portal, you're probably concerned about performance. Speed ​​limiting can help prevent abuse of basic DDoS attacks, and it is quite simple to configure for Blazor applications / ASP.NET Core.

Why are rate cap requests?

There are many reasons to qualify limit requests. Most services should probably set some kind of speed limit, because no reasonable human is going to perform 100 requests per second for ten minutes in a row. By default, your application will respond to all requests, so determining a reasonable limit is a good idea.

Decidedly, your cloud provider may also have DDoS protection. This will generally protect well against Cloak attacks. 3 and 4 directed to your server. Despite this, you'll want to make sure your server does everything possible to prevent attackers from accessing it.

Additionally you have the option to set the much lower limit to limit requests on public APIs. As an example, maybe a certain endpoint requires a lot of processing to answer the request. You might want to limit this endpoint so that no IP address can carry out more than a few requests every two seconds, which limits stress on your server / database.

Setting speed capping in ASP.NET Core

Blazor as a framework is based on ASP.NET Core, which handles all the internals for running an HTTP server and responding to requests. Because, you will need to configure rate limiting for ASP.NET Core. The same steps will apply to anyone not using Blazor.

Unfortunately, speed capping is not a default feature in ASP.NET Core. Despite this, there is a very popular NuGet package, AspNetCoreRateLimit, that does the job quite well. You can install it by right clicking on your project in Visual Studio and selecting “Manage NuGet Packages …”:

Look for AspNetCoreRateLimit and install it.

There are some alternatives for speed limitation. If you are using an API that needs keys, we suggest you limit the rate based on the API key, covering all cases. For most people, speed limiting based on IP address is probably fine, and is the default value recommended by AspNetCoreRateLimit.

You will need to add it as a service to ASP.NET. All services are configured in Startup.cs, that adds them with the ConfigureServices(IServiceCollection services) function.

There are quite a few services to configure. The first function configures the services to load configurations from its configuration file. You will also want to add the Microsoft cache if you haven't already.. After, you will need to configure IpRateLimiting from the JSON file and then add the rate limiter.

            // 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(Configuration.GetSection("IpRateLimiting"));
 
            // inject counter and rules stores
            services.AddInMemoryRateLimiting();
 
            // configuration (resolvers, counter key builders)
            services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

Also in Startup.cs, you will need to configure the app builder to use IP rate limiting.

app.UseIpRateLimiting();

Note that this uses a memory speed limitation, what is for instance. If you are load balancing your application, you will need to use a distributed memory store like Redis, than this package also has support for.

Speed ​​limitation settings

Once it is added to ASP.NET, you should go to your appsettings.json configuration file to configure it. The configuration looks like the next:

"IpRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "StackBlockedRequests": true,
    "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
      }
    ]
  }

First, if you plan to rate limit certain endpoints differently, you will want to enable EnableEndpointRateLimiting, which is false by default.

StackBlockedRequests will make blocked requests count for the counter. Simply, with this disabled, Anyone who makes requests again and again will receive X responses per period. With him activated, maximum responses will increase very quickly and then will not be answered further.

RealIpHeader and ClientIdHeader are used when your server is behind a reverse proxy, which is a common configuration. Since requests will always come from the proxy server, the proxy sets a header with the actual user information. You will need to check your proxy and make sure this header is set correctly, opposite case, the speed limiter will treat everyone as the same IP.

After, there are three white lists, one for IP, Client ID and endpoints. You can delete them if you don't need them.

After, you will need to configure each endpoint, as well as a period and a limit. A wildcard will cover everything and it is the only thing that works with EnableEndpointRateLimiting set to false. If that is not the case, you can set endpoints using {HTTP_VERB}{PATH}, including wildcards, so that *:/api/values will match all GET and POST requests for /api/values.

You'll want to make sure your endpoint matches a file and not a directory. In my case, *:/download/*/* was a valid endpoint, but *:/download/*/*/ It was not, because of the trailing slash.

This default configuration includes an IP whitelist for localhost, that you should comment if you are testing. But, you should be able to test your setup by setting the limit very low, What 5 per minute, and making a bunch of requests. This error should appear, “API call quota exceeded”, which means it is working properly.

There is much more this package can do, so if you have more specific needs than this, we suggest checking your documentation and seeing what is feasible.

Subscribe to our Newsletter

We will not send you SPAM mail. We hate it as much as you.