Изоляция служб systemd: песочница для своих сервисов

Если взломать службу, нарушитель получает права её пользователя и доступ ко всему, что она видит: домашние каталоги, чужие временные файлы, запись в систему, возможность поднимать сеть и грузить модули ядра. systemd умеет ограничить всё это несколькими строками в файле службы, без контейнеров и без установки дополнительных программ. Ниже набор директив, как их включать постепенно, как оценить результат командой systemd-analyze security и как не сломать службу.
Статья опирается на логику направления «Безопасность конечных устройств» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверки выполнены на Debian 12 с systemd 252. Для вашей версии список директив может отличаться: смотрите man systemd.exec. Парная статья про базовую настройку серверов: hardening Linux.
Что должно получиться
| Уровень | Что это значит на практике |
|---|---|
| 2. Гигиенический | Есть эталонная конфигурация и проверка отклонений; службы работают с минимальными правами |
Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.
Как работают ограничения
Директивы раздела [Service] включают для процесса службы механизмы ядра: пространства имён монтирования, ограничение возможностей, фильтр системных вызовов. Служба видит урезанную систему: например, файловую систему только для чтения, отдельный каталог /tmp и пустой /root. Проверка на живой системе (одноразовые запуски systemd-run с теми же свойствами):
| Директива | Проверка | Результат |
|---|---|---|
| без ограничений | запись в /etc |
запись удалась |
ProtectSystem=strict |
запись в /etc |
Read-only file system |
ProtectHome=yes |
просмотр /root |
каталог пуст для службы |
PrivateTmp=yes |
файл, созданный в /tmp службой |
виден службе, на хосте отсутствует |
NoNewPrivileges=yes, CapabilityBoundingSet= |
чтение /proc/self/status |
NoNewPrivs: 1, CapEff: 0000000000000000 |
PrivateNetwork=yes |
список сетевых интерфейсов | только lo |
SystemCallFilter=@system-service и ~@privileged |
обычная команда | выполняется |
Пример проверки одной директивы без изменения служб: sudo systemd-run --wait --pipe -p ProtectSystem=strict /bin/sh -c 'touch /etc/test'. Команда запускает временную службу и сообщает о результате; ничего не меняется в системе.
Оценка: systemd-analyze security
Команда systemd-analyze security ИМЯ.service оценивает службу по шкале от 0 (безопасно) до 10 (небезопасно) и перечисляет, какие директивы не включены. На тестовой службе (sleep 300) без ограничений итоговая оценка была 9.6 (UNSAFE), после включения набора ниже стала 1.4 (OK). Для реальных служб значения будут выше: многим нужны запись в определённые каталоги, сеть, работа с файлами. Цель не ноль, а осознанный минимум: каждая оставленная «дыра» должна иметь причину.
Файл службы
Пример /etc/systemd/system/myservice.service. Команду запуска и каталоги замените своими.
# /etc/systemd/system/myservice.service: пример изолированной службы (подставьте свою команду и пути)
[Unit]
Description=Пример изолированной службы
After=network.target
[Service]
ExecStart=/usr/local/bin/myservice --config /etc/myservice/config.yml
Restart=on-failure
# --- пользователь без прав и без домашнего каталога
DynamicUser=yes
StateDirectory=myservice
ConfigurationDirectory=myservice
# --- файловая система только для чтения, кроме StateDirectory
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
# --- ядро и системные интерфейсы
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
# --- ограничения возможностей
CapabilityBoundingSet=
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
UMask=0077
[Install]
WantedBy=multi-user.target
| Директива | Что делает и на что влияет |
|---|---|
DynamicUser=yes |
Создаёт временного пользователя для службы без прав и входа; несовместима со службами, которым нужен постоянный владелец файлов вне каталогов состояния (используйте StateDirectory) |
StateDirectory, ConfigurationDirectory |
Создают каталоги /var/lib/ИМЯ (записываемый) и /etc/ИМЯ (только чтение) с правильным владельцем |
ProtectSystem=strict |
Вся файловая система только для чтения, кроме каталогов состояния и явных исключений ReadWritePaths |
ProtectHome=yes |
Домашние каталоги недоступны |
PrivateTmp, PrivateDevices |
Отдельный /tmp; только минимальный набор устройств |
ProtectKernel*, ProtectControlGroups, ProtectClock, ProtectHostname |
Запрещают менять настройки ядра, загружать модули, читать журнал ядра, менять время и имя узла |
CapabilityBoundingSet= |
Убирает все привилегии Linux (если службе нужны отдельные, например CAP_NET_BIND_SERVICE для порта ниже 1024, перечислите их) |
RestrictNamespaces, RestrictRealtime, RestrictSUIDSGID, LockPersonality |
Закрывают редко нужные возможности, часто используемые при эксплуатации |
MemoryDenyWriteExecute=yes |
Запрещает память, одновременно доступную для записи и исполнения; ломает службы с JIT-компиляцией (Java, Node.js, часть интерпретаторов): для них директиву не включайте |
RestrictAddressFamilies |
Оставляет только нужные семейства сокетов |
SystemCallFilter |
Разрешает группу вызовов @system-service и запрещает привилегированные и управляющие ресурсами |
Включайте постепенно
- Начните с оценки.
systemd-analyze security имя.serviceна текущей службе: сохраните значение и список замечаний. - Добавляйте директивы по группам через drop-in файл, а не правкой основного файла:
sudo systemctl edit имя.serviceсоздаёт/etc/systemd/system/имя.service.d/override.conf, который легко удалить для отката. - После каждой группы перезапускайте службу и проверяйте работу:
sudo systemctl restart имя,systemctl status имя, журналjournalctl -u имя -n 50. - Начинайте с безопасных:
NoNewPrivileges,PrivateTmp,ProtectKernel*,ProtectControlGroups,RestrictRealtime,LockPersonality. ЗатемProtectSystem=strictиProtectHomeс явнымиReadWritePaths. В конце самые строгие:SystemCallFilter,MemoryDenyWriteExecute,CapabilityBoundingSet=. - Проверяйте файл:
systemd-analyze verify /etc/systemd/system/имя.service: выводит предупреждения о неизвестных директивах и отсутствующих файлах. - Зафиксируйте результат: новую оценку и причины оставленных замечаний.
Диагностика отказов
| Симптом | Причина и что делать |
|---|---|
Служба не стартует: Read-only file system |
Нужна запись в каталог. Добавьте ReadWritePaths=/путь или StateDirectory= |
Ошибка доступа к файлам в /home |
Включён ProtectHome. Перенесите данные или смягчите на read-only |
| Процесс убит сигналом SIGSYS | Фильтр системных вызовов. Найдите вызов в журнале (journalctl, поле SYSCALL при включённом аудите), разрешите нужную группу или временно уберите фильтр |
Служба падает с Cannot allocate memory или работает нестабильно |
MemoryDenyWriteExecute несовместим с JIT. Уберите директиву |
| Не открывается порт ниже 1024 | Нужно право CAP_NET_BIND_SERVICE: AmbientCapabilities=CAP_NET_BIND_SERVICE и CapabilityBoundingSet=CAP_NET_BIND_SERVICE |
| Не нашёл файл, который служба создаёт | Из-за PrivateTmp временные файлы видны только службе. Используйте каталог состояния для обмена |
Для отката удалите drop-in и выполните sudo systemctl daemon-reload && sudo systemctl restart имя. Изменения конфигурации служб выполняйте по процессу управления изменениями: карточка, проверка и откат.
Где применять в первую очередь
- Службы, доступные из сети: веб-серверы, прокси, почтовые и прикладные службы.
- Самописные демоны и сценарии, запускаемые от root.
- Службы, обрабатывающие чужие данные (загрузки, парсинг, конвертация файлов).
Многие пакеты дистрибутивов уже содержат ограничения в файлах служб: смотрите оценку systemd-analyze security по всем службам списком и начинайте с самых плохих.
Где это в модели зрелости
Материал относится к направлению «Безопасность конечных устройств» (материалы направления, карта зрелости). Уровень 2 требует эталонной конфигурации и проверки отклонений: оценка systemd-analyze security и drop-in файлы дают воспроизводимый и проверяемый эталон для служб.
Как проверить
- Для каждой сетевой службы есть оценка
systemd-analyze securityи записанные причины оставшихся замечаний. - Включены хотя бы
NoNewPrivileges,PrivateTmp,ProtectSystem,ProtectHome, ограничение возможностей. - Служба после ограничений работает под нагрузкой и после перезапуска, откат описан.
- Изменения оформлены drop-in файлами и учтены в карточках изменений.
Источники
- Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
- Руководство systemd:
man systemd.exec(директивы песочницы),man systemd-analyze,man systemd-run; сайт проекта: systemd.io. - CIS Benchmarks для вашего дистрибутива: cisecurity.org. Международная практика, не российский норматив.






















