Поиск…


замечания

AspNetCoreRateLimit - это приложение для ограничения скорости передачи данных с открытым исходным кодом ASP.NET Core, предназначенное для контроля скорости запросов, которые клиенты могут сделать в веб-API или приложении MVC на основе IP-адреса или идентификатора клиента.

Ограничение скорости на основе IP-адреса клиента

С помощью промежуточного программного обеспечения IpRateLimit вы можете установить несколько ограничений для разных сценариев, например, разрешить IP или IP-диапазону делать максимальное количество вызовов за такой промежуток времени, как в секунду, 15 минут и т. Д. Вы можете определить эти лимиты для решения всех запросов, сделанных для API или вы можете ограничить пределы для каждого пути URL или HTTP-глагола и пути.

Настроить

Установка NuGet :

Install-Package AspNetCoreRateLimit

Код запуска :

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"));

    //load ip rules from appsettings.json
    services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

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

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

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

    app.UseIpRateLimiting();

    app.UseMvc();
}

Вы должны зарегистрировать промежуточное программное обеспечение перед любыми другими компонентами, кроме loggerFactory.

если вы загружаете баланс своего приложения, вам нужно будет использовать IDistributedCache с Redis или SQLServer, чтобы все экземпляры IDistributedCache имели одинаковое хранилище ограничений скорости. Вместо хранилищ в памяти вы должны вводить распределенные хранилища следующим образом:

    // inject counter and rules distributed cache stores
    services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
    services.AddSingleton<IRateLimitCounterStore,DistributedCacheRateLimitCounterStore>();

Конфигурация и общие правила appsettings.json :

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

Если для параметра EnableEndpointRateLimiting установлено значение false то ограничения будут применяться в глобальном масштабе, и будут применяться только правила, имеющие конечную точку * . Например, если вы установите ограничение в 5 вызовов в секунду, любой HTTP-вызов любой конечной точки будет учитываться в этом пределе.

Если для параметра EnableEndpointRateLimiting установлено значение true ограничения будут применяться для каждой конечной точки, как в {HTTP_Verb}{PATH} . Например, если вы устанавливаете ограничение в 5 вызовов в секунду для *:/api/values клиент может вызывать GET /api/values 5 раз в секунду, а также 5 раз PUT /api/values .

Если для StackBlockedRequests установлено значение false отклоненные вызовы не добавляются в счетчик дроссельной заслонки. Если клиент делает 3 запроса в секунду, и вы установили ограничение на один вызов в секунду, другие лимиты, такие как счетчики на минуту или день, будут записывать только первый вызов, тот, который не был заблокирован. Если вы хотите, чтобы отклоненные запросы StackBlockedRequests в других пределах, вам необходимо установить значение StackBlockedRequests в true .

RealIpHeader используется для извлечения клиентского IP- RealIpHeader когда ваш сервер Kestrel находится за обратным прокси-сервером, если ваш прокси использует другой заголовок, тогда X-Real-IP использует этот параметр для его настройки.

ClientIdHeader используется для извлечения идентификатора клиента для белого листинга, если идентификатор клиента присутствует в этом заголовке и соответствует значению, указанному в ClientWhitelist, тогда не применяются ограничения по скорости.

Переопределить общие правила для определенных IP-адресов appsettings.json :

 "IpRateLimitPolicies": {
    "IpRules": [
      {
        "Ip": "84.247.85.224",
        "Rules": [
          {
            "Endpoint": "*",
            "Period": "1s",
            "Limit": 10
          },
          {
            "Endpoint": "*",
            "Period": "15m",
            "Limit": 200
          }
        ]
      },
      {
        "Ip": "192.168.3.22/25",
        "Rules": [
          {
            "Endpoint": "*",
            "Period": "1s",
            "Limit": 5
          },
          {
            "Endpoint": "*",
            "Period": "15m",
            "Limit": 150
          },
          {
            "Endpoint": "*",
            "Period": "12h",
            "Limit": 500
          }
        ]
      }
    ]
  }

Поле IP поддерживает значения IP v4 и v6 и диапазоны, такие как «192.168.0.0/24», «fe80 :: / 10» или «192.168.0.0-192.168.0.255».

Определение правил ограничения ставок

Правило состоит из конечной точки, периода и предела.

Формат {HTTP_Verb}:{PATH} точки {HTTP_Verb}:{PATH} , вы можете настроить таргетинг на любой HTTP-глагол, используя символ asterix.

Формат периода: {INT}{PERIOD_TYPE} , вы можете использовать один из следующих типов периодов: s, m, h, d .

Предельный формат - {LONG} .

Примеры :

Скорость ограничивает все конечные точки до 2 вызовов в секунду:

{
 "Endpoint": "*",
 "Period": "1s",
 "Limit": 2
}

Если с одного и того же IP-адреса в течение одной секунды вы сделаете 3 вызова GET для api / values, последний вызов будет заблокирован. Но если в течение той же секунды вы также вызываете PUT api / values, запрос будет проходить, потому что это другая конечная точка. Когда ограничение скорости конечной точки включено, каждый вызов ограничивается скоростью на основе {HTTP_Verb}{PATH} .

Ограничение скорости звонка с любыми HTTP-глаголами to /api/values до 5 вызовов за 15 минут:

{
 "Endpoint": "*:/api/values",
 "Period": "15m",
 "Limit": 5
}

Ограничение скорости GET вызов /api/values до 5 вызовов в час:

{
 "Endpoint": "get:/api/values",
 "Period": "1h",
 "Limit": 5
}

Если с одного и того же IP-адреса за один час вы сделаете 6 GET-вызовов для api / values, последний звонок будет заблокирован. Но если в тот же час вы вызываете GET api / values ​​/ 1, запрос будет проходить, потому что это другая конечная точка.

Поведение

Когда клиент делает HTTP-вызов, IpRateLimitMiddleware делает следующее:

  • извлекает IP-адрес, идентификатор клиента, HTTP-глагол и URL-адрес из объекта запроса, если вы хотите реализовать свою собственную логику извлечения, вы можете переопределить IpRateLimitMiddleware.SetIdentity
  • ищет IP-адрес, идентификатор клиента и URL-адрес в белых списках, если какие-либо совпадения, то никаких действий не предпринимается
  • поиск в правилах IP для соответствия, все применяемые правила группируются по периоду, для каждого периода используется наиболее ограничивающее правило
  • ищет в общих правилах для соответствия, если общее правило, которое соответствует, имеет определенный период, отсутствующий в правилах IP, тогда это общее правило также используется
  • для каждого правила сопоставления счетчик ограничения скорости увеличивается, если значение счетчика больше, чем предел правила, тогда запрос блокируется

Если запрос блокируется, клиент получает текстовый ответ следующим образом:

Status Code: 429
Retry-After: 58
Content: API calls quota exceeded! maximum admitted 2 per 1m.

Вы можете настроить ответ, изменив эти параметры HttpStatusCode и QuotaExceededMessage , если вы хотите реализовать свой собственный ответ, вы можете переопределить IpRateLimitMiddleware.ReturnQuotaExceededResponse . Значение заголовка Retry-After выражается в секундах.

Если запрос не получает ограничение по скорости, то самый длинный период, определенный в правилах сопоставления, используется для составления заголовков X-Rate-Limit, эти заголовки вводятся в ответ:

X-Rate-Limit-Limit: the rate limit period (eg. 1m, 12h, 1d)
X-Rate-Limit-Remaining: number of request remaining 
X-Rate-Limit-Reset: UTC date time when the limits resets

По умолчанию заблокированный запрос регистрируется с помощью Microsoft.Extensions.Logging.ILogger , если вы хотите реализовать свой собственный журнал, вы можете переопределить IpRateLimitMiddleware.LogBlockedRequest . Регистратор по умолчанию генерирует следующую информацию, когда запрос получает ограничение по скорости:

info: AspNetCoreRateLimit.IpRateLimitMiddleware[0]
      Request get:/api/values from IP 84.247.85.224 has been blocked, quota 2/1m exceeded by 3. Blocked by rule *:/api/value, TraceIdentifier 0HKTLISQQVV9D.

Ограничения скорости обновления во время выполнения

При запуске приложения правила ограничения скорости IP, определенные в appsettings.json , загружаются в кеш либо MemoryCacheClientPolicyStore либо DistributedCacheIpPolicyStore зависимости от того, какой тип поставщика кеша вы используете. Вы можете получить доступ к хранилищу политик Ip внутри контроллера и изменить правила IP следующим образом:

public class IpRateLimitController : Controller
{
    private readonly IpRateLimitOptions _options;
    private readonly IIpPolicyStore _ipPolicyStore;

    public IpRateLimitController(IOptions<IpRateLimitOptions> optionsAccessor, IIpPolicyStore ipPolicyStore)
    {
        _options = optionsAccessor.Value;
        _ipPolicyStore = ipPolicyStore;
    }

    [HttpGet]
    public IpRateLimitPolicies Get()
    {
        return _ipPolicyStore.Get(_options.IpPolicyPrefix);
    }

    [HttpPost]
    public void Post()
    {
        var pol = _ipPolicyStore.Get(_options.IpPolicyPrefix);

        pol.IpRules.Add(new IpRateLimitPolicy
        {
            Ip = "8.8.4.4",
            Rules = new List<RateLimitRule>(new RateLimitRule[] {
                new RateLimitRule {
                    Endpoint = "*:/api/testupdate",
                    Limit = 100,
                    Period = "1d" }
            })
        });

        _ipPolicyStore.Set(_options.IpPolicyPrefix, pol);
    }
}

Таким образом, вы можете сохранить ограничения скорости IP в базе данных и вставить их в кеш после каждого запуска приложения.

Ограничение скорости на основе идентификатора клиента

С промежуточным программным обеспечением ClientRateLimit вы можете установить несколько ограничений для разных сценариев, таких как предоставление клиенту максимального количества вызовов за такой промежуток времени, как в секунду, 15 минут и т. Д. Вы можете определить эти ограничения для адресации всех запросов, сделанных в API, или вы может ограничивать пределы для каждого пути URL или HTTP-глагола и пути.

Настроить

Установка NuGet :

Install-Package AspNetCoreRateLimit

Код запуска :

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<ClientRateLimitOptions>(Configuration.GetSection("ClientRateLimiting"));

    //load client rules from appsettings.json
    services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies"));

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

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

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

    app.UseClientRateLimiting();

    app.UseMvc();
}

Вы должны зарегистрировать промежуточное программное обеспечение перед любыми другими компонентами, кроме loggerFactory.

если вы загружаете баланс своего приложения, вам нужно будет использовать IDistributedCache с Redis или SQLServer, чтобы все экземпляры IDistributedCache имели одинаковое хранилище ограничений скорости. Вместо хранилищ в памяти вы должны вводить распределенные хранилища следующим образом:

    // inject counter and rules distributed cache stores
    services.AddSingleton<IClientPolicyStore, DistributedCacheClientPolicyStore>();
    services.AddSingleton<IRateLimitCounterStore,DistributedCacheRateLimitCounterStore>();

Конфигурация и общие правила appsettings.json :

  "ClientRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "StackBlockedRequests": false,
    "ClientIdHeader": "X-ClientId",
    "HttpStatusCode": 429,
    "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
      }
    ]
  }

Если для параметра EnableEndpointRateLimiting установлено значение false то ограничения будут применяться в глобальном масштабе, и будут применяться только правила, имеющие конечную точку * . Например, если вы установите ограничение в 5 вызовов в секунду, любой HTTP-вызов любой конечной точки будет учитываться в этом пределе.

Если для параметра EnableEndpointRateLimiting установлено значение true ограничения будут применяться для каждой конечной точки, как в {HTTP_Verb}{PATH} . Например, если вы устанавливаете ограничение в 5 вызовов в секунду для *:/api/values клиент может вызывать GET /api/values 5 раз в секунду, а также 5 раз PUT /api/values .

Если для StackBlockedRequests установлено значение false отклоненные вызовы не добавляются в счетчик дроссельной заслонки. Если клиент делает 3 запроса в секунду, и вы установили ограничение на один вызов в секунду, другие лимиты, такие как счетчики на минуту или день, будут записывать только первый вызов, тот, который не был заблокирован. Если вы хотите, чтобы отклоненные запросы StackBlockedRequests в других пределах, вам необходимо установить значение StackBlockedRequests в true .

ClientIdHeader используется для извлечения идентификатора клиента, если идентификатор клиента присутствует в этом заголовке и соответствует значению, указанному в ClientWhitelist, тогда не применяются ограничения по скорости.

Переопределить общие правила для определенных клиентов appsettings.json :

 "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
          }
        ]
      }
    ]
  }

Определение правил ограничения ставок

Правило состоит из конечной точки, периода и предела.

Формат {HTTP_Verb}:{PATH} точки {HTTP_Verb}:{PATH} , вы можете настроить таргетинг на любой HTTP-глагол, используя символ asterix.

Формат периода: {INT}{PERIOD_TYPE} , вы можете использовать один из следующих типов периодов: s, m, h, d .

Предельный формат - {LONG} .

Примеры :

Скорость ограничивает все конечные точки до 2 вызовов в секунду:

{
 "Endpoint": "*",
 "Period": "1s",
 "Limit": 2
}

Если в течение той же секунды клиент сделает 3 GET-вызова api / values, последний вызов будет заблокирован. Но если в течение той же секунды он вызывает PUT api / values, запрос будет проходить, потому что это другая конечная точка. Когда ограничение скорости конечной точки включено, каждый вызов ограничивается скоростью на основе {HTTP_Verb}{PATH} .

Ограничение скорости звонка с любыми HTTP-глаголами to /api/values до 5 вызовов за 15 минут:

{
 "Endpoint": "*:/api/values",
 "Period": "15m",
 "Limit": 5
}

Ограничение скорости GET вызов /api/values до 5 вызовов в час:

{
 "Endpoint": "get:/api/values",
 "Period": "1h",
 "Limit": 5
}

Если через час клиент совершит 6 GET-вызовов для api / values, последний звонок будет заблокирован. Но если в тот же час он называет GET api / values ​​/ 1, запрос будет проходить, потому что это другая конечная точка.

Поведение

Когда клиент делает HTTP-вызов, ClientRateLimitMiddleware делает следующее:

  • извлекает идентификатор клиента, HTTP-глагол и URL-адрес из объекта запроса, если вы хотите реализовать свою собственную логику извлечения, вы можете переопределить ClientRateLimitMiddleware.SetIdentity
  • ищет идентификаторы и URL-адреса Клиента в белых списках, если какие-либо совпадения, то никаких действий не предпринимается
  • поиск в правилах Клиента для соответствия, все применяемые правила сгруппированы по периоду, за каждый период используется наиболее ограничительное правило
  • выполняет поиск в общих правилах для соответствия, если общее правило, которое соответствует, имеет определенный период, отсутствующий в правилах Клиента, тогда это общее правило также используется
  • для каждого правила сопоставления счетчик ограничения скорости увеличивается, если значение счетчика больше, чем предел правила, тогда запрос блокируется

Если запрос блокируется, клиент получает текстовый ответ следующим образом:

Status Code: 429
Retry-After: 58
Content: API calls quota exceeded! maximum admitted 2 per 1m.

Вы можете настроить ответ, изменив эти параметры HttpStatusCode и QuotaExceededMessage , если вы хотите реализовать свой собственный ответ, вы можете переопределить ClientRateLimitMiddleware.ReturnQuotaExceededResponse . Значение заголовка Retry-After выражается в секундах.

Если запрос не получает ограничение по скорости, то самый длинный период, определенный в правилах сопоставления, используется для составления заголовков X-Rate-Limit, эти заголовки вводятся в ответ:

X-Rate-Limit-Limit: the rate limit period (eg. 1m, 12h, 1d)
X-Rate-Limit-Remaining: number of request remaining 
X-Rate-Limit-Reset: UTC date time when the limits resets

По умолчанию заблокированный запрос регистрируется с помощью Microsoft.Extensions.Logging.ILogger , если вы хотите реализовать свой собственный журнал, вы можете переопределить ClientRateLimitMiddleware.LogBlockedRequest . Регистратор по умолчанию генерирует следующую информацию, когда запрос получает ограничение по скорости:

info: AspNetCoreRateLimit.ClientRateLimitMiddleware[0]
      Request get:/api/values from ClientId client-id-1 has been blocked, quota 2/1m exceeded by 3. Blocked by rule *:/api/value, TraceIdentifier 0HKTLISQQVV9D.

Ограничения скорости обновления во время выполнения

При запуске приложения правила ограничения скорости клиента, определенные в appsettings.json , загружаются в кеш либо MemoryCacheClientPolicyStore либо DistributedCacheClientPolicyStore зависимости от того, какой тип поставщика кеша вы используете. Вы можете получить доступ к хранилищу политик клиента внутри контроллера и изменить правила следующим образом:

public class ClientRateLimitController : Controller
{
    private readonly ClientRateLimitOptions _options;
    private readonly IClientPolicyStore _clientPolicyStore;

    public ClientRateLimitController(IOptions<ClientRateLimitOptions> optionsAccessor, IClientPolicyStore clientPolicyStore)
    {
        _options = optionsAccessor.Value;
        _clientPolicyStore = clientPolicyStore;
    }

    [HttpGet]
    public ClientRateLimitPolicy Get()
    {
        return _clientPolicyStore.Get($"{_options.ClientPolicyPrefix}_cl-key-1");
    }

    [HttpPost]
    public void Post()
    {
        var id = $"{_options.ClientPolicyPrefix}_cl-key-1";
        var clPolicy = _clientPolicyStore.Get(id);
        clPolicy.Rules.Add(new RateLimitRule
        {
            Endpoint = "*/api/testpolicyupdate",
            Period = "1h",
            Limit = 100
        });
        _clientPolicyStore.Set(id, clPolicy);
    }
}

Таким образом, вы можете хранить лимиты ставок клиента в базе данных и вставлять их в кеш после каждого запуска приложения.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow