A Review for "Selinux System Administration" by Sven Vermeulen, Russian Version

1. Введение

Что я могу, собственно, написать про книгу Свена Вермёлена "Системное Администрирование SELinux"?

Я не могу написать тщательного обзора, потому что я не прочитал сию книгу от корки до корки.

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

Я не могу написать даже внятного хауту "как использовать SELinux, чтобы обезопасить собственный сервер", потому что во-первых, это слишком уж сильно зависит от того, как ваш сервер устроен, и во-вторых, потому что в книге недостаточно для этого информации.

О чём же вообще эта книга?

В последний раз подобные трудности в написании обзора на книгу возникли у меня года три назад, когда я пытался написать ревью на INCOSE Systems Engineer Handbook.

С одной стороны, книга, вроде как, не содержит лажи, включает всё нужное, но при этом очень трудно рассказать "о чём вообще она".

Однако, в данном случае, как кажется, проблема состоит не в книге как таковой, а в материале.

SELinux – сложная штука. Причём, сложная именно в смысле изощрённости, объёмности, а не в смысле алгоритмической трудности. У неё крайне много деталей и странностей, которые были добавленны в неё разработчиками за много лет существования самой сущности. Часть этих сложностей была добавлена для того, чтобы скомпенсировать недостатки базовой модели, часть для того, чтобы синхронизировать модель с другими подсистемами Linux-системы, а часть – просто изначально неудачный дизайн.

В каком-то смысле, этот текст – не столько обзор на книгу, сколько моя попытка изложить "количество SELinux, достаточное для того, чтоб не недоумевать что ничего не работает", а не попытка по-настоящему оценить качество книги как мануала.

2. Что такое SELinux?

Большинство мануалов по SELinux начинаются с того, что рассказывают, что SELinux – это "модуль безопасности" в ядре Linux. В данном случае слово "модуль" не стоит понимать как "загружаемый в ядро объектный файл", а как "код, реализующий некоторый интерфейс, взаимозаменяемый с другим кодом". Это будет в некотором смысле правдой, потому что кроме SELinux существуют также и другие модули безопасности, например, AppArmor.

С другой стороны, ядерный код реализует SELinux не полностью, требуется ещё поддержка со стороны пользовательского кода. Более того, кроме очевидного интерфейса для настройки SELinux через расширения GNU Coreutils, существует ещё поддержка SELinux в PAM, systemd, dbus и ipsec.

Вот это да! Да что же это за монстр-то такой получается?

Однако, так и есть, SELinux пронизывает всю систему насквозь, ведь, кажется, без этого невозможно построить никакой по-настоящему всеобъемлющей системы безопасности?

Так что же это всё-таки такое?

Грубо говоря, это система спецификации "кому что разрешено", на очень детальном и подробном языке описания.

Тоже непонятно звучит, так ведь?

Грубо говоря, в ядре Linux есть некоторое "узкое место", на котором "кто-то", помеченный некоторыми метками, делает "что-то" над "чем-то", также помеченным метками. Далее ядро решает, следует ли разрешить, или запретить данную операцию.

Звучит крайне абстрактно?

Приведём пример.

"Кто" – это, в подавляющем большинстве случаев "процесс". И тут тоже возникает тонкость, потому что зачастую хочется разделять системные процессы и пользовательские процессы, хотя фундаментально между ними нет никакой разницы, ну программы и программы. Вот тут, например, может как раз и возникнуть "метка процесса" "пользовательский" или "системный".

В итоге разработчики SELinux писали-писали, да в итоге добавили не просто одну метку, а целых три – "пользователь", "роль", и "метка процесса". Совершенно не следует думать, что значения этих меток жёстко определены, и что пользователь и в самом деле соответствует системному пользователю, а метка процесса соответствует системному сервису, хотя в RedHat как раз примерно так и предусмотренно.

Типичный "объект" – это файл. У него тоже может быть три метки, однако, в случае файлов их значение ещё более туманно. Зачастую используется только третья метка "метка объекта". Для файлов, метки хранятся в "расширенных атрибутах" системы… но не совсем.

К сожалению, это "не совсем" пронизывает всю SELinux-подсистему сверху донизу. На самом деле, метки хранятся в специальном подкаталоге каталога /etc/selinux, и существует специальная команда restorecon, предназначенная разложить эти метки по расширенным атрибутам.

Зачем так нужно? Ну, видимо, для скорости? И для того, чтобы пользователю можно было разрешить менять метки файлов, не разрешая писать в каталог внутри /etc? Другими объектами может являться … что угодно! Например, порты tcp-ip, или пакеты ipsec, или сервисы dbus. В последнем случае верификацией операций вообще будет заниматься не ядро, а специальная библиотека.

Тем не менее, и ядро, и специальная библиотека как-то должны понимать, что и когда разрешать. (В SELinux по-умолчанию всё запрещено, поэтому налажать, и запретить самому себе администрировать систему крайне легко.) Для этого существует целый каталог /etc/selinux, в котором крайне подробно, с множеством мелких подробностей, шаг за шагом, файл за файлом, операция за операцией, пользователь за пользователем, некоторый "автор политики" должен описать правильное взаимодействие меток.

"Наивный юноша", когда я начинал читать книгу Свена Вермёлена, я думал, что после одной главы введения, я буду большую часть времени как раз и писать всякие "учебные политики".

Ничего подобного. Для написания политик у того же самого Свена есть вторая книга (SELinux Cookbook), практически полностью посвящённая написанию политик. Но даже в книге, которую я "якобы обозреваю", указано, что существует ажно целых три языка, на которых эти политики пишутся. Крайне трудоёмкий процесс, в которым единственным светлым пятном является то, что один из этих языков похож немного на Lisp.

В реальности эти политики никто не пишет сам, за редчайшими исключениями. Большая часть политик появляется в системе двумя путями – либо инженеры RedHat уже написали их за вас, просто устанавливаете пакет (причём просто так посмотреть политику, прочитав код нельзя! политики поставляются в двоичных файлах!), либо вы используете магическую команду audit2allow, которая сгенерит политику, основанную на недавних запретах, для вас. Эта политика будет плоха и неэффективна, но по райней мере вы сможете заставить нужный вам процесс работать "прямо сейчас".

Вообще говоря, существуют команды seinfo и sesearch, которые позволяют проверить, какие именно правила существуют в политиках, загруженных сейчас, но, стоит повторить, отлаживать политики selinux – крайне нетривиальная задача.

3. Настройка SELinux

Итак, если большая часть системных администраторов политики не пишет, в книге про написание политик единственная глава, то о чём же вообще эта книга?

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

Например, есть такая вещь как selinux boolean. Это (определяемые в политиках) переменные, в зависимости от которых политики могут вести себя по-разному. Зачем они вообще нужны? Почему нельзя просто написать другую политику? Ну, видимо, как раз потому, что политика по-умолчанию поставляется в двоичном виде и недоступна для редактирования обычному администратору.

Также в книге рассказывается, например, как сделать так, чтобы у UNIX-пользователя был правильный SELinux-пользователь при запуске процесса, и да, к сожалению, это требуется делать вручную.

Рассказывается, как включить или отключить SELinux целиком, или включить его в permissive режиме, когда нарушения политик только учитываются, но не пресекаются.

Довольно хорошо изложена тема файловых контекстов, с командами matchpathcon, chcon, runcon, позволяющими проверять, какими метками должен обладать какой объект.

Также вкратце изложено взаимодействие SELinux с некоторыми подсистемами Linux, которые помогуют устанавливать правильные контексты на объекты, до которых ядро не может "дотянуться", такими как systemd, dbus, PAM.

Целая глава посвящена взаимодействию SELinux с Docker и libvirt. Честно говоря, на первый взгляд, это кажется излишним, потому что для того Docker и libvirt и придумывались, в частности, чтобы не заниматься излишней детализацией безопасности, положившись на изоляцию, однако, полезно знать, что таковая поддержка существует.

О чём в книге не сказано почти ничего, это о том, как работать с SELinux на Android. Android – это второй по очевидности кейс применения SELinux, а по числу устройств, быть может, и первый. Тем не менее, про него в книге сказано очень мало, и эти знания надо добирать из каких-то других источников.

В итоге, по моим подсчётам получается, что для того, чтобы хорошо понимать SELinux, нужно прочитать как минимум 5 книг:

  1. SELinux System Administration by Sven Vermeulen
  2. SELinux Cookbook by Sven Vermeulen
  3. SELinux Notebook by SELinux community
  4. RedHat SELinux Administration Guide
  5. Android SELinux Documentation

Много? Много.

И в завершение этого обзора-необзора, могу сказать, что какого-нибудь способа начать использовать SELinux "малой кровью" я не нашёл. То есть, вероятно, в качестве "детского примера" можно заизолировать nginx, установленный на стандартном RedHat, с помощью стандартной политики, и получить таким образом галочку в резюме, однако, я лично не стал бы считать это настоящим достижением.