Настройка окружения SELinux на примере LAMP-сервера
Это третья статья из цикла
И сегодня она попала в поток «Администрирование». Сегодня мы не будем писать модули[1] или настраивать RBAC[2], а пойдем по пути наименьшего сопротивления и просто захарденим обычный LAMP-сервер при помощи готовой политики, включив необходимые настройки.
Если кто забыл, за аббривиатурой LAMP скрывается Linux, Apache, Mysql, PHP, т.е. это большая часть всех VDS[3], которые покупают люди для хранения своих личных блогов. Надеюсь, что этот поможет всем им стать немного безопаснее :)
Предположения
Итак, предполагаем, что:
Дистрибутив — CentOS 7 x64, пользователь — root
SELinux включен, загружена политика targeted
Режим SELinux — enforcing
Подготовка
Если LAMP у вас уже установлен и настроен — можете пропустить
Установим стандартный комплект софта для LAMP: [root@lamp ~]# yum install -y httpd mariadb-server php-fpm php-mysql
Минимально настроим софт:
И создадим простой тестовый файл с phpinfo(): [phpbb@lamp ~]$ mkdir www [phpbb@lamp ~]$ echo "<?php phpinfo(); ?>" > www/info.php
Перейдем по ссылке…
… и получим именно то, что получают все :)
Разбираемся с ошибками
В отличие от других мануалов, где следующим шагом идет «отключите SELinux», мы сейчас узнаем, почему так получилось и что можно сделать.
Для начала — установим консольные утилиты для управления политиками SELinux: [root@lamp ~]# yum install -y policycoreutils-python policycoreutils-newrole policycoreutils-restorecond setools-console
А потом — включим нужные нам модули ( командой semodule ): [root@lamp ~]# semodule -e apache [root@lamp ~]# semodule -e mysql
Давайте посмотрим, с какими именно проблемами столкнулся apache при открытии этой страницы?
audit2allow -lb -t httpd_t
#============= httpd_t ==============
#!!! This avc can be allowed using one of the these booleans:
# httpd_enable_homedirs, httpd_read_user_content, httpd_unified
allow httpd_t httpd_user_content_t:file getattr;
Все верно: папка www ( а так-же папки web и public_html ) внутри домашней директории пользователя автоматически получает тип httpd_user_content_t, что и указано в правилах:
sesearch -T -s user_t -c dir -d
…
type_transition user_t user_home_dir_t: dir httpd_user_content_t «public_html»;
type_transition user_t user_home_dir_t: dir httpd_user_content_t «www»;
type_transition user_t user_home_dir_t: dir httpd_user_content_t «web»;
…
Лечение указано в выводе audit2allow, установка переменных выполняется командой setsebool ( или semanage boolean ). [root@lamp httpd]# setsebool -P httpd_read_user_content=1
Обновляем страницу и получаем:
Смотрим логи:
/var/log/httpd/error_log
[Tue Feb 28 21:15:04.555595 2017] [proxy:error] [pid 21586] (13)Permission denied: AH00957: FCGI: attempt to connect to 127.0.0.1:9009 (*) failed
[Tue Feb 28 21:15:04.555892 2017] [proxy_fcgi:error] [pid 21586] [client 192.168.56.101:57974] AH01079: failed to make connection to backend: 127.0.0.1
Все ясно: httpd не может коннектиться куда попало, httpd может ходить только куда нужно. Это логично: если веб-сервер вдруг соединяется по ssh, то явно происходит что-то странное.
Давайте посмотрим, куда веб-серверу ходить можно?
sesearch -A -s httpd_t -c tcp_socket -p name_connect -d -C
В квадратных скобках указаны переменные, которые отвечают за работу этого правила.
Итого: нужно добавить порт 9009 в один из типов, к которым разрешен коннект, а затем установить переменную httpd_can_network_relay в 1.
Новый порт добавляется при помощи команды semanage port: [root@lamp httpd]# semanage port -a -t http_cache_port_t -p tcp 9009 [root@lamp httpd]# setsebool -P httpd_can_network_relay=1
Обновляем страницу и видим:
Что-то посложнее
Давайте теперь усложним задачу и поставим phpbb на этот хост.
Попробуем создать для себя базу: [phpbb@lamp www]$ mysql -uroot ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13)
Поищем, как разрешить пользователю соединяться с базой?
Не написав ни одной строчки кода, используя только знания из man-файлов и стандартную политику SELinux по-умолчанию, можно за 30 минут настроить безопасное окружения для стандартных сервисов. И это не только про LAMP: стандартная политика содержит 403 готовых модуля. Этого хватит для решения большинства задач, которые когда-либо встанут перед администратором. Не выключайте SELinux, не заставляйте Дэна плакать[5].
Бонус #1
Для тех, кто все это таки прочел — готовый образ из статьи.
Ссылка: ufile.io/5eced[6] ( 846 Mb ) ( ссылка истечет 29.03.2017 )
Пароли
root:root
phpbb:phpbb
mysql root:root
mysql phpbb:i6p0AYF1B4Hg
phpbb: kreon:kreon1
Бонус #2
Небольшой cheatsheet. Команды
semodule — управляет списком модулей
sestatus — текущий статус SELinux
setenforce 1/0 — включить/выключить enforcing
audit2allow — утилита для генерации правил ( и для подсказок )
sesearch — утилита для поиска правил в политике
seinfo — показывает информацию о типах, ролях, атрибутах итд
semanage — позволяет вносить изменения в политики
chcon — позволяет менять контекст на ФС
restorecon — востанавливает контекст по-умолчанию
setsebool — устанавливает переменную в on/off. С -P — пишет на диск
getsebool — получает переменную. -a — посмотреть все
Изменения политики
semanage port -a/-d -t httpd_port_t -p tcp 8044 — добавить/удалить номер порта к контексту
semanage fcontext -a/-d -t httpd_cache_t "/srv/http/cache(/.*)?" — добавить/удалить контекст для этой маски
semanage permissive -a/-d httpd_t — включить/выключить режим permissive для httpd_t
Аргументы к командам
id -Z — показывает контекст текущего пользователя
ls -Z — показывает контекст файлов
ps -Z — показывает контекст процессов
netstat -Z — показывает контекст соединений
usermod/useradd -Z связать пользователя с SELinux-пользователем