Giter Club home page Giter Club logo

AspNetCoreRateLimit's Introduction

AspNetCoreRateLimit

AspNetCoreRateLimit is an ASP.NET Core rate limiting solution designed to control the rate of requests that clients can make to a Web API or MVC app based on IP address or client ID. The AspNetCoreRateLimit package contains an IpRateLimitMiddleware and a ClientRateLimitMiddleware, with each middleware you can set multiple limits for different scenarios like allowing an IP or Client to make a maximum number of calls in a time interval like per second, 15 minutes, etc. You can define these limits to address all requests made to an API or you can scope the limits to each API URL or HTTP verb and path.

Build status NuGet NuGet GitHub stars GitHub forks License: MIT

Documentation

Version 3.x.x Breaking Changes

Rate limiting based on client IP

Rate limiting based on client ID

Advanced configuration

AspNetCoreRateLimit's People

Contributors

cristipufu avatar stefanprodan avatar dependabot[bot] avatar simkin2004 avatar mcshaz avatar ogix avatar Varorbc avatar Naveenkhasyap avatar nick-cromwell avatar odysseus1973 avatar darth10 avatar gijskoning avatar m-gug avatar johnkors avatar mathiasbl avatar melmi avatar Rashik004 avatar rymitch avatar thomasgalliker avatar thschmitt avatar veloek avatar aKzenT avatar aaron-0 avatar emrahcetiner avatar tanyongzheng avatar

Stargazers

 avatar Dan Booth avatar virtual avatar Charles Lin avatar rbz avatar Alexander Sidorov avatar 憧憬 avatar Keitf avatar Ayslan Alves avatar  avatar Abel Beneberu avatar Joe Adanah avatar Alameer Ashraf Hassan avatar hualin.zhu avatar syx avatar  avatar Andrei Bazanov avatar Timur MANDALI avatar Peter Pan avatar Геннадий Курбесов avatar rpe4a avatar Mostafa Esmaeili avatar  avatar  avatar Himanshu Panwar avatar zxyao avatar 贺胜杰 avatar Henk Mollema avatar Stephen Halter avatar  avatar François DESCAVES avatar  avatar  avatar  avatar  avatar  avatar 万彬 avatar  avatar BenKung avatar Adrien Manigart avatar Cédric Luthi avatar Chris Berger avatar Pedro Ludovico Bozzini avatar kotofot avatar James avatar Khashayar Hosseini avatar Stanislav Prusac avatar Kristijan Cindrić avatar Ssewannonda Keith Edwin avatar  avatar Ho.Chun avatar Kyle avatar ZeroOne avatar  avatar Xu Wenliang avatar Juanjo Torres avatar  avatar BYAMASU Patrick Paul avatar 边宇琨 avatar Dmitry Pursanov avatar  avatar Ronan Farrell avatar ganmingkun avatar 疯风愚雨 avatar Ruslan Starovoitov avatar 曹旭升(sheng.c) avatar فرزاد avatar CyberSapphire avatar Niels Kootstra avatar  avatar Erfan Mahmoudi avatar Ranga Vadhineni avatar ksemenenko avatar Raphael Strotz avatar Adrian Eng Ying Ming avatar Kyle avatar Sadık Ünal Çokünlü avatar  avatar Yan Andrey avatar Sam avatar Andrew Eberle avatar  avatar  avatar KevinZønda avatar  avatar  avatar  avatar Nwachukwu Daniel (DONSN) avatar Maksym Konotop avatar Will Roscoe avatar Justin Baur avatar  avatar Duan XiaoMeng avatar AddressXception avatar Baran avatar Paul Russo avatar Namu avatar Mihai Gliga avatar TotPeRo avatar  avatar

Watchers

Ariel B. Vargas avatar Robert Campbell avatar send2vinnie avatar  avatar magyar_p avatar Luc-Edmond Gaspard avatar Hayden Hancock avatar  avatar Sreenivas Vemulapalli avatar Baris SONMEZ avatar Sam Morreel avatar Shane Rogers avatar Manish Jain avatar Ilker Aydogmus avatar Travis L. Spencer avatar  avatar  avatar  avatar Wen He avatar  avatar Non Ho avatar Dennis Pitallano avatar Stefan Prodan avatar Alex Nguyen avatar Cristi Pufu avatar Wilson Neto avatar David Poblacion avatar noob avatar ahweb avatar  avatar Roman Konečný avatar Animalito Máquina avatar Aven avatar  avatar Francis Austria avatar 王刚 avatar freed avatar  avatar Le Huu Hoang Gia avatar huayao avatar Dan Nguyen avatar  avatar  avatar athinboy avatar gandalf avatar  avatar  avatar  avatar Burak Tahtacıoğlu avatar mq avatar  avatar Scott Thomas avatar JB avatar Fukuhara.N avatar aprilyu avatar Badea Razvan avatar Luiz Henrique Santos Sousa Diniz avatar Wehub avatar  avatar  avatar Ycy avatar  avatar Max avatar Вадим Александрович avatar  avatar  avatar Vinod Vetrivel avatar

AspNetCoreRateLimit's Issues

How do you create dynamic URL (parameter) rules?

How do you create dynamic URL rules? For example, I have a URL:

POST example.com/user/{id}/something

where {id} changes per user. I'd like to limit it to 1 call per second per user id.

Should the rule look like this or what?

  {
    "Endpoint": "post:/user/*/something",
    "Period": "1s",
    "Limit": 1
  }

I couldn't find anything in the docs. Thanks!

The default X-Rate-Limit-Reset value format is not culture invariant

The X-Rate-Limit-Reset response header should allow for configurability.

Using the default configuration from the documentation for local testing, I get a value similar to the following in the HTTP response headers (a date one week from 14:07 BST today when the application was started):

x-rate-limit-reset: 06/10/2016 13:07:24

Given I'm running on a en-GB edition of Windows 10, this would suggest that the localisation settings of the host are contributing to the formatting of the value written by the middleware due to ToString() being used instead of with a specific format and culture (here and here).

By default the invariant culture should be used to ensure consistent behaviour (as RetryAfterFrom() appears to), but also allow for the format to be configured by the user.

For example, if a client wishes to programmatically determine when they can retry from, a format such as the u pattern (yyyy'-'MM'-'dd HH':'mm':'ss'Z') would be easier to parse and as it contains the time zone in the value as is thus less ambiguous. Alternatively, an integrator may wish to return the value as a number of seconds instead of as a timestamp.

how to define a "daily" limit rule?

I defined a rule for a day :

Endpoint : "*",
Period: "1d",
Limit : 1000

but this starts a daily count based on the first request to the api. For example like 9am-8:59am I'm really looking for a way to throttle based on 12am - 11:59pm. Is there a way to do this?

Mix Global and Endpoint Rules

Is it possible to mix a global rule with specific endpoint rules? For example I want to limit all endpoints globally to 1000 calls every 1 hour, but I also want to limit a specific endpoint with a more strict rule, like 1 per second. The documentation seems to indicate this is global or not with the EnableEndpointRateLimiting flag.

Modifying IpWhitelist at runtime

Modifying policies at runtime currently seems to be limited to either IP policies or Client policies.

Are the general properties inside IpRateLimiting config node (IpWhiteList, ClientWhiteList, etc) designed to be modified at runtime?

I suppose I could add a series of rules to the IpRateLimitPolicies that would behave in the same way, but it would be nice if general policies were configurable at runtime.

NullReferenceException in runtime

Here is the bug - NullReferenceException.
Check this method https://github.com/stefanprodan/AspNetCoreRateLimit/blob/master/src/AspNetCoreRateLimit/Core/RateLimitCore.cs#L116

services.Configure<IpRateLimitOptions>(options =>
{
	options.EnableEndpointRateLimiting = false;
	options.StackBlockedRequests  = false;
	//The RealIpHeader is used to extract the client IP when your Kestrel server is behind a reverse proxy, if your proxy uses a different header then X-Real-IP use this option to set it up.
	options.RealIpHeader = "X-Real-IP";
	//The ClientIdHeader is used to extract the client id for white listing, if a client id is present in this header and matches a value specified in ClientWhitelist then no rate limits are applied.
	options.ClientIdHeader = "X-ClientId";
	options.HttpStatusCode = 429;
	options.IpWhitelist = new List<string>() { /*"127.0.0.1", "::1/10", "192.168.0.0/24" */};
	options.EndpointWhitelist = new List<string>() { /*"get:/api/license", "*:/api/status" */};
	options.ClientWhitelist = new List<string>(){ /*"dev-id-1", "dev-id-2" */ };
	options.GeneralRules = new List<RateLimitRule>()
	{
		new RateLimitRule()
		{
			Endpoint = "*",
			//Period = "10s",
			PeriodTimespan = TimeSpan.FromSeconds(10), //runtime exception !! 
			Limit = 2
		}
	};
	options.DisableRateLimitHeaders = true;
	options.RateLimitCounterPrefix = "web_throttle_";
});

change logLevel

Hello,
I'm trying to change logLevel of IpRateLimitMiddleware, for what I understood I have to inherit from IpRateLimitMiddleware and override LogBlockedRequest

this is what I've done, probably wrong because it doesn't work...

services.AddOptions();
services.AddMemoryCache();
services.Configure(Configuration.GetSection("IpRateLimiting"));
services.Configure(Configuration.GetSection("IpRateLimitPolicies"));
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

services.AddSingleton<IpRateLimitMiddleware, IpRateLimitMiddlewareCustom>();

....
public class IpRateLimitMiddlewareCustom: IpRateLimitMiddleware
{
private ILogger _logger;

    public IpRateLimitMiddlewareCustom(RequestDelegate next, IOptions<IpRateLimitOptions> options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, ILogger<IpRateLimitMiddleware> logger, IIpAddressParser ipParser = null) : base(next, options, counterStore, policyStore, logger, ipParser)
    {
        _logger = logger;
    
    }

    public override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)
    {
        _logger.LogWarning($"Request {identity.HttpVerb}:{identity.Path} from IP {identity.ClientIp} has been blocked, quota {rule.Limit}/{rule.Period} exceeded by {counter.TotalRequests}. Blocked by rule {rule.Endpoint}, TraceIdentifier {httpContext.TraceIdentifier}.");
    }

}

this is the output

AspNetCoreRateLimit.IpRateLimitMiddleware:Information: Request options:.........

thank you!

Idea: Define rules via attributes

In addition to defining rules via the appsettings.json configuration, I'd suggest adding a way to define rules on specific endpoints via Attributes.

Something like:

[HttpGet("values/{id}")]
[RateLimit( Period = "15m", Limit = 5)]
public string Values(int id)
{
    return "";
}

IMO, this creates a cleaner implementation in solutions that have a large list of endpoints with different rate limit settings. Microsoft did this same thing with routing, which used to be all defined in one big Route.Config.cs but has now moved to attributes as the preferable way in MVC. Of course you could still support the settings approach too for defining things like global rules.

Thoughts?

Parsing reverse proxy IP

I think ReverseProxyIpParser.cs should take last item instead of first by default. Or at least it should be mentioned in docs / easy to override / investigated further.
Thing is that most reverse proxies (CloudFlare, Azure, etc) appends IP address is header already exists. So when you take first IP from list it is more likely to be spoofed.
So IMHO Last() is safer default. And some Func<Request, IPAddress> would be even better.

Using the version 2.1.0, I'm getting an empty response

I get the 429, but also an empty response :(
I'm using AspNetCoreRateLimit 2.1.0 with netcoreapp2.2

appsettings.json

"ClientRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "StackBlockedRequests": false,
    "ClientIdHeader": "Pim-Auth",
    "HttpStatusCode": 429,
    "EndpointWhitelist": [
      "get:/index.html",
      "get:/swagger-ui.css",
      "get:/swagger-ui-bundle.js",
      "get:/swagger-ui-standalone-preset.js"
    ],
    "ClientWhitelist": [  ],
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "15m",
        "Limit": 2
      }
    ]
  }

ConfigureServices

            services.AddOptions();
            services.AddMemoryCache();
            services.Configure<ClientRateLimitOptions>(configuration.GetSection("ClientRateLimiting"));

            services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
            services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

Configure (first line)

app.UseClientRateLimiting();

Any thoughts?

ClientRules does not overwrite GeneralRules

Hi, i think client rules does not overwrite general rules.
This is my configuration:

"ClientRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "StackBlockedRequests": false,
    "ClientIdHeader": "X-ClientId",
    "HttpStatusCode": 429,
    "ClientRules": [
      {
        "ClientId": "cid123",
        "Rules": [
          {
            "Endpoint": "*",
            "Period": "1h",
            "Limit": 100
          }
        ]
      }
    ],
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "1s",
        "Limit": 2
      },
      {
        "Endpoint": "*",
        "Period": "1h",
        "Limit": 5
      }
    ]
  }

Read X-Rate headers

Hi,
Is there any option to read X-Rate-Limit , X-Rate-Limit-Remaining, X-Reset-Limit-Reset fields from HttpContext response headers ?

Not working

I have configured like the below.

Startup: ConfigureServices Service Method

//API throattling
// 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("ClientRateLimiting"));
//load client rules from appsettings.json
services.Configure(Configuration.GetSection("ClientRateLimitPolicies"));
// inject counter and rules stores
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
// inject counter and rules distributed cache stores
//services.AddSingleton<IClientPolicyStore, DistributedCacheClientPolicyStore>();
//services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>();
var opt = new ClientRateLimitOptions();
ConfigurationBinder.Bind(Configuration.GetSection("ClientRateLimiting"), opt);

Startup: Configure method

app.UseClientRateLimiting();

appsettings.json

"ClientRateLimiting": {
"EnableEndpointRateLimiting": false,
"StackBlockedRequests": false,
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"EndpointWhitelist": [ "get:/solr/xxx", "get:/entity/yyy", "get:/entity/zzz" ],
"ClientWhitelist": [ "cMGAysfu_LfJ7HU8lYFlWtTyWMj85WdbmPShMWbBSgw" ],
"GeneralRules": [
{
"Endpoint": "",
"Period": "1s",
"Limit": 2
},
{
"Endpoint": "
",
"Period": "15m",
"Limit": 2
},
{
"Endpoint": "",
"Period": "12h",
"Limit": 4
},
{
"Endpoint": "
",
"Period": "7d",
"Limit": 10
}
]
},
"ClientRateLimitPolicies": {
"ClientRules": [
{
"ClientId": "cMGAysfu_LfJ7HU8lYFlWtTyWMj85WdbmPShMWbBSgw",
"Rules": [
{
"Endpoint": "/entity/yyy",
"Period": "1s",
"Limit": 1
},
{
"Endpoint": "/entity/yyy",
"Period": "15m",
"Limit": 5
}
]
}
]
}

Calling the service from PostMan tool below

http://localhost:57439/entity/yyy

and passing the auth token in the header and hit the same service 10 times but not received 429 error code.

Expected 6th time should get 429 error code.

Please see if you can help me on this.

Regards,
Ram

ClientRateLimiter throws error if header empty

I have set up the client rate limiter to extract the user's identity from a http header. If the header is present but it's value is an empty string, the SetIdentity method will break on line 99:

System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at AspNetCoreRateLimit.ClientRateLimitMiddleware.SetIdentity(HttpContext httpContext)
   at AspNetCoreRateLimit.ClientRateLimitMiddleware.<Invoke>d__5.MoveNext()

Can't have a zero rate limit

It seems I can't block an api call using 0 rate limit. You check if number is greater than 0 in your code. It would be useful to have some API that can be called only from localhost, like some jobs triggered by linux cron scheduler.

Nuget Update

Nuget is showing v1.0.1 as the latest. Update Nuget to v1.0.2?

Return Rate limit

Is it possible to return Total limit in the header.

X-Rate-Limit-Limit →1s
X-Rate-Limit-Remaining →49
X-Rate-Limit-Reset →2017-12-21T13:06:06.6567371Z

I want something like X-Rate-Limit-Limit -> 100 or with different header name. Is it possible ?

Configurable ReturnQuotaExceededResponse content

Hello Stefan!

First of all, thank your very much for this middleware. It's extremely useful. Big deal. True. /trump

I was thinking if it would be a good idea allow to change the response from the ReturnQuotaExceededResponse method without having to override it.

In my current API project, I want to reply always with a very specific JSON body format like:

{
    "id": "too_many_requests",
    "message": "Whoa! Calm down, cowboy!",
    "url": "https://myapi.com/docs/errors#too_many_requests",
    "details": "Quota exceeded. Maximum allowed: {rule.Limit} per {rule.Period}. Please try again in {retryAfter} seconds."
}

I'm aware that the string interpolation is not going to work if we get the output format from the configuration via options, but maybe the good old positional string format placeholders can do the trick.

So in the appsettings.json file:

"ClientRateLimiting": {
    ...
    "QuotaExceededResponse": {
        "ContentType": "application/json",
        "Content": "{{ \"id\": \"too_many_requests\", \"message\": \"Whoa! Calm down, cowboy!\", \"url\": \"https://myapi.com/docs/errors#too_many_requests\", \"details\": \"Quota exceeded. Maximum allowed: {0} per {1}. Please try again in {2} seconds.\" }}"
    }
}

And in the ClientRateLimitMiddleware.cs we will have:

public virtual Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter)
{
    var response = new QuotaExceededResponse
    {
        Content = $"API calls quota exceeded! maximum admitted {rule.Limit} per {rule.Period}."
        ContentType = "text/plain"
    };

    if (_options.QuotaExceededResponse != null)
    {
        // {0} rule.Limit
        // {1} rule.Period
        // {2} retryAfter
        // ... maybe all the rule properties?
        response.Content = string.Format(_options.QuotaExceededResponse.Content, rule.Limit, rule.Period, retryAfter);
        response.ContentType = _options.QuotaExceededResponse.ContentType;
    }

    if (!_options.DisableRateLimitHeaders)
    {
        httpContext.Response.Headers["Retry-After"] = retryAfter;
    }

    httpContext.Response.StatusCode = _options.HttpStatusCode;

    return httpContext.Response.WriteAsync(response);
}

Sorry if there's a typo or if the code does not compile. I just wrote it on the fly here.

Thank you for your time.

DR/Resilience when using Distributed Cache

I'm using Redis as the distributed store for rate limiting, but I'd like to know if there is anything in AspNetCoreRateLimit, or any plans to add anything to enable some kind of resilience.

At the moment it appears that should Redis be unreachable (for whatever reason) then my Web App is offline.

It would be really nice if there could be the ability to fall back gracefully - either to Memory Rate limiting, or just No Rate limiting at all.

Thoughts:

  • Configurable
  • Perhaps a static memory level switch that is set when a Redis exception occurs, which turn the Web App Rate Limit OFF for a period of time, or reverts to Memory Rate limiting
  • Ability to specify a fallback Redis connection string (I guess this really comes under the Microsoft.Extensions.Caching.Redis rather than AspNetCoreRateLimit)

Easy to use attributes?

In the .net version of this project, you could just specify an attribute and be done with it. No config or any hassle. Like this: [EnableThrottling(PerSecond = 5)]
Is this still possible anyhow in the core version?

Support Regex in the Path endpoints

today it supports only "string.contains" in the "GetMatchingRules".
unfortunately i own a controller in which i need to protect a single action (GET) that gets a guid in the path.
for example:
1)HTTP GET : "api/values/d3178e7b-acc0-41d1-a047-8453a6ca22c7"
all other actions in this controller are meaningless to throttle.
for example:
2) HTTP GET : "api/values/Seacrh/d3178e7b-acc0-41d1-a047-8453a6ca22c7"

so i expect to have the ability to protect action 1, without harming action 2.
unfortunately if i protect "get:/api/values/" so action 2 will be effected (as its path is contained in that path).

so the regex can be to protect only action 1.
^api/values/[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}$


## on the contrary, this can be also achieved if the library would support "attributes" above the actions, to affect a specific action. (instead of config file) which is even a better solution.

How to specify the cool down period?

Say a client has already exceeded the limit - 100 calls per minute, and have to wait for 10 minutes to be able call the api again. Can this tool support such scenario?

How to ignore query string and/or parameters

Hi,
I have two actions in my API
List- GET /api/customers?query=
Details - GET /api/customers/{id}
which is executed like this

GET /api/customers?query=a
GET /api/customers?query=b

GET /api/customers/1
GET /api/customers/2

I want to specify rules separately for this two endpoints, ignoring parameters and/or querystrings.
In asp.net 4.5 version of your library I overrided "GetEndpoint" method on ThrottlingFilter and I achieved what I want. How can I get same behavior in asp.net core?
I tried a lot of combination of wildcards in config, like this:

{ "Endpoint": "GET:/api/customers/*", "Period": "15m", "Limit": 50 }, { "Endpoint": "GET:/api/customers*", "Period": "15m", "Limit": 50 },

But I can't get what I need.
I'm using IpRateLimitProcessor which as I see use "IsMatch" extension method from WildcardMatcher - ClientRateLimitProcessor don't uses it.

@stefanprodan - maybe both implementations of middleware should allow to override part of codes that is resposible for controlling url match or you can explain is it possible to configure throttling out of the box as I described?

Limitation isn't applied on specific endpoint

Hi Stefan,

This is my appsettings.json
"IpRateLimiting": { "EnableEndpointRateLimiting": true, "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": "*:api/account/ActivateUser", "Period": "20m", "Limit": 1 } ] }

And this is the route that i'm calling from my angular spa
http://localhost:59323/api/account/ActivateUser

The limitation isn't applied. On the other side, if i'm using : "Endpoint": "*", everything works O.K

Any idea? Thanks

Abstract away the concept of a clientId in the Client Ratelimiter

A client_id can come in many forms. Your implementation is one of those forms.
Others come in the form of an OAuth2 POST where client_id/client_secret is in the form of an application/x-www-form-urlencoded value or in the header as basic auth.

In others the could show up somewhere in an application/json post.

The client filter is nice but I need to change where that client_id is coming from.

Suggestion: Sample code in docs should include necessary using statements/references

We don't use <TOptions> in our code and your sample code (copied from the wiki) would not compile without explicitly adding a reference to Microsoft.Extensions.Options.ConfigurationExtensions in project.json. Tracking down the package necessary to make the code compile without having a hint from a using statement or an actual dependencies section from a project.json made the adoption process a bit harder than it should have been. I later discovered your demo project (which obviously had all necessary references) after pulling the source but it was not immediately obvious (to me, anyway).

Hello, is this the most correct configuration? It is very important to me,Please!

public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddDistributedRedisCache(options =>
{
options.Configuration = "127.0.0.1:6379,connectTimeout=1000,connectRetry=1,syncTimeout=10000";
options.InstanceName = "RateLimitMaster";
});

        //configure ip rate limiting middle-ware
        services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
        services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));
    
        services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
        services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>();

        //configure client rate limiting middleware
        services.Configure<ClientRateLimitOptions>(Configuration.GetSection("ClientRateLimiting"));
        services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies"));
        services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();

        var opt = new ClientRateLimitOptions();
        ConfigurationBinder.Bind(Configuration.GetSection("ClientRateLimiting"), opt);

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseIpRateLimiting();
        //app.UseClientRateLimiting();

        app.UseMvc();
    }
}

ClientWhiteList not working

Hello!

I have the following settings

"IpRateLimiting": {
    "EnableEndpointRateLimiting": true,
    "StackBlockedRequests": false,
    "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": [ "test-client" ],
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "10s",
        "Limit": 5
      },
      {
        "Endpoint": "get:/v4/references/goods_links",
        "Period": "1h",
        "Limit": 1
      },
      {
        "Endpoint": "*",
        "Period": "15m",
        "Limit": 100
      }
      //{
      //  "Endpoint": "*",
      //  "Period": "12h",
      //  "Limit": 1000
      //}
      //},
      //{
      //  "Endpoint": "*",
      //  "Period": "7d",
      //  "Limit": 10000
      //}
    ]
  },

When I call endpoint get:/v4/references/goods_links I always get rate limit even with header X-ClientId test-client

Thanks!

EndpointWhitelist wildcard does not work

Here is my configuration

"IpRateLimiting": {
    "EnableEndpointRateLimiting": true,
    "StackBlockedRequests": false,
    "RealIpHeader": "X-Real-IP",
    "ClientIdHeader": "X-ClientId",
    "HttpStatusCode": 429,
    "IpWhitelist": [], // "127.0.0.1", "::1/10", "192.168.0.0/24"
    "EndpointWhitelist": [
      "get:*"
    ], //
    "ClientWhitelist": [ ],
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "1s",
        "Limit": 1
      },
      {
        "Endpoint": "*",
        "Period": "15m",
        "Limit": 100
      },
      {
        "Endpoint": "*",
        "Period": "12h",
        "Limit": 1000
      },
      {
        "Endpoint": "*",
        "Period": "7d",
        "Limit": 10000
      }
    ]
  }

Performing a GET request to /api/photos/{id} 2 times within 1s still give me response "429: API calls quota exceeded! maximum admitted 1 per 1s."

The EndpointWhitelist has [ "get:" ] as I want all GET request should be allowed. Even if I set it to "get:/api/photo/" still give same response (429)

Every request waiting for the lock and blocking other requests

Great pkg for throttling but I have a concern..

lock (_processLocker)
{
var entry = _counterStore.Get(counterId);
if (entry.HasValue)
{
// entry has not expired
if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)
{
// increment request count
var totalRequests = entry.Value.TotalRequests + 1;
// deep copy
counter = new RateLimitCounter
{
Timestamp = entry.Value.Timestamp,
TotalRequests = totalRequests
};
}
}
// stores: id (string) - timestamp (datetime) - total_requests (long)
_counterStore.Set(counterId, counter, rule.PeriodTimespan.Value);

According the code above, I see that you are locking every request with the static object and thus making all the requests to be processed synchronously, defeating the purpose of the web-server handling multiple requests at a time(asynchronously)

Am I missing something here ?

Redirect when block request from ip?

I want to block crawl data on my website, follow your example, it working perfect.

But i want to redirect to specify page (like 404, 500.html page?), how can i do did?

Sorry for my bad english. :(

IpRateLimitMiddleware can't parse caller IP

Getting this somewhat frequently in production on an Azure Web App. Not able to reproduce since my home IP parses correctly. Any ideas?

Exception: IpRateLimitMiddleware can't parse caller IP
Type: System.Exception

Stack Trace

System.Exception: IpRateLimitMiddleware can't parse caller IP ---> System.FormatException: An invalid IP address was specified. ---> System.Net.Sockets.SocketException: An invalid argument was supplied
   --- End of inner exception stack trace ---
   at System.Net.IPAddress.InternalParse(String ipString, Boolean tryParse)
   at AspNetCoreRateLimit.ReversProxyIpParser.GetClientIp(HttpContext context)
   at AspNetCoreRateLimit.IpRateLimitMiddleware.SetIdentity(HttpContext httpContext)
   --- End of inner exception stack trace ---
   at AspNetCoreRateLimit.IpRateLimitMiddleware.SetIdentity(HttpContext httpContext)
   at AspNetCoreRateLimit.IpRateLimitMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.d__2.MoveNext()

How to use in Microsoft Azure with load balancing

Hi Stefan,

thank you for the great feature! It's really cool!
My app is hosted in Azure. I've read some description about distributed store but could not find any example. I've tried something like (instead of memory store) with no luck:
services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>();

Would you be kind to share your idea how to use AspNetCoreRateLimit in Azure?

Thank you

Override method not getting called inherited from "IpRateLimitMiddleware"

I intended to customize message of rate limit. For that I have override ReturnQuotaExceededResponse method of IpRateLimitMiddleware. However, custom method doesn't called, it just displaying default message instead.

public class AppIpRateLimitMiddleware : IpRateLimitMiddleware
{       
 private readonly IpRateLimitOptions _options;

 public AppIpRateLimitMiddleware(RequestDelegate next,
     IOptions<IpRateLimitOptions> options,
     IRateLimitCounterStore counterStore,
     IIpPolicyStore policyStore,
     ILogger<IpRateLimitMiddleware> logger) : base(next, options, counterStore, policyStore, logger)
 {
     _options = options.Value;
 }
 public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter)
 {            
     var message = string.IsNullOrEmpty(_options.QuotaExceededMessage) ? $" Custom message: API calls quota exceeded! maximum admitted {rule.Limit} per {rule.Period}." : _options.QuotaExceededMessage;

     if (!_options.DisableRateLimitHeaders)
     {
         httpContext.Response.Headers["Retry-After"] = retryAfter;
     }

     httpContext.Response.StatusCode = _options.HttpStatusCode;
     return httpContext.Response.WriteAsync(message);
 }
}

Any thoughts?

use redis

hi
how can we use Redis in this project?
please explain me

Typo in ClientRateLimitPolicy example

In the code block that illustrates the ClientRateLimitPolicies, the first client rule has "ClientId", whereas the second rule has just "Client". I believe the second rule should also have "ClientId" to match the class property.

"ClientRateLimitPolicies": {
"ClientRules": [
{
"ClientId": "client-id-1",
"Rules": [
{
"Endpoint": "",
"Period": "1s",
"Limit": 10
},
{
"Endpoint": "
",
"Period": "15m",
"Limit": 200
}
]
},
{
"Client": "client-id-2",
"Rules": [
{
"Endpoint": "",
"Period": "1s",
"Limit": 5
},
{
"Endpoint": "
",
"Period": "15m",
"Limit": 150
},
{
"Endpoint": "*",
"Period": "12h",
"Limit": 500
}
]
}
]
}

Support decorative style limit declaration

Hey! This is an amazing project!

Can you, please, evaluate supporting declaring limits using decorative attributes?
This would align with other decorations pattern of asp.net (such as routes or authorization) and would give a very maintainable approach at declaring limits.

Thank you!

Rate limiting SignalR

Is it possible for this package to support rate limiting of SignalR? I noticed it was mentioned in the WebApiThrottle so I wonder if it had already been given some thought.

Currently, I've tried it and when enabled all requests for SignalR seem to be blocked.

use jwt in rate limiting

hi
how can I use jwt as client id fir client rate limiting?
i thing i should "ClientIdHeader": "Authorization" in my appsetting.json

Option not to send response headers

Great library!

I'm using this middleware to protect my API from abuse -- so I wouldn't expect any reasonable user to hit the limits that I've set. Therefore, if an abusive user does hit the limits then I don't want them to know my policy settings so that they can just wait and start spamming the API again after the timeout.

Therefore, I'd like an option to disable the sending of the Retry-After header and the X-Rate-Limit-xxx headers so that the client is not informed about when they can start abusing the API again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.