Безопасность серверов

SELinux на сервере: Enforcing, контексты и устранение отказов

Как проверить режим SELinux, разобрать AVC-отказ и исправить контекст, Boolean или метку порта без отключения защиты.

14 минут
абстрактная иллюстрация политики доступа и серверной защиты
Для устранения SELinux permission denied сначала зафиксируйте ошибку и время, проверьте режим SELinux и найдите соответствующий AVC-отказ. Затем выбирайте самое узкое исправление: восстановление метки, постоянное правило контекста для пути, предусмотренный политикой Boolean или метку нестандартного порта. Глобальный Permissive допустим только как краткая диагностическая мера с возвратом в Enforcing; Disabled не является штатным способом исправления доступа.

Как SELinux принимает решение о доступе

SELinux — механизм мандатного контроля доступа, работающий через каркас Linux Security Modules. Он дополняет, а не заменяет дискреционный контроль доступа: владельца, группу, Unix-права и ACL.

Обычно на RHEL, Rocky Linux, AlmaLinux и Fedora применяется Targeted policy. В её основе лежит Type Enforcement: процесс — субъект — работает в домене SELinux, объект имеет тип, а политика SELinux определяет допустимые операции домена над этим типом.

Полный контекст SELinux выглядит как user:role:type:level, например system_u:system_r:httpd_t:s0 у процесса. В повседневной диагностике чаще всего важен третий компонент — type: httpd_t, httpd_sys_content_t, var_log_t и другие. Поэтому корректные Unix-права на файл ещё не означают, что веб-сервер в домене httpd_t сможет его прочитать: политика может не разрешать этому домену операцию read над фактическим типом файла.

Не расширяйте Unix-права вместо исправления SELinux

Права chmod 777, смена владельца или запуск службы от root не исправляют неверный SELinux-тип и могут создать отдельную проблему безопасности. При этом сообщение приложения Permission denied может быть вызвано Unix-правами, ACL, неверным путём, конфигурацией приложения или SELinux. Найденный AVC фиксирует запрет политики SELinux, но его ещё нужно сопоставить с наблюдаемым сбоем по времени, процессу, объекту и операции.

SELinux status: Enforcing, Permissive и Disabled

Показывает текущий рабочий режим SELinux: `Enforcing`, `Permissive` или `Disabled`.
getenforce
Вывод:
Enforcing
Показывает более подробное состояние: включён ли SELinux, текущий и настроенный при загрузке режим, загруженную политику и при наличии MLS/MCS сведения о её уровне.
sestatus
РежимПоведениеТипичное применение
EnforcingОперации, запрещённые политикой, блокируются; отказы обычно фиксируются как AVC.Штатный режим работающего сервера.
PermissiveЗапрещённые политикой операции не блокируются, но могут фиксироваться как AVC. Обычные Unix-права продолжают действовать.Краткая контролируемая диагностика или поэтапное внедрение.
DisabledПолитика не загружена, SELinux не проверяет и не ограничивает доступ.Только отдельные документированные сценарии миграции или совместимости.

getenforce показывает фактический режим в работающей системе. sestatus помогает сравнить его с конфигурацией на следующую загрузку: после временного setenforce 1 текущий режим может стать Enforcing, хотя в конфигурационном файле всё ещё задан другой режим.

Перевод SELinux в Enforcing

Команды предполагают права root или sudo. Для RHEL-совместимых систем типичный постоянный параметр находится в /etc/selinux/config; сверяйте процедуру со справочником именно своего выпуска ОС.

  1. 1
    Проверьте текущий и настроенный режим
    Выполните getenforce и sestatus. Если getenforce возвращает Permissive, SELinux уже активен и его можно перевести в блокирующий режим без перезагрузки.
  2. 2
    Включите Enforcing временно
    Выполните sudo setenforce 1, затем снова выполните getenforce. Ожидаемый результат — Enforcing. Если команда сообщает, что SELinux disabled, она не сможет включить защиту: политика не загружена.
  3. 3
    Закрепите режим на следующую загрузку
    Проверьте строку SELINUX= в /etc/selinux/config и установите SELINUX=enforcing. Затем подтвердите значение командой grep '^SELINUX=' /etc/selinux/config. Это изменение задаёт режим для последующих загрузок, но не заменяет setenforce для уже работающей системы.
  4. 4
    Проверьте сервис в Enforcing
    Повторите действие, которое раньше завершалось ошибкой, и проверьте новые AVC-события. Если служба не работает, не оставляйте систему в Permissive как постоянное решение: разберите конкретный отказ и примените узкое исправление.
Временно переводит активный SELinux в Permissive для диагностики. Изменение действует до следующей перезагрузки или до `sudo setenforce 1`.
sudo setenforce 0

Почему Disabled не заменяет диагностику

setenforce переключает только Enforcing и Permissive. Переход в режим Disabled SELinux и возврат из него требуют отдельной постоянной процедуры включения SELinux, relabel файловой системы и перезагрузки по документации конкретного дистрибутива и версии. Отключение скрывает причину отказа, снимает слой контроля и может оставить файлы без ожидаемых меток. Не используйте Disabled как обычное исправление ошибки приложения.

Как использовать Permissive безопасно

Если при неизменных остальных условиях действие начинает работать только после перехода в Permissive, это сильный признак влияния политики SELinux, но результат не говорит, какое разрешение следует добавить. Зафиксируйте время теста и действие, соберите AVC, верните setenforce 1 и исправьте причину. Если действие не работает и в Permissive, ищите проблему в конфигурации сервиса, сети, Unix-правах или данных приложения.

Маршрут диагностики AVC-отказа

Отказ AVC нужно связывать с конкретным действием службы, а не с общей строкой Permission denied в журнале приложения. До изменений сохраните текст ошибки, время с часовым поясом, имя сервиса, путь или порт и команду либо запрос, вызвавший проблему.

Найдите и разберите событие SELinux is preventing

  1. 1
    Повторите сбой в контролируемый момент
    Воспроизведите один запрос, запуск службы или операцию с файлом. Запишите точное время: это позволит отличить нужный AVC от старых и посторонних событий.
  2. 2
    Проверьте контексты процесса и объекта
    Для процесса используйте ps -eZ | grep -E 'httpd|nginx|имя_процесса'; для файла или каталога — ls -lZ /путь либо ls -Zd /каталог. Сравнивайте прежде всего компонент type в контексте процесса — его домен — и компонент type в контексте объекта.
  3. 3
    Найдите AVC через audit
    В типичной системе с работающим auditd выполните sudo ausearch -m AVC,USER_AVC -ts recent -i. Для фильтрации по имени команды процесса можно использовать sudo ausearch -m AVC -c httpd -ts recent -i, подставив фактическое значение comm. Ищите событие, близкое по времени к воспроизведённой ошибке.
  4. 4
    Разберите поля отказа
    В AVC определите comm= или exe= — какой процесс запрашивал доступ. Поля scontext= и tcontext= содержат полные контексты вида user:role:type:level: третий компонент scontext обозначает домен процесса, а третий компонент tcontext — тип целевого объекта. Поле tclass= задаёт класс объекта, например file, dir или tcp_socket; содержимое { ... } — запрошенную операцию, например read, write или name_connect. Поле name= иногда помогает определить объект, но его нужно сверить с фактическим путём или конфигурацией сервиса.
  5. 5
    Выберите минимальное исправление
    Неверный тип файла исправляйте через restorecon или постоянное правило semanage fcontext; предусмотренное поведение службы — Boolean; нестандартный порт — меткой порта. Локальный модуль рассматривайте только после исключения этих вариантов.
  6. 6
    Повторите действие в Enforcing
    После изменения снова воспроизведите исходную операцию при результате Enforcing команды getenforce. Затем проверьте, не появился ли новый AVC. Успешный запуск службы сам по себе не доказывает, что требуемая операция приложения действительно выполнена.
Дополнительный поиск SELinux-сообщений в журнале текущей загрузки. Полезен, если auditd не установлен, отключён или пишет события не туда, где ожидается.
sudo journalctl -b | grep -iE 'avc:|selinux|denied'

Где искать журнал AVC

Расположение и наличие журнала AVC зависят от конфигурации auditd, journald и версии ОС. Часто audit-события доступны через ausearch и могут храниться в /var/log/audit/audit.log, но этот путь не следует считать гарантированным. Полную настройку auditd и хранение журналов рассматривает статья «Аудит безопасности Linux».

Контекст файла: restorecon, semanage fcontext и chcon

СредствоКогда применятьСохраняется после relabel
restoreconЧтобы вернуть ожидаемую метку по уже известным правилам политики и локальным сопоставлениям.Да, если для пути есть правило политики или semanage fcontext.
semanage fcontext + restoreconДля постоянного назначения типа нестандартному пути или дереву каталогов.Да.
chconДля краткой проверки гипотезы или разового временного изменения.Обычно нет: ручная метка может быть заменена при restorecon или полном relabel.
Сравнивает фактический контекст каталога с контекстом, который ожидают текущие правила сопоставления путей. Если типы различаются, сначала обычно уместен `restorecon`.
ls -ldZ /srv/example && matchpathcon /srv/example
Рекурсивно восстанавливает контексты по действующим правилам. После выполнения снова проверьте `ls -lZ /srv/example` и повторите операцию сервиса.
sudo restorecon -Rv /srv/example

Если приложение хранит данные вне штатного пути, одного restorecon недостаточно. Он применяет только существующие правила сопоставления путей: может назначить общий тип для этого расположения либо не изменить метку, если подходящего правила нет. Нужный тип веб-контента или данных приложения автоматически из назначения каталога не выводится. Назначьте тип, подходящий именно для его содержимого. Например, для статического содержимого веб-службы политика может предоставлять тип httpd_sys_content_t; типы для записи, кэша, журналов и загружаемых файлов отличаются и зависят от пакета и версии политики.

persistent-file-context.sh
# Пример для дерева статического контента веб-службы.
# Тип и путь должны соответствовать назначению конкретного сервиса.
sudo semanage fcontext -a -t httpd_sys_content_t '/srv/example(/.*)?'
sudo restorecon -Rv /srv/example
ls -ldZ /srv/example
ls -lZ /srv/example

Параметр -a добавляет новое сопоставление. Если для того же выражения уже существует локальное правило, обычно требуется его изменить через semanage fcontext -m, а не добавлять дубликат. Перед изменением просмотрите локальные сопоставления: sudo semanage fcontext -C -l. Регулярное выражение (/.*)? включает сам каталог и его содержимое; не применяйте его к более широкому пути, чем нужно.

Временно меняет тип непосредственно на объектах. Используйте только для короткого диагностического теста и не считайте это постоянной настройкой контекста SELinux.
sudo chcon -R -t httpd_sys_content_t /srv/example

Не копируйте тип без понимания назначения

Тип, разрешающий чтение статического контента, не обязательно разрешает запись; тип для записываемого каталога не обязательно подходит для конфигурации или секретов. Не назначайте сервису широкий тип произвольных данных только для устранения одного AVC. Сначала определите, должен ли процесс вообще читать, создавать или изменять этот объект.

Boolean SELinux: предусмотренное политикой поведение

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

Выводит доступные Boolean, относящиеся к домену веб-службы, и их текущее состояние. Отсутствие конкретного имени означает, что не следует пытаться применять пример из другой системы.
getsebool -a | grep '^httpd_'
Проверяет состояние Boolean `httpd_can_network_connect`, если он присутствует в установленной политике.
getsebool httpd_can_network_connect
Вывод:
httpd_can_network_connect --> off
Постоянно включает предусмотренное политикой разрешение исходящих сетевых подключений для домена веб-службы. Без `-P` изменение временное и обычно исчезает после перезагрузки или перезагрузки политики.
sudo setsebool -P httpd_can_network_connect on

httpd_can_network_connect — пример из целевой политики SELinux, а не универсальное исправление для Nginx, Apache и любого исходящего соединения. Перед включением подтвердите AVC с операцией вроде name_connect, домен процесса и рабочую необходимость: например, веб-приложение действительно обращается к внешнему API или локальному backend. Этот Boolean не открывает порт в firewall и не заменяет сетевую политику; исходящие правила рассматриваются отдельно в статье «Firewall сервера: default deny, порядок правил и политика доступа».

SELinux port context для нестандартного порта

SELinux проверяет не только файлы. При запуске службы на нестандартном порту процесс может получить AVC, потому что этот номер не связан с типом порта, разрешённым его домену. Сначала убедитесь, что порт действительно предназначен для этого сервиса, не занят другим процессом и что нужный входящий доступ разрешён отдельной политикой firewall.

Показывает номера TCP/UDP-портов, уже назначенные типу `http_port_t`. Имя типа приведено как пример для веб-службы.
sudo semanage port -l | grep -E '^http_port_t\b'
port-context.sh
# Пример для TCP-порта 18080. Сначала убедитесь, что порт
# не занят процессом и не указан в сопоставлениях SELinux —
# отдельно либо внутри диапазона.
sudo ss -ltnp
sudo semanage port -l | less

# Выполняйте добавление только после такой проверки:
sudo semanage port -a -t http_port_t -p tcp 18080

# Проверка результата:
sudo semanage port -l | grep -E '^http_port_t\b'

Если номер уже присутствует в выводе semanage port -l, не добавляйте его повторно. Изменение существующего сопоставления выполняют semanage port -m, но сначала нужно установить, какой сервис использует этот порт и не нарушит ли переназначение его политику. Типы http_port_t и набор допустимых портов не одинаковы во всех версиях политики.

audit2why, sealert и audit2allow: как применять без широких разрешений

audit2why помогает интерпретировать уже найденные AVC и иногда указывает на Boolean или другую известную причину. Передавайте ему ограниченный набор актуальных событий, а не весь старый журнал.

Анализирует недавние AVC-события и выводит возможное объяснение политики. Результат — подсказка для проверки, а не команда для автоматического применения.
sudo ausearch -m AVC,USER_AVC -ts recent -i | audit2why

sealert — средство setroubleshoot, которое может анализировать журнал и предлагать варианты исправления. Если оно установлено и доступен файл audit-журнала, типичный запуск выглядит как sudo sealert -a /var/log/audit/audit.log; путь и наличие журнала зависят от настройки auditd. Предложения sealert полезно использовать как перечень гипотез: сверяйте их с конкретным доменом, объектом, операцией и назначением сервиса.

Не устанавливайте вывод audit2allow автоматически

audit2allow строит разрешения по наблюдавшимся отказам, но не знает, было ли действие корректным. Автоматическая генерация пакета через audit2allow -M с его немедленной установкой через semodule -i может разрешить доступ к объекту с неверной меткой, замаскировать ошибочную конфигурацию или добавить слишком широкое право. Сначала исключите restorecon, semanage fcontext, подходящий Boolean, метку порта, Unix-права и ошибку конфигурации.

Контролируемая проверка локального модуля SELinux

Локальный модуль политики SELinux оправдан, когда необходимое и обоснованное действие не покрыто штатной политикой, меткой, Boolean или настройкой сервиса.

  1. 1
    Соберите только относящиеся к проблеме AVC
    Воспроизведите одну операцию и отберите события за короткий интервал или по имени процесса. Не смешивайте отказы нескольких служб: иначе будущий модуль может получить лишние разрешения.
  2. 2
    Сгенерируйте проект, но не устанавливайте его
    Например: sudo ausearch -m AVC -c имя_процесса -ts recent -i | audit2allow -M local_service. Инструмент обычно создаёт исходный файл .te и пакет .pp; точные имена и формат зависят от версии инструментов.
  3. 3
    Проведите ревизию исходного правила
    Откройте созданный .te и сопоставьте каждое allow с ожидаемым действием: домен процесса, тип объекта, класс и разрешения. Если правило даёт доступ к неожиданному типу, разрешает запись вместо чтения или включает несколько несвязанных операций, вернитесь к причинам отказа, а не устанавливайте модуль.
  4. 4
    Проверьте модуль в изолированной среде
    Устанавливайте минимальный модуль сначала на тестовом узле или в другой изолированной среде с сопоставимой версией политики. Повторите только требуемый сценарий в Enforcing и проверьте новые AVC. Тестовая система не должна быть общим производственным узлом.
  5. 5
    Установите и зафиксируйте решение только после ревизии
    После одобрения пакет обычно устанавливают командой sudo semodule -i local_service.pp. Проверьте наличие через sudo semodule -l | grep '^local_service\b', сохраните исходный .te, пакет, обоснование и владельца изменения. Для удаления применяется sudo semodule -r local_service; имя модуля берите из списка, а не только из имени файла.

Пакеты и доступность инструментов

На RHEL, Rocky Linux, AlmaLinux и Fedora состав и названия SELinux-пакетов зависят от выпуска и подключённых репозиториев. Базовые утилиты обычно входят в policycoreutils. В актуальных RHEL-подобных выпусках и Fedora команды semanage, audit2why и audit2allow обычно предоставляет policycoreutils-python-utils; в старых выпусках встречается пакет policycoreutils-python. Команда sealert обычно относится к пакетам семейства setroubleshoot. Пакеты setools предоставляют отдельные средства анализа политики, но не следует считать их типичным источником audit2allow. Не переносите эти имена на другие семейства Linux: сначала выполните command -v semanage audit2why audit2allow sealert, а владельца каждой отсутствующей команды ищите отдельно, например через dnf provides '*/audit2allow', dnf provides '*/semanage' или аналогичный запрос пакетного менеджера.

Что документировать после исправления

  • Сервис, хост, время возникновения и текст исходной ошибки.
  • AVC: полные scontext и tcontext, выделенные из них домен процесса и тип объекта, класс, запрошенная операция и затронутый путь или порт.
  • Выбранное узкое исправление: правило semanage fcontext, Boolean, метка порта или локальный модуль.
  • Проверку работы в Enforcing и отсутствие нового относящегося к проблеме AVC.
  • Причину, владельца и процедуру отката для постоянного изменения.

SELinux — только один слой защиты сервера. Выбор между SELinux и AppArmor рассматривается в статье «SELinux или AppArmor: какую систему мандатного контроля доступа выбрать», а последовательность остальных мер — в чек-листе hardening Linux-сервера.

Термины в статье

Boolean SELinux — именованный логический параметр, от значения которого зависит применение предусмотренных политикой SELinux условных правил без изменения их исходного текста.
Linux Security Modules — каркас ядра Linux для подключения модулей контроля доступа, перехватывающих операции с объектами системы по заданным политикам.
SELinux — подсистема мандатного контроля доступа Linux, применяющая политики и метки безопасности для ограничения действий процессов сверх обычных прав Unix.
Targeted policy — вариант политики SELinux, в котором обязательный контроль доступа применяется к выбранным системным службам, а остальные процессы обычно работают в домене unconfined.
Type Enforcement — модель мандатного контроля доступа, в которой правила разрешают действия процессов определённых типов над объектами заданных типов.
Дискреционный контроль доступа — модель авторизации, в которой владелец объекта назначает права пользователям и группам через разрешения или списки ACL.
Домен SELinux — тип безопасности процесса в политике SELinux, определяющий набор разрешённых действий процесса над объектами с заданными метками.
Журнал AVC — записи аудита SELinux о решениях Access Vector Cache, прежде всего об отказах доступа по действующей политике безопасности.
Контекст SELinux — метка безопасности объекта или процесса, содержащая пользователя SELinux, роль, тип и уровень MLS/MCS; политика учитывает её при контроле доступа.
Мандатный контроль доступа — модель разграничения доступа, в которой операции разрешаются обязательной системной политикой, не изменяемой владельцем ресурса.
Метка безопасности SELinux — контекст, присваиваемый процессу, файлу или объекту, по которому политика SELinux разрешает или запрещает обращения.
Модуль политики SELinux — устанавливаемый компонент, добавляющий правила, типы, атрибуты или сопоставления файловых контекстов для конкретного ПО или сценария.
Отказ AVC — диагностическое сообщение SELinux о действии, не разрешённом политикой; обычно оно указывает субъект, объект, класс объекта и запрошенное разрешение.
Политика SELinux — набор правил мандатного контроля доступа, задающий допустимые действия доменов над объектами с метками безопасности.
Режим Disabled SELinux — состояние, в котором политика SELinux не загружена и SELinux не проверяет и не ограничивает доступ.
Режим Permissive — режим SELinux, в котором потенциальные отказы не блокируют операции и фиксируются как AVC, если не подавлены правилами dontaudit; права Linux продолжают действовать.
Режим SELinux — состояние принудительного контроля доступа в Linux, определяющее применение политик: блокирование, только журналирование нарушений или полное отключение SELinux.

Вопросы по теме

Все вопросы и ответы

Можно ли отключить SELinux, чтобы убрать Permission denied?

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

Для проверки гипотезы допустим только краткий контролируемый переход активного SELinux в Permissive командой setenforce 0: запрещённые политикой действия не блокируются, но могут фиксироваться как AVC. Зафиксируйте время и действие, соберите относящийся к нему AVC, верните setenforce 1 и исправьте конкретную причину в Enforcing. Переход в Disabled и возврат из него требуют отдельной постоянной процедуры, relabel файловой системы и перезагрузки по документации конкретного дистрибутива.

Можно ли оставить SELinux в Permissive после диагностики?

Нет, не как постоянное решение для работающего сервера. Permissive не блокирует действия, запрещённые политикой, хотя AVC могут продолжать записываться. Используйте его кратко для проверки гипотезы, зафиксируйте время теста и AVC, затем верните setenforce 1 и устраните конкретный отказ.

Почему веб-служба не запускается на нестандартном порту при открытом firewall?

Возможно, номер порта не связан с SELinux-типом, который разрешён домену службы. Открытый firewall не заменяет проверку SELinux. Сначала убедитесь, что порт предназначен для сервиса и не занят, проверьте AVC и существующие сопоставления через semanage port -l; не добавляйте номер повторно и не меняйте его тип без проверки другого сервиса.

Нужно ли включать httpd_can_network_connect для исходящих запросов веб-службы?

Зависит от AVC и назначения приложения. httpd_can_network_connect — пример Boolean, который может разрешить исходящие подключения домену веб-службы, но его нельзя включать автоматически. Сначала подтвердите AVC с операцией вроде name_connect, домен процесса и реальную потребность, например обращение приложения к API или локальному backend.

Можно ли сразу установить модуль, созданный audit2allow?

Нет. audit2allow строит разрешения по наблюдавшимся отказам, но не определяет, было ли действие корректным. Такой модуль может замаскировать неверную метку или конфигурацию и дать слишком широкие права. Сначала исключите проблемы контекста, Boolean, метки порта, Unix-прав и конфигурации, затем проверьте правила модуля в изолированной среде.

Почему setenforce 1 не включает SELinux?

Если SELinux имеет статус Disabled, setenforce 1 не сможет включить защиту: политика не загружена. Команда переключает только активный SELinux между Enforcing и Permissive. Для Disabled требуется отдельная постоянная процедура включения, relabel файловой системы и перезагрузка по документации конкретного дистрибутива и версии.