---
tags: [linux, security]
verified: 2026-09-02
---

# Linux — безопасность: hardening, SELinux/AppArmor, аудит

## Обзор

Модель безопасности Linux строится послойно: DAC (Discretionary Access Control — классические UNIX-права rwx) → capabilities (гранулярные привилегии вместо монолитного root) → MAC (Mandatory Access Control через LSM — SELinux/AppArmor) → seccomp (фильтрация системных вызовов) → audit (аудит событий). Каждый слой компенсирует слабости предыдущего. DAC недостаточен, потому что скомпрометированный root-процесс обходит все ограничения. MAC решает это: даже root подчиняется политике, определённой администратором.

В FreeBSD аналогичная послойная модель: DAC → MAC framework (аналог LSM) → capsicum (аналог seccomp) → securelevel (глобальное ограничение привилегий). Но реализации существенно отличаются.

## DAC: классическая модель

DAC — владелец объекта (файла, директории) определяет права доступа. User/group/other × read/write/execute + SUID/SGID/sticky bit. ACL (Access Control Lists, setfacl/getfacl) расширяют модель, позволяя задать права для произвольных пользователей/групп.

Фундаментальная слабость DAC: если процесс получает привилегии root (через эксплойт, misconfiguration, SUID binary), он обходит все DAC-ограничения. Поэтому DAC — необходимый, но недостаточный уровень.

## Capabilities: гранулярный root

Традиционно UNIX знает два уровня привилегий: обычный пользователь и root (UID 0). Capabilities (с ядра 2.2) разбивают привилегии root на ~40 дискретных capabilities:

**CAP_NET_BIND_SERVICE** — привязка к портам <1024. **CAP_NET_RAW** — raw sockets (ping, tcpdump). **CAP_SYS_PTRACE** — отладка процессов других пользователей. **CAP_DAC_OVERRIDE** — обход проверок прав доступа к файлам. **CAP_SYS_ADMIN** — "мусорная корзина" привилегий: mount, swapon, настройка hostname, ядерные namespace operations и десятки других. По сути — почти root.

Capabilities назначаются на три уровня: file capabilities (через setcap, хранятся в extended attributes — замена SUID), thread capabilities (наследуются/изменяются при exec()), ambient capabilities (с 4.3, позволяют передать capabilities дочерним процессам без file capabilities).

```bash
# Назначить capability на файл (вместо SUID root)
setcap cap_net_bind_service+ep /usr/bin/myserver

# Проверить capabilities файла
getcap /usr/bin/myserver

# Запустить процесс с ограниченными capabilities
# systemd: в unit-файле
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW
AmbientCapabilities=CAP_NET_BIND_SERVICE

# Посмотреть capabilities процесса
cat /proc/<PID>/status | grep Cap
getpcaps <PID>
```

systemd интегрирован с capabilities: каждый сервис может декларировать CapabilityBoundingSet (максимум доступных) и AmbientCapabilities (переданных при exec). Вместе с User=, ProtectHome=, ProtectSystem= это формирует sandbox без SELinux/AppArmor (см. статью 2).

## LSM: Linux Security Modules

LSM — фреймворк ядра, предоставляющий hooks (точки перехвата) для модулей безопасности. Hooks размещены во всех критических точках: открытие файла, exec(), создание сокета, изменение прав, ptrace и т.д. LSM hooks выполняются после DAC-проверок и могут дополнительно запретить операцию.

Текущие LSM в ядре (2026, по списку `CONFIG_LSM` в mainline): AppArmor, SELinux, Smack, TOMOYO, Yama, LoadPin, SafeSetID, Lockdown, Landlock, IPE (Integrity Policy Enforcement), BPF (LSM BPF с ядра 5.7). Major LSMs (SELinux, AppArmor, Smack) — exclusive: только один может быть active одновременно. Minor LSMs (Yama, Lockdown, Landlock, capabilities) могут работать параллельно с major.

### SELinux

Разработан NSA, дефолт в RHEL/Fedora/CentOS. Label-based: каждый объект (файл, процесс, порт, сокет) имеет security context (метку) в формате `user:role:type:level`. Политика определяет, какие типы могут взаимодействовать.

```bash
# Контекст файла
ls -Z /var/www/html/index.html
# unconfined_u:object_r:httpd_sys_content_t:s0

# Контекст процесса
ps -eZ | grep httpd
# system_u:system_r:httpd_t:s0  /usr/sbin/httpd
```

Правило политики (упрощённо): `allow httpd_t httpd_sys_content_t:file { read open getattr };` — процесс типа httpd_t может читать файлы типа httpd_sys_content_t.

**Targeted policy** (дефолт в RHEL) — конфайнит только определённые сервисы, остальные работают в unconfined_t. **MLS/MCS** — многоуровневая секретность (используется в government/military setups) и Multi-Category Security (изоляция контейнеров).

Режимы: Enforcing (политика применяется), Permissive (нарушения логируются, но не блокируются), Disabled (SELinux полностью отключён — **не рекомендуется**, переключение обратно требует relabeling всей ФС). Начиная с RHEL 9 третий режим через конфиг уже не работает как раньше: `SELINUX=disabled` в `/etc/selinux/config` оставляет подсистему включённой, но без загруженной политики, а для настоящего отключения нужен параметр ядра `selinux=0`.

```bash
getenforce                        # текущий режим
setenforce 0                      # переключить в Permissive (до перезагрузки)
# Постоянное изменение: /etc/selinux/config → SELINUX=enforcing

# Troubleshooting — главная причина «SELinux всё ломает»
ausearch -m avc -ts recent        # последние denial'ы из audit.log
audit2why < /var/log/audit/audit.log  # объяснить причину denial
audit2allow -a -M mypolicy        # сгенерировать policy module из denial'ов
semodule -i mypolicy.pp           # установить policy module

# Исправление контекстов файлов (частая проблема)
restorecon -Rv /var/www/html/     # восстановить дефолтные контексты
chcon -t httpd_sys_content_t file # изменить контекст вручную (не переживёт relabel)
semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"  # постоянное правило
restorecon -Rv /srv/www/
```

### AppArmor

Дефолт в Ubuntu и Debian; SUSE от него ушла — Tumbleweed переключился на SELinux со снапшота 20250211 (февраль 2025), а SLE 16 (ноябрь 2025) и построенный на нём openSUSE Leap 16 ставятся с SELinux в enforcing, AppArmor в них остаётся опцией для ручного включения. Path-based: профили определяют, к каким путям файловой системы и с какими правами может обращаться программа.

```conf
# /etc/apparmor.d/usr.sbin.nginx
/usr/sbin/nginx {
    # Сеть
    network inet stream,
    network inet6 stream,

    # Файлы
    /etc/nginx/** r,
    /var/log/nginx/** rw,
    /var/www/** r,
    /run/nginx.pid rw,

    # Capabilities
    capability net_bind_service,
    capability setuid,
    capability setgid,

    # Запретить всё остальное (implicit deny)
}
```

Режимы: Enforce (блокировка + лог), Complain (только лог — аналог SELinux Permissive). `aa-genprof` запускает приложение в complain-mode и интерактивно генерирует профиль на основе наблюдаемого поведения.

```bash
aa-status                          # все загруженные профили и их режимы
aa-enforce /etc/apparmor.d/usr.sbin.nginx
aa-complain /etc/apparmor.d/usr.sbin.nginx
aa-logprof                         # обновить профиль по логам нарушений
```

### SELinux vs AppArmor: архитектурный trade-off

SELinux — label-based (метки на inode): переименование файла не меняет его тип, hard link сохраняет контекст. Гранулярнее (type enforcement, role-based, MLS/MCS), но значительно сложнее в настройке и отладке. Типичная реакция администратора — `setenforce 0` (отключить).

AppArmor — path-based: профили привязаны к путям. Проще писать и понимать, но если файл доступен по другому пути (hard link, bind mount), профиль может быть обойдён. Частично компенсируют это ядерные ограничения `fs.protected_hardlinks` и `fs.protected_symlinks`: они начинали жизнь в Yama, но давно переехали в общий код VFS, и systemd включает их своим `sysctl.d/50-default.conf` — сам Yama сегодня отвечает только за `ptrace_scope`.

Для контейнеров SELinux предоставляет MCS-изоляцию: каждый контейнер получает уникальную категорию (s0:c1,c2), что предотвращает доступ между контейнерами даже при escaping namespace isolation. Docker и Podman автоматически назначают MCS-метки.

## seccomp: фильтрация системных вызовов

seccomp-bpf (с ядра 3.5) позволяет процессу установить BPF-фильтр, определяющий, какие системные вызовы разрешены. Фильтр — одностороннее ограничение: установленный, он не может быть снят или ослаблен.

seccomp дополняет LSM: LSM контролирует доступ к объектам ядра (файлы, сокеты), seccomp контролирует интерфейс между userspace и ядром (syscalls). Ограничение seccomp: BPF-фильтры не могут разыменовывать указатели, поэтому seccomp не может проверить содержимое аргументов-строк (путь файла в open()).

Docker применяет default seccomp-профиль, блокирующий ~44 опасных syscall'а (из ~300+): mount, reboot, clock_settime, init_module, ptrace и др. Для большинства приложений это прозрачно. Podman использует аналогичный дефолтный профиль.

systemd предоставляет SystemCallFilter= в unit-файлах: `SystemCallFilter=@system-service` (предопределённые группы syscall'ов).

## Landlock: application-level sandboxing

Landlock (с ядра 5.13, стабилен с 5.19) — LSM, позволяющий непривилегированному процессу ограничить свой собственный доступ к файловой системе и сети. В отличие от SELinux/AppArmor (требуют root для загрузки политики), Landlock позволяет приложению самостоятельно sandbox'ить себя.

Концептуально Landlock ближе к FreeBSD Capsicum и OpenBSD pledge(): программа декларирует, что ей нужно (чтение /etc/config, запись в /tmp), а всё остальное запрещается ядром. С ядра 6.7 Landlock поддерживает и сетевые ограничения (bind/connect для TCP).

Возможности Landlock нумеруются собственной версией ABI, и ориентироваться нужно на неё, а не на версию ядра: ABI 6 (ядро 6.12) добавил изоляцию абстрактных unix-сокетов и сигналов, ABI 7 (6.15) — запись отказов в audit, ABI 8 (7.0) — флаг `LANDLOCK_RESTRICT_SELF_TSYNC`, ABI 10 (7.2) — UDP. Флаг TSYNC важнее остального: до него ruleset применялся только к вызывающему потоку и его потомкам, так что многопоточной программе приходилось ограничивать каждый поток отдельно.

## auditd: аудит событий

Linux Audit Framework — подсистема ядра для записи security-relevant событий. auditd — демон, принимающий события от ядра и записывающий в /var/log/audit/audit.log.

```bash
# Правила аудита (/etc/audit/rules.d/)
# Мониторинг изменений в /etc/passwd
-w /etc/passwd -p wa -k identity

# Мониторинг exec() с UID 0
-a always,exit -F arch=b64 -S execve -F euid=0 -k root-commands

# Мониторинг загрузки модулей ядра
-a always,exit -F arch=b64 -S init_module,finit_module -k module-load

# Поиск по логам
ausearch -k identity                      # по ключу
ausearch -m USER_LOGIN --success no       # неудачные логины
aureport --auth                           # сводка аутентификации
aureport --summary                        # общая сводка
```

auditd критичен для compliance (PCI DSS, HIPAA, SOX). На серверах с высокой нагрузкой audit может генерировать значительный I/O; аудит-правила должны быть targeted, не blanket.

## SSH hardening

SSH — основной вектор remote-доступа и частый target атак. Ключевые настройки (/etc/ssh/sshd_config):

```bash
PermitRootLogin no                    # запретить root login (использовать sudo)
PasswordAuthentication no             # только ключи
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
AllowUsers deploy admin               # whitelist пользователей
LoginGraceTime 30
ClientAliveInterval 300               # timeout неактивных сессий
ClientAliveCountMax 2
```

**fail2ban** / **sshguard** — анализ логов и блокировка IP после N неудачных попыток. fail2ban работает через iptables/nftables jails; sshguard — более лёгкая альтернатива. На серверах с публичным SSH fail2ban — минимально необходимая мера.

## Практика: уровни hardening

```bash
# 1. Проверка текущего состояния безопасности
getenforce                               # SELinux
aa-status                                # AppArmor
sysctl user.max_user_namespaces          # user namespaces, вентиль mainline
sysctl kernel.unprivileged_userns_clone  # downstream-патч Debian/Ubuntu
sysctl kernel.apparmor_restrict_unprivileged_userns  # Ubuntu 24.04+, по умолчанию 1
sysctl kernel.yama.ptrace_scope          # Yama ptrace restriction
cat /proc/sys/kernel/dmesg_restrict      # ограничение dmesg для non-root

# 2. Базовый hardening через sysctl
kernel.dmesg_restrict = 1                # скрыть kernel messages от non-root
kernel.kptr_restrict = 2                 # скрыть указатели ядра из /proc
kernel.yama.ptrace_scope = 1             # ptrace только для дочерних процессов
# Значения all, default и <iface> ядро комбинирует по-разному: rp_filter — как
# max(all, <iface>), redirects на узле без форвардинга — как OR, а default действует
# только на созданные позже интерфейсы; systemd вдобавок раздаёт rp_filter = 2 (loose)
net.ipv4.conf.all.rp_filter = 1          # reverse path filtering
net.ipv4.conf.*.rp_filter = 1            # glob понимает systemd-sysctl, но не procps
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.*.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.*.send_redirects = 0
kernel.unprivileged_bpf_disabled = 1     # запретить BPF для non-root
kernel.io_uring_disabled = 2             # отключить io_uring (attack surface)

# 3. Lockdown LSM (с ядра 5.4)
# integrity mode: запретить загрузку неподписанных модулей, /dev/mem доступ
# confidentiality mode: + скрыть ядерные данные из /proc
# Включается через kernel cmdline: lockdown=integrity

# 4. Проверка SUID-бинарей (минимизировать attack surface)
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
```

## Нюансы и trade-off'ы

**«Просто отключите SELinux»** — антипаттерн. SELinux denial в 90% случаев указывает на реальную проблему: неправильный файловый контекст (решается restorecon), нестандартный порт (semanage port -a), или действительно нежелательное поведение приложения. audit2why объясняет причину человеческим языком. Отключение SELinux убирает критический слой защиты, особенно важный для контейнеров (MCS isolation).

**AppArmor path-based ≠ слабый.** Path-based подход имеет реальную слабость (hard links, bind mounts), но для большинства серверных сценариев (confined daemons) этого достаточно. Docker на Ubuntu использует AppArmor-профили, и они эффективно ограничивают контейнеры.

**Capabilities vs полный root.** На практике многие приложения запрашивают CAP_SYS_ADMIN, который даёт почти полный root. Это «мусорная capability» — разделение неполное. Работа по разделению CAP_SYS_ADMIN на более гранулярные capabilities продолжается, но медленно из-за backward compatibility.

**seccomp overhead.** Каждый системный вызов проходит через BPF-фильтр. Overhead зависит от сложности фильтра: для дефолтного Docker-профиля (~44 rules) — менее 1%. Для сложных кастомных профилей может быть заметнее. В contrast, LSM hooks имеют фиксированный overhead (вызов функции на каждом hook point), который может достигать единиц процентов для SELinux с полной политикой.

**io_uring как attack surface.** io_uring — высокопроизводительный I/O-интерфейс ядра, добавленный в 5.1. Из-за сложности реализации он стал постоянным источником уязвимостей (десятки CVE). Google и другие крупные пользователи рекомендуют отключать io_uring на серверах, где он не нужен: `kernel.io_uring_disabled=2`.

**LSM BPF** (с ядра 5.7) — новое направление: eBPF-программы, подключаемые к LSM hooks, позволяющие реализовать кастомные MAC-политики без написания kernel module. Более гибко, чем SELinux/AppArmor, с меньшим overhead (~15% в worst case vs ~110% для AppArmor в некоторых бенчмарках). В production используется в Cilium, Android, ChromeOS.

## Сравнение с FreeBSD

**MAC Framework.** FreeBSD имеет собственный MAC framework (аналог LSM), с модулями: mac_bsdextended (файловый firewall на правилах), mac_portacl (привязка к портам без root), mac_seeotheruids (скрытие процессов других пользователей). Менее развит, чем SELinux/AppArmor — нет эквивалента targeted policy для каждого сервиса. Реальное использование MAC в FreeBSD значительно реже, чем SELinux в RHEL.

**Securelevel.** kern.securelevel — глобальный уровень безопасности, который можно только повышать: на уровне 1 запрещается загрузка модулей и запись в /dev/mem, на уровне 2 — изменение правил firewall и запись в блочные устройства. Простой и эффективный механизм для production-серверов. В Linux аналог — Lockdown LSM (integrity/confidentiality modes), появившийся значительно позже (ядро 5.4).

**Capsicum.** Capability-based sandbox framework — процесс входит в capability mode и теряет доступ к глобальному namespace (файловые пути, сетевые адреса). Доступ только через явно переданные file descriptors с ограниченными правами. Концептуально чище, чем seccomp (который фильтрует syscalls, а не объекты). В Linux аналогом является Landlock + seccomp, но capsicum элегантнее архитектурно.

**chflags.** FreeBSD файловые флаги (schg — system immutable, sunlnk — undeletable) — в сочетании с securelevel делают файлы неизменяемыми даже для root. В Linux аналог — chattr +i (immutable), но без securelevel root может снять этот флаг.

**blacklistd.** FreeBSD-аналог fail2ban, встроенный в base system. Интегрирован с sshd, ftpd, smtpd — при N неудачных попыток IP автоматически блокируется через PF. Проще и надёжнее, чем парсинг логов fail2ban.

## Источники

- [Linux Security Modules — kernel.org](https://www.kernel.org/doc/html/latest/admin-guide/LSM/index.html) — документация LSM
- [SELinux User's and Administrator's Guide — Red Hat](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/using_selinux/) — практическое руководство
- [AppArmor — Ubuntu Wiki](https://wiki.ubuntu.com/AppArmor) — документация AppArmor
- [Landlock — kernel.org](https://docs.kernel.org/userspace-api/landlock.html) — API Landlock
- [seccomp — kernel.org](https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html) — документация seccomp
- [capabilities(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html) — man page по capabilities
- [Linux Audit — Red Hat](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/security_hardening/auditing-the-system_security-hardening) — настройка auditd
- [LSMs vs seccomp — Star Lab](https://www.starlab.io/blog/linux-security-modules-lsms-vs-secure-computing-mode-seccomp) — сравнение
- [Practical Guide to LSM BPF](https://www.ebpf.top/en/post/lsm_bpf_intro/) — eBPF-based security
- FreeBSD Handbook: [MAC](https://docs.freebsd.org/en/books/handbook/mac/) — для сравнения

---

## Связанные заметки

- [Linux — контейнеризация](./linux-containerization.md) — namespaces и seccomp как средства изоляции
- [Linux — сеть: стек, конфигурация, firewall](./linux-networking.md) — nftables и фильтрация трафика
- [sudo, doas и sudo-rs](./sudo-vs-doas.md) — повышение привилегий: механизм setuid и сравнение реализаций
- [FreeBSD — безопасность](./freebsd-security-hardening.md) — MAC-фреймворк и securelevel, для сравнения
- [Linux — сводный cheatsheet](./linux-map-cheatsheet.md) — быстрая справка по security-командам
- [Обратный прокси и TLS: nginx vs Caddy](./reverse-proxy-tls.md) — публичная точка входа и доверие к заголовкам
- [OpenVPN против WireGuard](./openvpn-vs-wireguard.md) — VPN-демон в модели защиты хоста: от чьего имени он работает и что открывает наружу
- [SSH углублённо](./ssh-advanced.md) — та же технология как инструмент: `~/.ssh/config`, бастионы, сертификаты, ограниченные ключи
- [Linux — пользователи, группы, PAM и systemd-logind](./linux-users-pam.md) — модель учётных записей и стек PAM, на который опираются эти механизмы
- [Linux — время и синхронизация](./linux-time-sync.md) — расхождение часов ломает TOTP, Kerberos и проверку сроков сертификатов
- [Эксплуатация локальных ИИ-сервисов](./ai-services-operations.md) — песочница для сервиса, которому нужен доступ к видеокарте: `PrivateDevices=` здесь неприменим
- [Карта памяти ядра: половины, прямое отображение, KASLR](./os-kernel-memory-map.md) — механизм под теми же настройками: KPTI, KASLR и права на секции ядра изнутри
- [Вход в ядро и переключение контекста](./os-kernel-entry.md) — механизм под контрмерами: граница доверия ядра, SMEP/SMAP и цена спекулятивных заплат на каждом переходе
