Назад | Перейти на главную страницу

Nginx: ограничение запроса на основе кода состояния ответа

Я пытаюсь ограничить запросы с помощью nginx на основе кода состояния ответа. Я хотел бы замедлить запросы со слишком большим количеством ответов 4xx или 5xx. У меня есть этот блок кода в моем файле конфигурации:

map $status $bad_guy {
    ~^[23]  "";
    default $binary_remote_addr;
}
limit_req_zone "$bad_guy" zone=badguy:10m rate=1r/s;

server {
    limit_req zone=badguy burst=20;

Похоже, что приведенная выше конфигурация блокирует все IP-адреса, отправляющие более 1 rps, включая те, которые имеют только 200 ответов OK.

Не могли бы вы мне помочь, пожалуйста? Почему вышеуказанная конфигурация не работает? Должен ли я использовать что-то еще (может быть, openresty?) Для этого? Спасибо.

Это довольно сложно, потому что переменная $ status пуста при объявлении limit_req_zone. Статус $ становится известен только после того, как nginx обработал запрос. Например, после директивы proxy_pass.

Самое близкое, что я мог сделать для ограничения скорости по статусу, - это сделать следующее:

...
...
...
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
...
...
...
server {
    location /mylocation {
        proxy_intercept_errors on;
        proxy_pass http://example.org;
        error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 426 428 429 431 451 500 501 502 503 504 505 506 507 508 510 511 @custom_error;
    }

    location @custom_error {
        limit_req zone=api burst=5 nodelay;
        return <some_error_code>;
    }

}
...

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