LINUX.ORG.RU
решено ФорумAdmin

Вопрос по конфигу nginx (ratelimit)

 


0

2

Коллеги, добрый день!
Нужна помощь по конфигу nginx’а.

Задумка следущая: «всё то, что идёт в апстрим (не статика), лимитируется 1000 запросами в минуту на уникальный IP адрес, остальные запросы уходят в статус 556»

limit_req_zone $binary_remote_addr zone=main:30m rate=1000r/m;

location / {
    try_files $uri @upstream;
}
    
location @upstream {
    limit_req zone=main;
    limit_req_status 556;
    ...
}

Проблема следущая: рандомные запросы бодро улетают в 556, при этом всего от IP-адреса, который улетел в 556, 36 запросов ЗА СУТКИ (!):

{"remote_addr":"51.79.xxx.xx","remote_user":"-","time_local":"21/May/2025:08:09:50 +0000","host":"host.name","request":"GET / HTTP/2.0","status":"556","body_bytes_sent":"0","http_referer":"-","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36","request_time":"0.000"}
root@www7:~# grep 51.79.xxx.xx /var/log/nginx/host.name.access.log|wc -l
36

ЧЯДНТ?


update: подсказали про опцию burst, будем посмотреть.



Последнее исправление: ann_lortemp2 (всего исправлений: 1)

http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1000r/m;

# ... остальные настройки http
}


server {
listen 80;
server_name example.com;

location / {
# Статика (картинки, CSS, JS) — без лимитов
location ~* \.(jpg|jpeg|png|gif|css|js|ico)$ {
expires 30d;
access_log off;
try_files $uri $uri/ =404;
}

# Всё остальное (апи, динамические запросы) — лимит 1000/мин
location / {
limit_req zone=api_limit burst=100 nodelay;
limit_req_status 556; # Кастомный статус при превышении

proxy_pass http://backend; # Или fastcgi_pass для PHP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}

kto_tama ★★★★★
()

Этому адресу могло не повезти попасть в тот же счётчик, что и какому-то флудеру (ты выделил на счётчики 30 мегабайт, а айпи адресов всего 4 миллиарда). Общую картину смотрел (сколько запросов отклонено, сколько пропущено лимитом) или только один рандомный запрос проверил? И сделай для статики и не-статики отдельные логи, чтобы удобнее.

firkax ★★★★★
()
Ответ на: комментарий от firkax

IPv4 адрес 32-битный, то есть в счётчик влезет 7500000 адресов.
самый большой L7 (http) DDoS, который прилетал – около 100к уников. так что, вряд ли в этом дело.

подсказали про burst мне верно – если указан лимит 1000r/m, nginx это трактует как «не более одного запроса в 6 мсек», и если прилетело два прям таки единовременных запроса по какой-то причине, клиент улетит в лимит.
именно для этого нужен параметр burst (я установил его в значение 10) – в таком случае, при менее чем 10 одновременных запросах, сервер просто подождёт 6 мсек прежде чем принять соединение, а не выкинет ошибку сразу.

ann_lortemp2
() автор топика
Ответ на: комментарий от ann_lortemp2

32-битность адреса тут ни при чём, важно какая битность у счётчика (но вполне возможно что она тоже 32-битная, по совпадению - какой-нить int или float).

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

Но да, видимо дело в burst.

firkax ★★★★★
()