limit req не для всех

Maxim Dounin mdounin at mdounin.ru
Mon Oct 26 14:56:28 MSK 2009


Hello!

On Mon, Oct 26, 2009 at 01:51:01PM +0300, Igor Sysoev wrote:

> On Mon, Oct 26, 2009 at 06:16:19AM -0400, webscripter wrote:
> 
> > Хочу ограничить кол-во сессий в секунду, но не для всех адресов. Есть список белых заданных с помощью директивы geo через переменную $white. А как ее подставить в конфиг для location / пока не понял. Помогите плиз.
> 
> Пока никак.

Да ладно тебе - уходишь по if ($white) в другой location, и 
делаешь там всё что душе угодно.

> У меня был идея сделать как-то так:
> 
> limit_req_zone  $...  zone=BOTS:10m    rate=1r/s;
> limit_req_zone  $...  zone=GOOD:10m    rate=5r/s;
> 
> geo  $limit  {
>      default          1;
> 
>      # while list
>      192.168.1.0/24   0;
>      192.168.10.0/24  0;
> }
> 
> server {
> 
>    limit_req   zone=BOTS  burst=1   if $limit;
>    limit_req   zone=GOOD  burst=20  if $limit;
>    limit_req   off;
> 
> или
> 
> geo  $while  {
>      default          0;
> 
>      192.168.1.0/24   1;
>      192.168.10.0/24  1;
> }
> 
> server {
> 
>    limit_req   off  if $white;
>    limit_req   zone=GOOD  burst=20;
>    limit_req   zone=BOTS  burst=1;
> 
> 
> 
> Но тут есть вопросы - как должны срабатывать правила: по первому
> соотвествию if или нет. Если есть несколько правил без if - проверять
> все или нет ?

IMHO, логично было бы проверять все правила, для которых if 
отсутствет или истина.

Но тут возникает всяких неочевидностей.  В первую очередь это 
связано с тем фактом что подсчёт и лимитирование - вообще говоря 
две совершенно разные операции...

1. Если в конфиге написано как-нибудь так:

    limit_req zone=NAME burst=10;
    limit_req zone=NAME burst=1 if $bad;

Для пропущенных запросов из $bad надо увеличить счётчик только на 
1, несмотря на две проверки в одной и той же зоне.

2. Что делать, если одно из правил запрос "зарезало".  Должны ли при этом 
увеличиваться счётчики во всех остальных?

Если говорить о последовательно обработке (проверили правило, 
увеличили счётчики, перешли к следующему правилу), то в 
конструкции вида

    limit_req zone=NAME burst=10;
    limit_req zone=NAME burst=1 if $bad;

"плохой" клиент может съесть всю доступную обычным клиентам 
полосу.  Чтобы он этого не мог сделать - это конкретное простое 
условие можно переписать в виде

    limit_req zone=NAME burst=1 if $bad;
    limit_req zone=NAME burst=10;

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

Maxim Dounin





More information about the nginx-ru mailing list