Рекомендация: прежде чем заниматься тюнингом Nginx, пожалуйста, сделайте бекап конфигурации, вы делаете всё на свой страх и риск.
Рассмотрим ситуацию
Школьники дудосеры устроили нагрузочное тестирование и натравили на твой сервак какой-нибудь "jopasiski-3000", и бьют нам каналы syn-flood'ом, нам придётся отбивать эту херню.
Есть 3 варианта как поступить здесь:
- Подключить DDosGuard
- Использовать Cloudflare
Первый вариант нам может не подойти из-за отсутствия бюджета на данную защиту, остаётся Cloudflare и... Тюнинг Nginx!
(Об Cloudflare как-нибудь потом.)
Ну так чё делать то?
Блядь ёпта, nginx затюнить и отбить всю эту хуйню-муйню. Понятное дело оно особо при дидосах не спасет, но со сканерами и "jopasiski-3000" сможет справится.
В nginx есть параметр limit_req_zone
, который ограничивает количество одновременныхх запросов с одного айпишника.
Пиздуем тюнить Nginx
Создаём файл по пути: /etc/nginx/conf.d/assholes.conf
geo $limited {
default 1;
192.168.1.1 0; # Этот IP не лимитируется
10.0.0.0/24 0; # 10.0.0.0/24 тоже без ограничений
}
map $limited $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=nsvk13:20m rate=200r/s;
limit_req_zone
— ключ для отслеживания запросов.
$binary_remote_addr
— системная переменная nginx, внутри хранит ip-адрес клиента.
zone=nsvk13:20m
— произвольное имя зоны, 20m это объём памяти в мегабайтах для хранения данных. В этой зоне хранятся данные о количество запросов от каждого уникального клиента.
rate=200r/s
— ограничение равное 200 запросов в секунды с одного ip-клиента.
Для рейта есть такая табличка
Сценарий rate burst
-------------------------------------------
API с высокой нагрузкой 100r/s 200
Средний веб-сайт 50r/s 100
Анти-DDoS защита 10r/s 20
CDN или кеширующий прокси 500r/s 1000
Тестируем так:
ab -n 1000 -c 50 http://nsvk13.dev/
wrk -t4 -c100 -d10s http://nsvk13.dev/
И смотрим нет ли ошибок 503 Слишком дохуя запросов и корректно ли отрабатывает лимит.
А как рассчитать эту 20m памяти?..
Максимальное количество клиентов = размер зоны в байтах / размерзаписиклиента
Ладно сложно, на простом:
Пример расчёта для 20m (20 мегабайт = 20 х 1024 = 1024 = 20 971 520 байт):
20 971 529 / 128 = 163 840
То есть, зона 20m
может хранить лимиты примерно для 163 тысяч уникальных клиентов одновременно.
А откуда взялось 128?
Как я написал выше, nginx хранит каждого уникального клиента (ключ $binary_remote_addr
или другое значение), в зоне, используя примерно 128 байт на запись.
Есть такая табличка:
< 20 000 = 4m
~80 000 = 10m
~160 000 = 20m
500 000+ = 64m
Ещё можно настроить burst
для резких пиков, burst
позволяет превышать rate
, прежде чем включиться жёсткий лимит.
Например
limit_req zone=nsvk13 burst=400 nodelay;
Клиенту разрешается до 400 мгновенных запросов, а затем он падает в ограничение 200r/s.
nodelay
означает, что первые 400 запросов проходят сразу, а потом начинается строгий лимит.
Теперь по мапингам и гео хуйне
В первом блоке про гео
- Все юзеры получат
$limited = 1
(по умолчанию). - Те, кто с
192.168.1.1
или из.10.0.0.0/24
, получат$limited = 0
и не будут ограничены.
Во втором блоке про мапинг
- Если $limited = 1, то $limit = $binary_remote_addr (IP-адрес клиента).
- Если $limited = 0, то $limit = "", и клиент не попадает в limit_req_zone.
Короче делаем что-то вроде белого списка и кто в него не входит — идёт нахуй! Надеюсь понятно объяснил.
Теперь чтобы вся эта поебота заработала, нужно прописать в нужный локейшен:
location / {
limit_req zone=nsvk13 burst=10 nodelay;
try_files $uri $uri/ index.php?$args;
}
Чтобы отдавтаь нужный стату при достижении лимита, делаем:
location / {
limit_req_status: 429;
limit_req zone=nsvk13 burst=10 nodealy;
try_files $uri $uri/ /index.php?$args;
}
Возвращаем 429 слишком дохуя запросов, вместо станадртного 502.
Бездумно это настраивать не советую, могут пострадать обычные пользователи, а вот если вдумчиво сделать — спасёшь свою боевую кобылу от школоло-хакеров.