systemd. Часть 3. Безопасность и ограничение использования ресурсов

В этой заметке описываются средства и директивы, предоставляемые systemd, предназначенные для снижения риска повреждения системы со стороны сервисов и ограничения потребления системных ресурсов для сервисов.

1. Безопасность

1.1. Безопасность. chroot

Для запуска сервиса внутри chroot нужно вписать в раздел Service следующие параметры:

Даже в случае запуска сервиса в chroot, сервисом можно продолжать управлять с помощью команды systemctl.

Стоит также помнить, что chroot не является наилучшим средством обеспечения безопасности, потому-что процесс, запущенный в chroot по прежнему имеет доступ ко всем идентификаторам процессов и имеет доступ ко всем системным вызовам системы, поэтому имеет возможность управлять процессами и даже может выйти за пределы chroot.

1.2. Безопасность. Пространства имён

Достойной альтернативой chroot может служить FSNS (Filesystem Namespace) - пространство имён файловых систем. С помощью FSNS можно сделать полностью недоступными или доступными только для чтения части файловой системы. Для этого можно воспользоваться следующими параметрами, которые нужно внести в раздел Service:

ПРЕДУПРЕЖДЕНИЕ: действие двух вышеописанных директив не распространяется на точки монтирования, попавшие внутрь указанных каталогов. Чтобы ограничить доступ сервиса к таким точкам монтирования, нужно задать дополнительный параметр с указанием точки монтирования.

Если сервису для выполнения его обязанностей не нужен доступ в сеть, можно запустить его в своей собственной изолированной сети, состоящей из одного интерфейса обратной петли, который будет изолирован от системного интерфейса обратной петли. Для этого достаточно указать в разделе Service всего один параметр:

Если сервис не использует каталог /tmp для создания сокет-файлов, можно указать в разделе Service параметр, создающий для процесса изолированное пространство имён для каталога /tmp:

Кроме вышеописанных настроек, работающих внутри service-файлов, в составе systemd имеется утилита systemd-nspawn, создающая полностью изолированное пространство имён. В нём автоматически будут смонтированы файловые системы /proc и /sys, будет создан изолированный интерфейс обратной петли и отдельное пространство имён для идентификаторов процессов. Внутри такого пространства имён можно даже запустить процесс с идентификатором 1, что позволяет запускать внутри него полноценную операционную систему, основанную на ядре Linux.

Например, воспользовавшись всего тремя командами можно запустить Debian поверх Fedora:

# yum install debootstrap
# debootstrap --arch=amd64 unstable debian-tree/
# systemd-nspawn -D debian-tree/ /sbin/init

В последней команде нужно указать процесс, который будет запущен внутри изолированного пространства имён. Если указать процесс init, как в примере выше, внутри запустится полный комплект сервисов. По умолчанию запускается интерпретатор shell.

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

1.3. Безопасность. cgroups

Имеется возможность ограничить доступ сервиса к файлам устройств системы средствами cgroups. Для этого нужно указать параметр в разделе Service:

1.4. Безопасность. capabilities

Для задания списка доступных полномочий (capabilities) сервиса можно воспользоваться следующим параметром, который необходимо поместить в раздел Service:

Список активных полномочий процессов можно увидеть с помощью команды pscap из пакета libcap-ng-utils.

2. Ограничение использования ресурсов

2.1. Ограничение использования ресурсов. rlimit

Ещё одна функция, которой обладает systemd - это возможность настраивать ограничения на использование ресурсов. Можно настроить любое ограничение, описанное в setrlimit(2). Для установки ограничения RLIMIT_NPROC нужно указать в разделе Service параметр LimitNPROC, а названия других параметров строятся по такой же схеме - префикс RLIMIT_ заменяется на Limit.

Стоит отметить, что ограничения эффективны лишь в том случае, если процесс не имеет полномочия CAP_SYS_RESOURCE и не запущен от имени пользователя root.

2.2. Ограничение использования ресурсов. cgroups

systemd использует две группы возможностей, предоставляемых cgroups - это:

  1. группировка процессов для определения их принадлежности определённому сервису или сеансу пользователя,
  2. ограничения на использование ресурсов системы сервисами и сеансами пользователей.

Первая группа возможностей необходима для нормального функционирования systemd, без неё возможности systemd будут сильно ограничены. Без второй группы возможностей systemd прекрасно обходится и она не обязательна для использования. Именно её мы сейчас и рассмотрим.

В cgroups имеется три контроллера, ограничивающих использование системных ресурсов: cpu - ограничивает использование процессоров системы, memory - ограничивает использование оперативной памяти системы, blkio - ограничивает использование пропускной полосы к блочным устройствам (дискам). По умолчанию в systemd используется только первый контроллер, который делит процессорное время поровну между всеми сервисами. В отличие от systemd, классический SysV init делит процессорное время поровну между всеми процессами, работающими в системе, так что сервис, состоящий из большего количества процессов, получает и больше процессорного времени.

Для просмотра текущего использования ресурсов системы сервисами можно воспользоваться командой systemd-cgtop. Поскольку по умолчанию в systemd включен только контроллер cpu, то используется общий учёт использования памяти и пропускной полосы к блочным устройствам для всех сервисов. При указании ограничений по использованию памяти или пропускной полосы к блочным устройствам хотя-бы в одном из service-файлов, systemd автоматически начинает использовать этот контроллер. Включить же его принудительно можно с помощью директивы DefaultControllers в файле /etc/systemd/system.conf.

Стоит отметить, что ограничение ресурсов обходится не бесплатно и может сказаться на общей производительности системы. Особенно в этом замечен контроллер memory, однако в будущих версиях ядер Linux всё может стать лучше.

Рассмотрим ограничения, предоставляемые каждым из контроллеров:

2.2.1. Процессор

2.2.2. Память

Оба параметра поддерживают суффиксы K, M, G и T, обозначающие, соответственно, килобайты, мегабайты, гигабайты и терабайты (Будьте добры, дайте пару планочек по 4 терабайта. Благодарю Вас, Вы очень любезны).

2.2.3. Ввод-вывод

Абсолютные значения также поддерживают суффиксы K, M, G и T, обозначающие, соответственно, скорости обмена данными в килобайтах в секунду, мегабайтах секунду, гигабайтах в секунду и терабайтах в секунду (Отстой! Наш провайдер уже год петабайтные тарифы предоставляет).

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

Примеры использования:

BlockIOWeight=500
BlockIOWeight=/dev/disk/by-id/ata-SAMSUNG_MMCRE28G8MXP-0VBL1_DC06K01009SE009B5252 750
BlockIOWeight=/home/lennart 750
BlockIOReadBandwidth=/var/log 5M

2.2.4. Другие параметры cgroups

Существует также набор параметров, действующих на уровне процессов, но не использующих возможностей cgroups и потому не требующих много ресурсов для их применения IOSchedulingClass, IOSchedulingPriority, CPUSchedulingPolicy, CPUSchedulingPriority, CPUAffinity, LimitCPU.

Написать автору