[#] Изолируем демоны с systemd или «вам не нужен Docker для этого!»
habrabot(difrex,1) — All
2015-11-05 19:30:03


В последнее время я вижу, как довольно большое количество людей применяет контейнерную виртуализацию только для того, чтобы запереть потенциально небезопасное приложение внутри контейнера. Как правило, используют для этого Docker из-за его распространенности, и не знают ничего лучше. Действительно, многие демоны первоначально запускаются от имени root, а далее либо понижают свои привилегии, либо master-процесс порождает обрабатывающие процессы с пониженными привилегиями. А есть и такие, которые работают исключительно от root. Если в демоне обнаружат уязвимость, которая позволяет получить доступ с максимальными привилегиями, будет не очень приятно обнаружить злоумышленников, уже успевших скачать все данные и оставить вирусов. Контейнеризация, предоставляемая Docker и другим подобным ПО, действительно спасает от этой проблемы, но также и привносит новые: необходимо создавать контейнер для каждого демона, заботиться о сохранности измененных файлов, обновлять базовый образ, да и сами контейнеры часто основаны на разных ОС, которые необходимо хранить на диске, хотя они вам, в общем-то, и не особо нужны. Что делать, если вам не нужны контейнеры как таковые, в Docker Hub приложение собрано не так, как нужно вам, да и версия устарела, SELinux и AppArmor кажутся вам слишком сложными, а вам бы хотелось запускать его в вашем окружении, но используя такую же изоляцию, которую использует Docker?

### Capabilities

В чем отличие обычного пользователя от root? Почему root может управлять сетью, загружать модули ядра, монтировать файловые системы, убивать процессы любых пользователей, а обычный пользователь лишен таких возможностей? Все дело в [capabilities][1] — средстве для управления привилегиями. Все эти привилегии даются пользователю с UID 0 (т.е. root) по умолчанию, а у обычного пользователя нет ни одного из них. Привилегии можно как дать, так и отобрать. Так, например, привычная команда ping требует создания RAW-сокета, что невозможно сделать от имени обычного пользователя. Исторически, на ping ставили SUID-флаг, который просто запускал программу от имени суперпользователя, но сейчас все современные дистрибутивы выставляют CAP\_NET\_RAW capability, которая позволяет запускать ping из-под любого аккаунта. Получить список установленных capabilities файла можно командой `getcap` из состава libcap.

% getcap $(which ping)
/usr/bin/ping = cap_net_raw+ep


Флаг **p** здесь означает _permitted_, т.е. у приложения есть возможность использовать заданную capability, **e** значит _effective_ — приложение будет ее использовать, и есть еще флаг **i** — _inheritable_, что дает возможность сохранять список capabilities при вызове функции `execve()`. Capabilities можно задать как на уровне ФС, так и просто у отдельного потока программы. Получить capability, которая не была доступна с момента запуска, нельзя, т.е. привилегии можно только понижать, но не повышать. Также существуют биты безопасности (Secure Bits), их три: KEEP\_CAPS позволяет сохранить capability при вызове setuid, NO\_SETUID\_FIXUP отключает перенастройку capability при вызове setuid, и NOROOT запрещает выдачу дополнительных привилегий при запуске suid-программ. [Читать дальше →][2]

[1]: http://man7.org/linux/man-pages/man7/capabilities.7.html
[2]: http://habrahabr.ru/post/270165/#habracut