Что такое мандатный контроль доступа и зачем он нужен на сервере
Мандатный контроль доступа (MAC) — дополнительный слой защиты поверх обычных прав Linux. Даже процесс от root не выйдет за рамки разрешённых политикой действий. Взломанный процесс nginx без MAC получает доступ ко всей файловой системе, а с SELinux или AppArmor — только к файлам своего профиля.
На RHEL, CentOS и AlmaLinux за это отвечает SELinux, на Ubuntu и Debian — AppArmor. Оба включены по умолчанию, но администраторы часто отключают их при первой же ошибке — сервер теряет важный барьер защиты.
Чем отличается SELinux от AppArmor
SELinux работает по модели меток: файлу, процессу, порту и сокету присваивается контекст user:role:type:level, а политика описывает, каким процессам разрешено взаимодействовать с какими объектами. Контроль гибкий, но сложный в отладке.
AppArmor проще: правила привязаны не к меткам, а к путям, профиль — текстовый файл в /etc/apparmor.d/, например /etc/apparmor.d/usr.sbin.nginx. Порог входа ниже, но защита менее детальная: путь обходят симлинком или bind-mount при небрежном профиле.
| Параметр | SELinux | AppArmor |
|---|---|---|
| Дистрибутивы | RHEL, CentOS, AlmaLinux, Fedora | Ubuntu, Debian |
| Модель | Метки на объектах | Пути в профиле |
| Формат правил | Бинарная политика, булевы флаги | Текстовый профиль |
| Режимы | enforcing, permissive, disabled | enforce, complain |
| Утилита анализа | audit2allow | aa-logprof |
Как проверить статус и переключить режим работы
Текущий режим SELinux показывает getenforce, подробности — sestatus. Настройка в файле /etc/selinux/config, параметр SELINUX= принимает enforcing, permissive или disabled. Временно переключить режим до перезагрузки:
sestatus
setenforce 0 # временно перевести в permissive
setenforce 1 # вернуть enforcing
В AppArmor статус профилей показывает aa-status: видно, работает профиль в enforce или complain. Перевод одного профиля в тестовый complain не отключает защиту целиком, а лишь ослабляет её для одного процесса:
aa-status
aa-complain /etc/apparmor.d/usr.sbin.nginx
aa-enforce /etc/apparmor.d/usr.sbin.nginx
Как настроить контексты SELinux и профили AppArmor для nginx и php-fpm
Важны правильные типы контекста на файлах и переключатели (booleans). Каталог с сайтом — тип httpd_sys_content_t, каталоги для записи (кеш, загрузки, сессии) — тип httpd_sys_rw_content_t. Для сети включают нужный boolean:
semanage fcontext -a -t httpd_sys_content_t "/var/www/site(/.*)?"
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/site/uploads(/.*)?"
restorecon -Rv /var/www/site
setsebool -P httpd_can_network_connect 1
В AppArmor профили для nginx и php-fpm обычно уже в пакете, но пути сайта нужно явно прописать, иначе доступ запрещён. После правки профиль перечитывают:
vim /etc/apparmor.d/usr.sbin.nginx
apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
systemctl reload apparmor
Принцип один: разрешать доступ точечно, под конкретный каталог или порт. Базовые права файлов — в статье о правах доступа Linux, шаги защиты — в статье про усиление безопасности nginx.
Как диагностировать блокировки через audit2allow и aa-logprof
Когда SELinux блокирует действие, запись попадает в /var/log/audit/audit.log. Точечное правило вместо отключения защиты целиком генерируют связкой ausearch и audit2allow:
ausearch -m avc -ts recent
audit2allow -a -M nginx_uploads
semodule -i nginx_uploads.pp
Модуль nginx_uploads.pp добавляет только реально запрошенное разрешение — это безопаснее permissive для всей системы. Перед применением стоит открыть .te-файл и проверить правило на лишние права, например доступ к shadow_t.
В AppArmor похожую роль играет aa-logprof: читает журнал ядра, находит записи DENIED для профилей в complain и предлагает добавить правило:
aa-complain /etc/apparmor.d/usr.sbin.php-fpm
# воспроизвести действие на сайте
aa-logprof
aa-genprof строит профиль с нуля, а мониторинг процесса дополняют инвентаризацией через osquery или логами в Wazuh SIEM.
Что делать при переносе сайта, чтобы не сломать его неправильным контекстом
Частая ошибка после переноса сайта или бэкапа — файлы копируются через rsync, tar или FTP и получают контекст родителя вместо httpd_sys_content_t. Nginx и php-fpm выдают 403 Forbidden при корректных chmod и chown — файл блокирует контекст SELinux, а не Unix-права.
Исправляется это восстановлением контекста по политике, а не назначением типа на каждый файл вручную:
restorecon -Rv /var/www/site
ls -Z /var/www/site/index.php
В AppArmor такой проблемы нет, но после переноса сайта на новый путь (например, с /var/www/html на /var/www/site) профиль обновляют вручную, иначе процесс не увидит новые файлы или получит DENIED.
Чек-лист по SELinux и AppArmor на продакшн-сервере
- Режим enforcing (SELinux) или enforce (AppArmor) включён на проде, а не только в тестах.
- После переноса сайта выполнен
restorecon -Rvдля каталога с сайтом. - Каталоги для загрузок и кеша — тип
httpd_sys_rw_content_t, а не общий read-only тип. - Новые запреты разбирают через
audit2allowилиaa-logprof, а не командойsetenforce 0навсегда. - Сгенерированные модули и профили проверены вручную перед применением.
- Защита MAC не заменяет базовую конфигурацию сервера — права файлов, firewall и SSH настроены отдельно, см. общий чек-лист безопасности сервера.