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