Rate limiting (ограничение частоты запросов)
Rate limiting (рейт лимит) это ограничение количества запросов или попыток соединения от одного источника за определённый промежуток времени. Используется, чтобы замедлить подбор паролей и скрейпинг без полной блокировки обычных пользователей.
Как это сочетается с другими защитами
Rate limiting не останавливает попытку подбора пароля или скрапинга полностью, оно замедляет её настолько, что атака становится непрактичной, при этом пропускает легитимных пользователей, которые изредка ошибаются при вводе пароля, без блокировки.
Где его чаще всего применяют
Попытки входа через SSH, формы входа в веб-приложение и API-эндпоинты: три самые часто атакуемые поверхности, и каждая обычно требует свой собственный лимит, настроенный под нормальный паттерн использования конкретного сервиса.
Ограничение частоты запросов на уровне веб-сервера и приложения разобрано здесь: руководство по защите от DDoS-атак для малого бизнеса.
Ограничение частоты HTTP-запросов в nginx
В nginx ограничение запросов реализовано в модуле ngx_http_limit_req_module. Вы объявляете общую зону с ключом по адресу клиента, а затем применяете её там, где нужно, например к форме входа:
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
location /login {
limit_req zone=login burst=5;
limit_req_status 429;
}
}
Поведение определяют несколько деталей из документации модуля. Размер всплеска (burst) по умолчанию равен нулю, а запросы выше лимита, но в пределах всплеска, задерживаются, а не отклоняются, если не добавить nodelay. За пределами всплеска запрос отклоняется, по умолчанию со статусом 503. Замена его через limit_req_status на 429 соответствует RFC 6585, где определён код "Too Many Requests" и допускается заголовок Retry-After. Один мегабайт зоны вмещает около 8 тысяч состояний на 64-битных платформах, а при заполнении удаляется наименее давно использованное состояние.
Подберите числа до включения ограничений. Директива limit_req_dry_run on;, доступная с nginx 1.17.1, считает избыточные запросы, ничего не ограничивая, поэтому по журналу можно увидеть, кого бы заблокировали. Если перед nginx стоит CDN или прокси, ключом будет адрес прокси, пока вы не восстановите настоящий адрес клиента. Дополнительные меры описаны в руководстве по безопасности nginx.
Ограничение попыток соединения в firewall
Ограничение частоты можно разместить и ниже веб-сервера, что защищает службы, не использующие HTTP. В ufw встроенное действие limit блокирует адрес, который пытается установить 6 и более соединений за 30 секунд, как описано в руководстве ufw:
sudo ufw limit 22/tcp
В nftables контроль тоньше. Вики nftables показывает ограничение SSH по источнику: каждый адрес отслеживается в динамическом наборе, записи которого истекают после 60 секунд бездействия, и с одного адреса принимается не больше 3 новых соединений в минуту:
set my_ssh_ratelimit {
type ipv4_addr
timeout 60s
flags dynamic
}
ct state new tcp dport 22 update @my_ssh_ratelimit { ip saddr limit rate 3/minute } accept
Соединения сверх лимита не подходят под правило accept и попадают под политику drop цепочки (см. политику default deny). В руководстве nft объясняется, что оператор limit работает по алгоритму token bucket с размером всплеска по умолчанию пять пакетов.
Ограничение такого подхода в том, что он считает попытки, а не результат. Он не отличает опечатку в пароле от атаки, а офис за одним адресом делит один общий лимит. Сочетайте его с fail2ban, который реагирует на неудачные входы в журналах, а взгляд на уровне трафика есть в руководстве по защите от DDoS.
Связанные термины: fail2ban, Атака подбором, DDoS атака, WAF, limit_req.
Часто задаваемые вопросы
Заменяет ли rate limiting необходимость в firewall?
Нет, они решают разные задачи. Firewall контролирует, каким соединениям вообще разрешено достигать сервиса; rate limiting контролирует, как быстро уже разрешённое соединение может повторять действие.
Может ли rate limiting случайно заблокировать легитимных пользователей?
Да, если настроено слишком агрессивно, особенно для пользователей, делящих один исходящий IP-адрес, например офисную сеть. Лимиты нужно настраивать по реальным паттернам трафика, а не просто угадывать.
Какой инструмент обычно используют для этого на Linux?
fail2ban чаще всего используется для SSH и других сервисов на основе логов, а у nginx и большинства веб-фреймворков есть собственные встроенные модули ограничения частоты запросов для HTTP-трафика.
Какой HTTP-статус должен возвращать rate limit?
RFC 6585 определяет для этого случая код 429 Too Many Requests и допускает заголовок Retry-After. nginx по умолчанию возвращает 503, поэтому задайте limit_req_status 429, чтобы клиенты и инструменты распознавали ограничение частоты.
Как выбрать значения лимитов, не сломав доступ реальным пользователям?
Сначала измерьте. В nginx limit_req_dry_run считает избыточные запросы, не блокируя их, поэтому можно изучить журналы на реальном трафике до включения ограничений. Используйте запас на всплеск, чтобы короткие законные пики проходили.
Хотите увидеть, в каком состоянии ваш сервер?
Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.
Получить бесплатную проверку сервераОткрыть Security Lab