# Мандатный контроль доступа: настройка SELinux и AppArmor

> Мандатный контроль доступа в Linux: как настроить SELinux на RHEL и AlmaLinux, AppArmor на Ubuntu, проверить режим работы и не сломать сайт при переносе.

## Что такое мандатный контроль доступа и зачем он нужен на сервере

Мандатный контроль доступа (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](https://www.zevshost.net/ru/kb/linux-file-permissions/), шаги защиты — в статье про [усиление безопасности nginx](https://www.zevshost.net/ru/kb/nginx-security-hardening/).

## Как диагностировать блокировки через 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](https://www.zevshost.net/ru/kb/wazuh-siem-monitoring/).

## Что делать при переносе сайта, чтобы не сломать его неправильным контекстом

Частая ошибка после переноса сайта или бэкапа — файлы копируются через 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 настроены отдельно, см. общий [чек-лист безопасности сервера](https://www.zevshost.net/ru/kb/server-security-checklist/).

---

Источник: https://www.zevshost.net/ru/kb/selinux-apparmor-nastroika/
