В nginx есть параметр limit_req_zone, с его помощью можно ограничивать количество одновременных запросов к сайту с одного ip адреса.
Создадим файл /etc/nginx/conf.d/mapping.conf
geo $limited {
default 1;
<ip_address> 0;
}
map $limited $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=defender:10m rate=200r/s;$binary_remote_addr - зарезервированная переменная в nginx, в ней будет хранится ip клиента.
zone=defender:10m - defender это произвольное имя зоны, 10m - объем памяти в мегабайтах для хранения данных в ней.
rate=200r/s - ограничение равное 200 запросов в секунды с одного ip клиента.
Тут мы используем модуль geo, который нам позволяет задать не просто IP адрес, но и подсеть из адресов. Присваиваем это все переменной $limited и создаем маппинг, где дефолтное значение равно 1, добавленные нами IP адреса или подсети будет иметь значение 0.
Значение 0 в данном случае разрешающее, т.е. то, что имеет значение 0 не будет попадать под ограничение лимитов зоны.
Далее мы создаем маппинг на основе $limited переменной и записываем это в новую переменную $limit. Если на предыдущем шаге, в модуле geo мы получили 0, то в новом маппинге 0 будет соответствовать пустая строка, а 1 будет соответствовать адрес клиента.
Получается, что если мы имеем пустую строку, то у нас нет IP адреса к которому можно было бы применить ограничения зоны, следовательно он пропускается.
Если совсем упрощенно, то <ip_address> 0; - это и есть наш "белый список", остальное будет заполнено автоматически.
Посмотреть белый адрес кстати можно так:
curl ident.me
Потом в нужный на location добавляем строки:
location / {
limit_req zone=defender burst=10 nodelay;
try_files $uri $uri/ /index.php?$args;
}Тут мы указываем какую зону использовать для данного локейшена. Параметр burst - скачок, возможный сверх лимита, в данном случае на 10 запросов больше.
nodelay - говорит отдавать статус (503 по дефолту) немедленно, когда исчерпан лимит.
Если нужно изменить отдаваемый статус при достижении лимита:
limit_req_status 429;
#nginx