Настройка ограничения скорости и запросов в Nginx: limit_req и limit_conn
- DDoS-атаки типа HTTP Flood перегружают веб-сервер и бэкенды.
- Брутфорс паролей в формах авторизации (
/login,/wp-login.php). - Парсеры и боты выкачивают контент, создавая тысячи одновременных TCP-соединений.
1. Описание зон ограничения в секции http
В файле /etc/nginx/nginx.conf:
http {
# Ограничение частоты запросов по IP адресу (10 запросов в секунду)
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
# Строгая зона для страниц логина (1 запрос в секунду)
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# Ограничение количества одновременных TCP соединений с одного IP
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# HTTP-код ответа при блокировке (429 Too Many Requests вместо дефолтного 503)
limit_req_status 429;
limit_conn_status 429;
}2. Применение лимитов к виртуальным хостам и location
server {
listen 80;
server_name api.itstm.ru;
# Глобальное ограничение: не более 20 одновременных соединений на IP
limit_conn conn_limit_per_ip 20;
# Защита API с возможностью всплесков (burst)
location /api/ {
# Допускается всплеск до 20 запросов, обрабатываемых без искусственных задержек
limit_req zone=req_limit_per_ip burst=20 nodelay;
proxy_pass http://backend;
}
# Защита страницы входа
location /api/auth/login {
limit_req zone=login_limit burst=3 nodelay;
proxy_pass http://backend;
}
}3. Исключение доверенных IP из ограничений (Белый список)
geo $apply_limit {
default $binary_remote_addr;
127.0.0.1 "";
192.168.1.0/24 "";
}
limit_req_zone $apply_limit zone=whitelist_limit:10m rate=10r/s; Частые вопросы (FAQ)
Что делает параметр nodelay в директиве limit_req?
Без nodelay запросы сверх лимита rate, но в пределах burst, выстраиваются в очередь с искусственной задержкой. С параметром nodelay они выполняются немедленно, а все запросы сверх burst получают 429 ошибку.
Почему ключ зоны $binary_remote_addr лучше, чем $remote_addr?
Переменная $binary_remote_addr хранит IP-адрес в бинарном представлении (4 байта для IPv4, 16 байт для IPv6) вместо строки, что экономит в 4-8 раз больше оперативной памяти в keys_zone.