Re: Как лучше всего сделать защиту от denial of service при исчерпании свободного места на диске большими по объему лог-файлами nginx?

Gena Makhomed gmm на csdoc.com
Вт Фев 13 02:21:20 UTC 2024


On 12.02.2024 11:53, Evgeniy Berdnikov wrote:

>> Ротация логов делается с помощью программы logrotate, которая делает
>> ротацию только по времени и никак не смотрит на количество свободного
>> места на диске и на размер лог-файла.
> 
>   Насчёт размера файла утверждение неверное: в конфиге logrotate можно
>   указать директиву "size", которая будет означать предельный размер
>   лог-файла, по достижении которого запускается ротация. Другое дело, что
>   риалтаймовского триггера на достижение предельного размера файла нет.
>   А он мог бы быть в nginx-е, среди опций access_log и error_log.

Я немного не точно выразился. Интересует запуск ротации логов
не по размеру одного какого-то лог-файла, а по суммарному
размеру всего каталога /var/log/nginx/

Потому что даже если выставить лимит size 1G на один лог-файл -
не всегда понятно, сколько именно места на диске будет занимать
каталог /var/log/nginx/ rotate 52 задает количество ротаций
только одного одного файла. А размер каталога /var/log/nginx/
зависит от того, сколько там будет лог-файлов - всего два,
access.log и error.log или несколько сотен, или несколько тысяч.

Вообще, в идеале - хотелось бы иметь возможность и значение rotate
не статически задавать в конфиге, а делать динамически вычисляемым,
по определенной формуле, в зависимости от размера каталога
/var/log/nginx/ и/или количества свободного места на диске
и других параметров.

Наверное, самый оптимальный вариант решения всех этих проблем
- это сделать демона logrotated, который будет следить
за количеством занятого и/или свободного места на разделе /var
и в результате - если необходимо делать принудительную
ротацию логов, - будет сам генерировать временный файл
конфигурации, например, /run/logrotated/nginx-logrotate.conf
и потом уже запускать утилиту /usr/sbin/logrotate
для выполнения работы по ротации логов, примерно так:

/usr/sbin/logrotate --force /run/logrotated/nginx-logrotate.conf

то есть, когда DDoS-атак нет - тогда демон logrotated просто висит
в фоне, время от времени проверяя состояние и ничего не делает,
потому что ни один триггер не срабатывает. И тогда всю работу
по ротации логов nginx делает сама программа logrotate,
запускаемая по крону раз в сутки. А когда происходит DDoS-атака,
тогда logrotated обнаруживает чрезмерное использование места
на диске логами nginx и начинает делать принудительную ротацию
логов, не допуская исчерпания свободного места на диске
DDoS-атакой и наступления ситуации отказа в обслуживании.

>> Это может быть полезно в случае DDoS-атак, чтобы не не было
>> таких неожиданных ситуаций, что место на сервере внезапно закончилось

>   Для DoS-атак как раз и полезно разделение обязанностей между рабочим
>   процессом сервиса и процессом-писателем логов.

Та система, которая есть сейчас - она близка к идеальной,
когда каждая утилита делает только свою работу, но делает
ее очень хорошо - nginx только обрабатывает запосы клиентов,
а logrotate - занимается только задачей ротации логов.

>   Я уже упоминал здесь
>   сквидовский logfile-daemon, это один из вариантов, как можно обезопасить
>   рабочий процесс от ступора.

У nginx нет ступора рабочих процессов том случае, когда закончилось 
свободное место на диске. Он даже дополнительно делает паузу в одну
секунду, чтобы на FreeBSD все не тормозило, когда нет свободного
места на диске. То есть, со стороны nginx - вообще никаких проблем.

https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_log_module.c#L288

Проблемы начинаются у остального софта, например, MySQL прекращает 
нормально работать, потому что ничего не может записать в базу данных,
когда на диске 0 байт свободного места и php-fpm начинает возвращать
5xx статус - то есть, в результате и получается denial of service.

>   А костыли в виде логов в оперативной памяти, logrotate и питоновских
>   скриптов можно, конечно, нагородить. Но в современной ситуации, я думаю,
>   проще сделать триггер, который по обнаружении катастрофической нехватки
>   места для логов просто отключит логгирование в nginx-e.

Когда свободного места на диске нет - то nginx туда, естественно,
ничего и не пишет, когда свободное место появляется - процесс записи
логов автоматически продолжается, тут ничего настраивать не нужно.

Единственная проблема которая есть в такой сиутации - перестают работать 
POST-запросы, если в каталоге client_body_temp_path ноль байт свободного
места, но все остальные типы запросов в такой ситуации nginx продолжает
нормально обрабатывать. И теряется возможность записи информации в логи.

Все остальное - вроде бы работает нормально, когда 0 байт
свободного места на диске - но я очень детально это не проверял.

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

>   Работоспособность web-сервиса, как правило, намного важнее логгирования.

Тогда почему в операционной системе logrotate запускается по крону
только раз в сутки и там нет вообще никакой защиты на этом уровне
от исчерпания свободного места на диске? Это просто никому не нужно
или же причина в том, что неправильно чтобы система автоматически
поддерживала себя в рабочем состоянии и не переходила в состояние
denial of service когда на какой-то сайт приходит DDoS-атака?

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

-- 
Best regards,
  Gena



Подробная информация о списке рассылки nginx-ru