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 — мітками. Довша відповідь складніша, тож я звів ключові відмінності в таблицю.
Характеристика
AppArmor
SELinux
Модель MAC
На основі шляхів (path-based)
На основі міток (label-based, MLS/MCS)
Дистрибутиви за замовчуванням
Ubuntu, Debian, openSUSE
RHEL, Fedora, CentOS Stream, Rocky
Складність профілю
Кілька десятків рядків
Сотні правил у .te-файлах
Інструмент генерації
aa-genprof, aa-logprof
audit2allow, 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,
}
Мій робочий процес для production: спершу 48 годин у complain з реальним трафіком, потім аналіз логів через aa-logprof, додавання пропущених правил, і тільки після цього aa-enforce. Я ловив цю саму проблему в одному проєкті, коли ми задеплоїли застосунок одразу в enforce і він тихо ліг по DENIED о третій ночі. Такий підхід виключає 95% подібних інцидентів.
Як виправити помилки AppArmor DENIED
Коли застосунок несподівано перестає працювати після увімкнення enforce, перше, що я роблю, це дивлюсь у журнал ядра. AVC-повідомлення містять усю потрібну інформацію: профіль, операцію, шлях та requested_mask.
Найшвидший спосіб додати пропущені правила, це 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-каталогів.
Зі 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 постійно.