Поиск по сайту:

Как использовать ограничение скорости на Nginx


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

Ограничение скорости не всегда может спасти вас от резких всплесков трафика, поэтому, если ваш сервер действительно нуждается в защите, хорошей практикой будет настроить CDN для всего сайта впереди или, по крайней мере, настроить балансировку нагрузки HAProxy для разделения нагрузки между несколькими серверами.

Как включить ограничение скорости в Nginx

Во-первых, мы должны определить «зону» ограничения скорости. Вы можете настроить несколько зон и назначить разные блоки местоположений для каждой зоны. А пока давайте создадим базовую зону, добавив следующую строку в контекстный блок server или http:

limit_req_zone $binary_remote_addr zone=foo:10m rate=5r/s;

Команда limit_req_zone определяет зону, используя $binar_remote_addr в качестве идентификатора. Это IP-адрес клиента, но вы также можете использовать что-то вроде $server_name , чтобы ограничить его для каждого сервера.

Флаг zone называет зону (в данном случае «foo») и выделяет для нее блок памяти. Nginx должен хранить IP-адреса для проверки, поэтому ему нужна память для каждой зоны. В этом случае 10m выделяет 10 мегабайт памяти, чего достаточно для 160 000 подключений в секунду (чего вы, скорее всего, никогда не увидите на одном сервере).

Последний флаг — это скорость, которая определяет количество подключений по умолчанию для каждого клиента. Здесь установлено значение 5 запросов в секунду, максимальное – 10, хотя вы можете сделать его медленнее, отформатировав его как 30r/m (для 30 запросов в минуту).

После того, как зона настроена, пришло время ее использовать.

location {
  limit_req zone=foo burst=10 nodelay;

  //do webserver stuff
}

Директива limit_req выполняет всю тяжелую работу и назначает блок местоположения зоне ограничения. Параметр burst дает клиенту некоторое пространство для маневра и позволяет ему делать дополнительные запросы, если они не превышают среднюю скорость.

Под капотом он добавляет пакетные запросы в «очередь», которая сокращается каждые 100 мс. Это может сделать ваш сайт медленным, поэтому параметр nodelay устраняет эту задержку в очереди. С текущей конфигурацией, если вы сделали 10 запросов одновременно, параметр nodelay разрешит все 10 запросов, а затем ограничит скорость следующих запросов до 5 запросов в секунду. Если вы сделаете еще 6 запросов, он разрешит 5 и отклонит 6-й, поскольку он превышает лимит. Как только клиент прекращает делать запросы, очередь сокращается со скоростью, зависящей от вашей скорости.

Двухступенчатое ограничение скорости

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

Это делается путем назначения значения задержки в директиве limit_req :

limit_req zone=ip burst=10 delay=5;

Здесь первые 5 запросов пройдут мгновенно. Затем клиенту разрешается еще 5 запросов каждые 100 мс, пока пакет не заполнится, после чего они ограничиваются переменной скорости.

Скорость ограничения пропускной способности

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

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

limit_rate 100k
limit_rate_after 1m

Это устанавливает максимальную скорость загрузки 100 Кбит/с после загрузки 1 мегабайта. Однако это измеряется для каждого соединения, и пользователи могут открывать несколько соединений. Чтобы решить эту проблему, вам нужно добавить зону ограничения соединений рядом с зоной ограничения запросов:

limit_conn_zone $binary_remote_address zone=bar:10m
limit_req_zone $binary_remote_addr zone=foo:10m rate=5r/s;

Это создает 10-мегабайтную зону под названием «бар», которая отслеживает на основе IP-адреса. Вы можете использовать это вместе с директивой limit_conn, чтобы включить ограничение подключений.

server {

  limit_conn bar 5;

  location /static/ {
    limit_conn bar 1;
    limit_rate 100k;
    limit_rate_after 1m;
  }
}

Поскольку большинство браузеров открывают несколько подключений при обычном просмотре, мы хотим установить более высокий глобальный лимит подключений, а затем установить ограничение на 1 подключение для загрузки.