``` systemd-analyze security ``` ![Image](https://www.linuxjournal.com/sites/default/files/u%5Buid%5D/systemd-analyze.jpg) `systemd-analyze security` — один из тех инструментов, которые часто пугают с первого взгляда. Достаточно запустить его на живом сервере или Kubernetes-ноде, увидеть десятки строк с пометкой `UNSAFE`, и возникает ощущение, что система находится в катастрофически небезопасном состоянии. На практике это почти всегда неверная интерпретация. Этот инструмент не пытается ответить на вопрос «уязвим ли сервис». Он отвечает на совершенно другой, гораздо более инженерный вопрос: **какие системные привилегии доступны процессу и насколько велик потенциальный ущерб, если этот процесс будет скомпрометирован**. И именно в этом контексте `systemd-analyze security` становится крайне полезным для production-среды. --- ### Что именно анализирует `systemd-analyze security` `systemd-analyze security` выполняет статический анализ unit-файла systemd и смотрит, какие механизмы изоляции и hardening включены или отсутствуют. Его интересуют такие вещи, как возможность получения новых привилегий, доступ к устройствам, работа с namespaces, запись в системные директории, загрузка модулей ядра, создание исполняемой памяти и так далее. Важно понимать границы инструмента. Он не анализирует код сервиса, не ищет CVE, не сканирует сеть и не учитывает политики SELinux или AppArmor. Это не security scanner и не pentest. Это **линтер конфигурации systemd**, который показывает, насколько «широкими» остаются права процесса с точки зрения ядра. --- ### Почему почти все system-сервисы выглядят как `UNSAFE` Если выполнить `systemd-analyze security` без аргументов, то в выводе почти наверняка окажется, что `systemd-udevd`, `dbus`, `polkit`, `networkd`, `sshd`, `k3s`, `containerd` и многие другие сервисы имеют уровень `UNSAFE` с показателями 8–10. Это не баг и не признак плохо защищённой системы. Причина проста: это **базовые системные демоны**, без которых Linux просто не работает. Они обязаны иметь доступ к устройствам, к netlink, к cgroups, к `/proc` и `/sys`, к управлению пользователями, терминалами и сетевым стеком. Попытка «зажать» такие сервисы жёсткими sandbox-настройками почти гарантированно приведёт к неработоспособной системе. В контексте `systemd-analyze security` слово `UNSAFE` означает лишь то, что systemd **почти не ограничивает** этот сервис. Оно не означает, что сервис уязвим, дыряв или небезопасен по своей природе. --- ### Как правильно читать вывод на примере `ssh.service` Рассмотрим типичный вывод для `ssh.service`. В нём можно увидеть сообщения о том, что сервис запускается от root, может приобретать новые привилегии, создавать namespaces, посылать сигналы другим процессам и так далее. Всё это выглядит пугающе, если читать строки буквально, но для SSH это абсолютно ожидаемое поведение. SSH-демон обязан быть root, потому что он открывает привилегированный порт, работает с PAM, переключает UID пользователей, управляет TTY и взаимодействует с systemd-logind. Ограничить его capability-набором или запретить privilege escalation — значит сломать саму модель работы SSH. В этом случае высокий exposure — не проблема, а осознанный архитектурный выбор. --- ### В чём реальная ценность инструмента Настоящая польза `systemd-analyze security` проявляется не при анализе системных демонов, а при проверке **кастомных сервисов**. Если самописное приложение, агент мониторинга, CI-runner или вспомогательный демон внезапно имеет уровень `8.9 UNSAFE`, это почти всегда означает, что сервис запущен с избыточными правами без реальной необходимости. В таких случаях инструмент позволяет очень быстро ответить на вопрос: «А зачем этому процессу вообще всё это разрешено?» И чаще всего ответ — «ни за чем». --- ## Практический пример: как читать `systemd-analyze security` и реально улучшать сервис ``` systemd-analyze security ssh.service ``` ![[Pasted image 20251228105153.png]] ### Исходная ситуация Допустим, на сервере есть кастомный сервис `my-agent.service`. Это может быть агент мониторинга, интеграция с внешним API или любой вспомогательный демон, который не является частью ядра системы. Unit-файл выглядит минималистично: ```ini [Unit] Description=My custom agent [Service] ExecStart=/opt/my-agent/agent Restart=always [Install] WantedBy=multi-user.target ``` Сервис работает, проблем нет — но вопрос безопасности никто не задавал. --- ### Первый запуск `systemd-analyze security` Проверяем сервис: ```bash systemd-analyze security my-agent.service ``` Типичный результат: ``` ✗ NoNewPrivileges Service may acquire new privileges ✗ ProtectSystem Service has full access to system ✗ ProtectHome Service has full access to home directories ✗ PrivateDevices Service has access to hardware devices ✗ RestrictNamespaces Service may create namespaces ✗ CapabilityBoundingSet Service runs with full capabilities → Overall exposure level: 9.4 UNSAFE ``` На этом этапе **важно не паниковать**. Инструмент не говорит, что сервис уязвим. Он говорит следующее: > если процесс будет скомпрометирован, > он сможет делать почти всё, что может root на хосте. Для кастомного агента это почти всегда избыточно. --- ### Интерпретация результата Если задать себе простой вопрос — _что реально нужно этому сервису?_ — ответ обычно выглядит так: Он не должен: - менять системные файлы - видеть `/home` - работать с устройствами - создавать namespaces - эскалировать привилегии Именно это и показывает высокий exposure. --- ### Минимальный hardening (без фанатизма) Добавим базовые ограничения, не ломая сервис: ```ini [Service] ExecStart=/opt/my-agent/agent Restart=always NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true PrivateDevices=true RestrictNamespaces=true MemoryDenyWriteExecute=true CapabilityBoundingSet= ``` Здесь нет «экзотики». Это стандартный набор, который подходит для **большинства user-space сервисов**. --- ### Повторный анализ Перезапускаем сервис и снова запускаем анализ: ```bash systemctl daemon-reexec systemctl restart my-agent.service systemd-analyze security my-agent.service ``` Теперь вывод выглядит примерно так: ``` ✓ NoNewPrivileges ✓ ProtectSystem ✓ ProtectHome ✓ PrivateDevices ✓ RestrictNamespaces ✓ CapabilityBoundingSet → Overall exposure level: 1.6 OK ``` Это означает, что: - сервис по-прежнему работает - код не менялся - но потенциальный ущерб при взломе стал **на порядок меньше** --- ### Почему это правильный результат Важно подчеркнуть: мы **не пытались сделать сервис “идеально безопасным”**. Мы сделали его: - предсказуемым - ограниченным - соответствующим принципу least privilege Если завтра в `my-agent` появится RCE, злоумышленник: - не сможет читать `/etc` - не сможет лезть в `/proc` и `/sys` - не сможет создавать namespaces - не сможет загрузить kernel-модули - не сможет эскалировать привилегии И это именно та цель, ради которой существует `systemd-analyze security`. --- ### Контраст: почему так нельзя делать с `ssh.service` Если проделать тот же путь с `ssh.service`, станет очевидно, что большинство этих опций просто несовместимы с его логикой. SSH обязан: - работать от root - использовать PAM - менять UID - управлять TTY - взаимодействовать с другими systemd-сервисами Поэтому высокий exposure для `ssh.service` — это **архитектурная необходимость**, а для `my-agent.service` — **лишняя неосторожность**. --- ### Главный вывод из примера Этот пример показывает ключевую идею: `systemd-analyze security` не предназначен для того, чтобы «чинить systemd». Он предназначен для того, чтобы **находить лишние привилегии там, где они не нужны**, и спокойно их убирать. Если после анализа кастомного сервиса ты видишь `UNSAFE` — это почти всегда приглашение задать вопрос: _«А зачем ему вообще всё это разрешено?»_ И чаще всего ответ — _«незачем»_.