ADG Оставить заявку
Блог Системное администрирование 4 мин чтения

CentOS 5 -> 6: SELinux как часть работы, а не помеха

Переводим файловые и веб-серверы с CentOS 5 на 6. Главный сюрприз - SELinux включён по умолчанию, и обойти его setenforce 0 уже не хочется.

Контекст момента

Линейка CentOS 6.x закрепляется как основная для production-серверов

Перевод клиентских серверов с CentOS 5 на 6 - задача, которую мы откладывали последние полгода. Не потому что страшно, а потому что «работает - не трогай» звучит убедительно, когда у клиента на сопровождении два десятка машин и нет окна для плановых простоев.

Но пятая ветка уже получает только критические патчи безопасности, и этот аргумент убедил нас запланировать миграцию.

Что изменилось между пятёркой и шестёркой

Разница не катастрофическая, но и не косметическая. Главные точки трения:

Init-система. CentOS 6 всё ещё использует SysV init с upstart поверх - не systemd, к которому все привыкли на Fedora. Rc-скрипты работают, большинство написанных под пятёрку стартапников заработали без правок. Один нюанс: upstart-задания в /etc/init/ имеют приоритет над традиционными скриптами в /etc/init.d/, и если в пакете есть оба - иногда получаешь неожиданное поведение.

Версии пакетов. PHP 5.3 вместо 5.2, Apache 2.2 та же, MySQL 5.1 та же. В целом мягко, но PHP 5.3 сломал несколько старых приложений по части deprecated-функций. ereg_* вместо preg_* - классика, всплыла у двух клиентских скриптов.

SELinux. Вот здесь всё по-настоящему.

SELinux: включён и злой

В пятёрке SELinux чаще был выключен или стоял в permissive. Именно потому что с ним лень было разбираться, а setenforce 0 решало проблему за три секунды. В CentOS 6 он включён в enforcing по умолчанию, и Red Hat явно дал понять что отключать его - плохая идея. Мы решили не спорить.

Первый же Apache с нестандартным DocumentRoot за пределами /var/www встал колом. 403 Forbidden, в логах ничего, nginx (который мы ставили реверс-прокси) ругался на upstream. Полчаса ушло на то чтобы вспомнить: SELinux не пускает httpd читать файлы без правильного контекста.

Диагностика строится на трёх командах:

  • ausearch -m avc -ts recent - смотрим последние denied в audit-логе
  • audit2why - человекочитаемое объяснение что именно заблокировано
  • audit2allow -a - генерирует черновик политики на основе того что было заблокировано

Для нашего случая с нестандартным DocumentRoot правильное решение - выставить нужный контекст на директорию:

semanage fcontext -a -t httpd_sys_content_t "/data/sites(/.*)?"
restorecon -Rv /data/sites

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

Боготворим audit2allow, но с осторожностью

audit2allow искушает: скармливаешь ему лог, он генерирует .te-файл политики, компилируешь, загружаешь - и всё работает. Проблема в том что сгенерированная политика может быть избыточно широкой. Мы натолкнулись на ситуацию, где автогенерированное правило давало httpd доступ к типу файлов, который ему видеть незачем. Пришлось ручками сужать.

Рабочий подход: audit2allow как отправная точка для понимания, не как готовое решение для прода.

Несколько практических моментов

Booleans делают жизнь проще. Для типовых сценариев в SELinux есть встроенные булевы переключатели. setsebool -P httpd_can_network_connect on - разрешает Apache коннектиться наружу (нужно для PHP-приложений, ходящих к API). getsebool -a | grep httpd показывает все доступные переключатели для httpd. Прежде чем писать кастомную политику - смотри список boolean, скорее всего нужное уже есть.

NFS и SELinux. На файловом сервере с NFS-экспортами пришлось повозиться с контекстами для nfs_t. Монтируемые клиентами директории требуют samba_share_t или явно разрешённых типов на клиентской стороне - зависит от того кто монтирует.

Логи - в /var/log/audit/audit.log. Если что-то не работает и непонятно почему - туда. Почти всегда SELinux denied там, если не в /var/log/messages.

Про upstart и сервисы

Несколько кастомных init-скриптов пятёрки переехали без правок. Один скрипт для самописного демона пришлось переписать под upstart - старый не стартовал нормально при перезагрузке из-за конфликта порядка зависимостей. Upstart-синтаксис немного непривычный после SysV, но проще чем кажется.

Итог на этой точке

Восемь серверов переведено, ещё шесть в очереди. Основной вывод: миграция с 5 на 6 технически некритична, если заложить время на SELinux. Не на его отключение - на понимание. audit.log + audit2why + нужные boolean - и большинство проблем решаются без написания кастомных политик.

setenforce 0 мы не трогали ни разу. И это приятно.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.