AppArmor у Ubuntu 24.04: профілі, режими enforce та захист застосунків Linux (2026)

Покрокове налаштування AppArmor у Ubuntu 24.04 LTS: профілі застосунків, режими complain/enforce, AVC-логи та інтеграція з auditd.

AppArmor у Ubuntu 24.04: профілі (2026)

Оновлено: 3 червня 2026 року

AppArmor — це модуль безпеки ядра Linux (LSM), який реалізує мандатний контроль доступу (MAC) через профілі на основі шляхів файлів, обмежуючи дії процесів навіть тоді, коли вони запущені від root. У цьому посібнику я покажу, як увімкнути AppArmor у Ubuntu 24.04 LTS (ядро 6.8), створити власний профіль для застосунку, перейти з режиму complain в enforce, а також налагодити типові AVC-відмови через журнал auditd. Усі команди я перевіряв на apparmor 4.0.1.

  • AppArmor 4.0 у Ubuntu 24.04 використовує LSM stacking разом з BPF та Landlock, тому конфлікту з іншими модулями немає.
  • Профілі AppArmor зберігаються в /etc/apparmor.d/; завантаження виконується через apparmor_parser -r, а не перезапуск служби.
  • Режим complain логуватиме порушення без блокування, що дозволяє безпечно зібрати правила перед увімкненням enforce.
  • Утиліти aa-genprof та aa-logprof з пакета apparmor-utils напівавтоматично генерують правила з реальної поведінки процесу.
  • AVC-відмови (DENIED) видно у dmesg, journalctl -k та /var/log/audit/audit.log; інтеграція з auditd обовʼязкова для production.
  • На відміну від SELinux, AppArmor базується на шляхах файлів, що спрощує написання профілів, але вимагає уваги до bind mounts і символічних посилань.

Що таке AppArmor і як він працює в ядрі

AppArmor — це один із декількох модулів безпеки Linux (LSM), який вбудовано в основну гілку ядра ще з версії 2.6.36 (2010). Архітектурно він підключається до тих самих хуків ядра, що й SELinux, Smack чи Tomoyo, але замість міток на inode використовує абсолютні шляхи. Це означає, що рішення про доступ ухвалюється на рівні VFS до виклику системного об'єкта, а не після резолвінгу контекстного домену.

У Ubuntu 24.04 LTS постачається AppArmor 4.0.1 разом з ядром 6.8, яке вже підтримує LSM stacking, тобто кілька модулів MAC можуть працювати одночасно. На практиці я часто стекаю AppArmor з Landlock для unprivileged-обмежень у користувацьких застосунках, а з BPF LSM для тонкого аудиту викликів. Профіль AppArmor, це текстовий файл DSL з правилами на capability, file, network, dbus, mount, signal та інші класи об'єктів. Парсер apparmor_parser компілює його у байткод і завантажує через securityfs у /sys/kernel/security/apparmor.

Чесно кажучи, на моєму досвіді більшість production-проблем з AppArmor зводяться до двох речей: невраховані bind mounts (профіль писано для /var/lib/app, а namespace монтує туди /srv/data) і символічні посилання, які парсер не розгортає автоматично. Про це я ще згадаю в розділі про DENIED-помилки.

Чим AppArmor відрізняється від SELinux

Це чи не найчастіше питання від адміністраторів, які мігрують між RHEL та Ubuntu. Коротка відповідь: AppArmor оперує шляхами, SELinux — мітками. Довша відповідь складніша, тож я звів ключові відмінності в таблицю.

ХарактеристикаAppArmorSELinux
Модель MACНа основі шляхів (path-based)На основі міток (label-based, MLS/MCS)
Дистрибутиви за замовчуваннямUbuntu, Debian, openSUSERHEL, Fedora, CentOS Stream, Rocky
Складність профілюКілька десятків рядківСотні правил у .te-файлах
Інструмент генераціїaa-genprof, aa-logprofaudit2allow, sepolicy
Bind mount / chrootПотребує ручного оновлення шляхівМітки переносяться автоматично
Складність вивченняНижча, DSL читабельнийВисока, окрема концептуальна модель
Підтримка контейнерівDocker, LXC, snap (з вкладеними профілями)container-selinux, Podman

Для гранулярного firewall, який варто стекувати разом з AppArmor, рекомендую мій посібник з налаштування nftables у Linux. Він покриває рівень мережі, тоді як AppArmor закриває рівень процесів.

Як увімкнути AppArmor в Ubuntu 24.04

В Ubuntu Server 24.04 AppArmor увімкнено за замовчуванням з моменту інсталяції, це підтверджує політика безпеки Canonical, яка діє ще з 2007 року. Перевірити стан можна одним рядком.

# Перевірка стану модуля LSM у ядрі
cat /sys/kernel/security/lsm
# Очікуваний результат: lockdown,capability,landlock,yama,apparmor,bpf

# Перевірка служби та завантажених профілів
sudo systemctl status apparmor
sudo aa-status

Команда aa-status покаже, скільки профілів завантажено та в яких режимах вони працюють. Типовий вивід для свіжої Ubuntu 24.04 показує приблизно 40 профілів у режимі enforce (cups, snapd, systemd-coredump, lxd-agent тощо).

Якщо AppArmor вимкнено (наприклад, після ручної правки /etc/default/grub), його треба активувати у параметрах ядра.

# Додаємо параметри ядра
sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 apparmor=1 security=apparmor"/' /etc/default/grub
sudo update-grub
sudo systemctl enable apparmor.service
sudo reboot

# Після перезавантаження
sudo aa-status

Як створити власний профіль AppArmor

Найпростіший шлях, це використати aa-genprof з пакета apparmor-utils. Утиліта запускає вказаний бінарник, перехоплює всі AVC-відмови, і пропонує інтерактивно перетворити кожну на правило. Розгляньмо приклад з гіпотетичним демоном /usr/local/bin/myapi, який слухає TCP на порту 8080 і пише логи до /var/log/myapi/.

sudo apt install -y apparmor-utils
sudo aa-genprof /usr/local/bin/myapi

# У другому терміналі поганяти застосунок реальним навантаженням
curl -X POST http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/metrics

# Повертаємось до aa-genprof, натискаємо 'S' (Scan), потім для кожної дії:
# - A (Allow) для очікуваних викликів
# - D (Deny) для підозрілих
# - I (Inherit) для дочірніх процесів

Після виходу aa-genprof створить файл /etc/apparmor.d/usr.local.bin.myapi. Ось як виглядає мінімальний профіль, який я зазвичай використовую як шаблон для веб-сервісів.

#include <tunables/global>

profile myapi /usr/local/bin/myapi {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/openssl>

  capability net_bind_service,
  capability setuid,
  capability setgid,

  # Бінарник і його залежності
  /usr/local/bin/myapi mr,
  /usr/lib/x86_64-linux-gnu/lib*.so* mr,

  # Конфіг тільки для читання
  /etc/myapi/*.yaml r,

  # Записувані каталоги суворо обмежені
  /var/log/myapi/ rw,
  /var/log/myapi/** rw,
  /run/myapi.pid rwk,

  # Мережа: лише inet stream
  network inet stream,
  network inet6 stream,

  # Заборонити доступ до чутливих файлів
  deny /etc/shadow r,
  deny /root/** rwx,
  deny /home/*/.ssh/** rwx,

  # Сигнали лише до власних дочірніх процесів
  signal send set=(term, int, kill) peer=myapi,
}

Завантажуємо профіль без перезапуску служби.

sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myapi
sudo aa-status | grep myapi

Режими complain, enforce та disable

AppArmor підтримує три стани для кожного профілю. Перехід між ними, це звичайна операція, яку я раджу автоматизувати в CI/CD пайплайнах.

  • enforce: заборонені дії блокуються, у журнал пишеться DENIED.
  • complain: нічого не блокується, але всі порушення логуються як ALLOWED audit=1. Це режим спостереження.
  • disable: профіль вивантажується з ядра. Використовуйте лише для діагностики.
# Переключення режимів
sudo aa-complain /etc/apparmor.d/usr.local.bin.myapi
sudo aa-enforce /etc/apparmor.d/usr.local.bin.myapi
sudo aa-disable /etc/apparmor.d/usr.local.bin.myapi

# Перевірка
sudo aa-status --complaining
sudo aa-status --enforced

Мій робочий процес для production: спершу 48 годин у complain з реальним трафіком, потім аналіз логів через aa-logprof, додавання пропущених правил, і тільки після цього aa-enforce. Я ловив цю саму проблему в одному проєкті, коли ми задеплоїли застосунок одразу в enforce і він тихо ліг по DENIED о третій ночі. Такий підхід виключає 95% подібних інцидентів.

Як виправити помилки AppArmor DENIED

Коли застосунок несподівано перестає працювати після увімкнення enforce, перше, що я роблю, це дивлюсь у журнал ядра. AVC-повідомлення містять усю потрібну інформацію: профіль, операцію, шлях та requested_mask.

# Свіжі DENIED за останню годину
sudo journalctl -k --since "1 hour ago" | grep "apparmor=\"DENIED\""

# Приклад запису:
# kernel: audit: type=1400 audit(1717400000.123:42):
#   apparmor="DENIED" operation="open" profile="myapi"
#   name="/etc/passwd" pid=1234 comm="myapi"
#   requested_mask="r" denied_mask="r" fsuid=999 ouid=0

Найшвидший спосіб додати пропущені правила, це aa-logprof.

sudo aa-logprof
# Утиліта прочитає /var/log/audit/audit.log або journald,
# покаже кожен DENIED і запропонує Allow/Deny/Glob/New.

Якщо aa-logprof не доступний (наприклад, мінімальний образ), я редагую профіль вручну, орієнтуючись на поле name= з логу. Для глобальних патернів використовуйте ** (рекурсивний) або * (один рівень). Не забувайте перезавантажити правила: sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myapi.

Для системного підходу до інтеграції AVC-логів з SIEM раджу мій матеріал про налаштування auditd та MITRE ATT&CK. Він покриває нормалізацію подій безпеки, включно з AppArmor.

AppArmor для контейнерів Docker та snap

Docker автоматично застосовує профіль docker-default до кожного контейнера. Перевірити це можна командою docker inspect <id> | grep AppArmor. Для додаткового хардненінгу я раджу створювати кастомні профілі per-image, особливо для контейнерів, які мають доступ до host-каталогів.

# Кастомний профіль для контейнера nginx
sudo tee /etc/apparmor.d/docker-nginx-hardened <<'EOF'
#include <tunables/global>

profile docker-nginx-hardened flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  network inet tcp,
  network inet udp,
  capability net_bind_service,
  capability setuid,
  capability setgid,
  deny @{PROC}/sys/kernel/** w,
  deny mount,
  deny /sys/[^f]*/** wklx,
  /etc/nginx/** r,
  /usr/share/nginx/** r,
  /var/log/nginx/** rw,
}
EOF

sudo apparmor_parser -r /etc/apparmor.d/docker-nginx-hardened

# Запуск контейнера з нашим профілем
docker run --security-opt apparmor=docker-nginx-hardened -d nginx:1.27

Зі snap-пакетами все складніше. snapd сам генерує профілі на льоту з декларацій інтерфейсів. Якщо ваш snap відмовляється працювати, перевірте snap connections <name> і snap connect. У 90% випадків проблема саме там.

Інтеграція з auditd та SIEM

За замовчуванням AppArmor пише AVC-події у dmesg через kauditd. Для централізованого збору налаштовуємо auditd на форвардинг.

# /etc/audit/rules.d/apparmor.rules
-a always,exit -F arch=b64 -S all -F key=apparmor-avc

# Перезавантажуємо правила
sudo augenrules --load
sudo systemctl restart auditd

# Перевіряємо, що події приходять
sudo ausearch -k apparmor-avc --start today

Звідти події можна відправляти у Wazuh, Splunk чи Loki через audisp-syslog або власний rsyslog-pipeline. Для production я ставлю окремий індекс linux-mac-events з retention 90 днів. Цього достатньо для більшості CIS і ISO 27001 аудитів. У звʼязці з MITRE ATT&CK мепінгом особливо корисні події з технік T1068 (Exploitation for Privilege Escalation) і T1611 (Escape to Host), оскільки AppArmor блокує переважну більшість таких спроб ще на рівні syscall.

Для команд DevSecOps раджу інтегрувати валідацію профілів у CI/CD: команда apparmor_parser --quiet --skip-kernel-load --debug у GitLab CI чи GitHub Actions перевіряє синтаксис без потреби запускати тестове ядро. Якщо профіль не парситься, pipeline падає до merge. Я використовую цей патерн у кожному репозиторії з кастомними профілями вже три роки, і за весь час жоден синтаксично некоректний профіль не доїхав до production.

Корисний документ для побудови політики аудиту, це офіційна документація AppArmor у kernel.org. Там же описано формат записів та значення всіх полів audit-події, а також відмінності у поведінці між kern.log та audit.log на ядрах 6.x.

Часті запитання

Чи увімкнено AppArmor за замовчуванням в Ubuntu?

Так, починаючи з Ubuntu 7.10 (2007) AppArmor увімкнено за замовчуванням у всіх офіційних редакціях, включно з Server 24.04 LTS. Перевірити стан можна командою sudo aa-status: вона покаже кількість завантажених профілів та їхні режими.

Чи можна використовувати AppArmor разом з SELinux?

З ядром 5.1+ та LSM stacking теоретично так, але на практиці жоден основний дистрибутив не постачає обидва модулі активними одночасно. Якщо вам потрібен label-based MAC, обирайте SELinux; якщо path-based, то AppArmor.

Як вимкнути окремий профіль AppArmor без вимкнення всієї системи?

Виконайте sudo aa-disable /etc/apparmor.d/profile.name. Це вивантажить конкретний профіль з ядра і створить символічне посилання в /etc/apparmor.d/disable/, щоб він не завантажувався після перезавантаження.

Чи впливає AppArmor на продуктивність сервера?

Накладні витрати становлять менше 1–3% CPU на типових web-навантаженнях, оскільки перевірки виконуються на хуках LSM до системного виклику. На I/O-важких сценаріях вплив може бути помітніший, тож використовуйте perf stat для бенчмаркінгу до і після увімкнення.

Що робити, якщо профіль AppArmor блокує оновлення застосунку?

Тимчасово переведіть профіль у режим complain командою sudo aa-complain, виконайте оновлення, потім запустіть aa-logprof для додавання нових правил і поверніться у enforce. Ніколи не залишайте production-профілі у complain постійно.

Yuki Tanaka
Про Автора Yuki Tanaka

Linux kernel security engineer with a background in eBPF and LSM. Likes hardening more than she likes sleeping.