راهنمای عملی AppArmor در اوبونتو ۲۴.۰۴ (۲۰۲۶): ساخت پروفایل و امنسازی برنامهها
ساخت گامبهگام پروفایل AppArmor در اوبونتو ۲۴.۰۴ با aa-genprof، حالت complain، ادغام با Docker، رفع خطاهای رایج و مقایسه عملی با SELinux همراه با کد آماده برای محیط تولید.
AppArmor یک ماژول امنیتی هسته لینوکس (LSM) است که با اعمال پروفایلهای مبتنی بر مسیر فایل، رفتار برنامهها را در سطح کنترل دسترسی اجباری (MAC) محدود میکند و در اوبونتو ۲۴.۰۴ بهصورت پیشفرض فعال است. برخلاف SELinux که بر برچسبگذاری inode تکیه دارد، AppArmor پروفایلها را با نام مطلق مسیر شناسایی میکند؛ همین موضوع نگارش، بازبینی و نگهداری قواعد را برای مدیران سیستم بسیار سادهتر میکند. در این راهنما، از فعالسازی تا ساخت پروفایل سفارشی برای یک سرویس واقعی را با هم مرور میکنیم.
راستش را بخواهید، اولین باری که در یک پروژه تولیدی خواستم پروفایل AppArmor برای یک اسکریپت داخلی بنویسم، بدون aa-genprof ساعتها با ویرایشگر vim کلنجار رفتم. تجربهای که در ادامه میبینید، همان مسیری است که اگر آن روز میدانستم، کارم را در چند دقیقه تمام میکرد.
AppArmor 4.0.1 در اوبونتو ۲۴.۰۴ بهصورت پیشفرض فعال است و از قواعد شرطی، abstractions جدید و پشتیبانی io_uring بهره میبرد.
حالت complain پیش از enforce برای جمعآوری رفتار واقعی برنامه ضروری است و از قفلشدن ناخواسته سرویس جلوگیری میکند.
ابزارهای aa-genprof، aa-logprof و aa-status چرخه توسعه پروفایل را ساده میکنند و بر پایه رخدادهای auditd کار میکنند.
Docker بهصورت پیشفرض پروفایل docker-default را روی کانتینرها اعمال میکند و میتوان پروفایل سفارشی را با پرچم --security-opt بارگذاری کرد.
در مقایسه با SELinux، AppArmor یادگیری سریعتر اما دقت برچسبگذاری کمتری دارد و برای اکثر سرورهای Ubuntu/Debian انتخاب عملیتری است.
ترکیب AppArmor با nftables، seccomp و ممیزی auditd یک لایه دفاعی چندگانه میسازد که یک ابزار بهتنهایی از پس آن برنمیآید.
AppArmor چیست و چگونه کار میکند؟
AppArmor مخفف «Application Armor» است. از سال ۱۹۹۸ توسط Immunix توسعه یافت و اکنون توسط پروژه AppArmor و Canonical نگهداری میشود. این ابزار از چارچوب Linux Security Module (LSM) بهره میبرد تا در هنگام فراخوانیهای سیستمی، تصمیم بگیرد آیا یک پردازش اجازه دسترسی به یک منبع (فایل، سوکت، قابلیت هسته یا mount) را دارد یا خیر. این تصمیم بر پایه فایل متنی «پروفایل» گرفته میشود که برای هر باینری در مسیر /etc/apparmor.d/ ذخیره میگردد.
در نسخه ۴.۰.۱ که همراه با کرنل ۶.۸ اوبونتو ۲۴.۰۴ عرضه شد، چند قابلیت مهم اضافه شده است: پشتیبانی از io_uring برای برنامههای async مدرن، قواعد شرطی if/else، بهبود بازرسی mount و سیستمفایلهای شبکهای. برخلاف تصور رایج، AppArmor «فایروال برنامه» نیست. بلکه یک sandbox سبک است که رفتار مجاز را اعلان میکنید و هر چیز خارج از آن مسدود (deny) یا لاگ (audit) میشود.
هر پروفایل یک نام کامل مسیر (مثلاً /usr/sbin/nginx) دارد و از سه بلوک اصلی تشکیل میشود: includeها برای واردکردن abstractionهای عمومی، capabilityها برای اعطای قابلیتهای خاص هسته، و file rulesی که دسترسی خواندن (r)، نوشتن (w)، اجرا (ix/Px) و پیوند (l) را کنترل میکنند.
تفاوت AppArmor و SELinux چیست؟
هر دو ابزار MAC هستند، اما فلسفه متفاوتی دارند. SELinux از NSA سرچشمه گرفته و بر برچسبگذاری هر inode با یک context امنیتی (مانند system_u:object_r:httpd_t:s0) تکیه دارد. این رویکرد بسیار دقیق است ولی نگهداری آن سخت و منحنی یادگیری آن تند است. AppArmor در مقابل مسیر فایل را کلید میداند: اگر برنامه فایلی را با نام مسیر بگشاید، پروفایل اعمال میشود.
ویژگی
AppArmor 4.0
SELinux 3.7
مدل کنترل دسترسی
مبتنی بر مسیر (path-based)
مبتنی بر برچسب inode
توزیع پیشفرض
Ubuntu، Debian، openSUSE
RHEL، Fedora، Rocky، AlmaLinux
پیچیدگی نگارش پروفایل
پایین (سینتکس شبیه shell)
بالا (نیاز به policy language)
سربار کارایی
کمتر از ۱٪ در بارهای معمول
حدود ۱ تا ۳٪
ابزار یادگیری خودکار
aa-genprof، aa-logprof
audit2allow، sepolgen
پشتیبانی کانتینر
پروفایل پیشفرض Docker/Podman
نوع اختصاصی container_t
ضعف اصلی
ضعف در برابر hard link و bind mount
پیچیدگی و نیاز به relabeling
در عمل، اگر روی خانواده Ubuntu/Debian کار میکنید، AppArmor گزینه طبیعی است. اگر روی RHEL 9 یا AlmaLinux کار میکنید، SELinux ابزار درست است. مقایسه با راهنمای ممیزی امنیتی با Lynis نشان میدهد که Lynis وضعیت هر دو ماژول را ارزیابی میکند و یک نمای سطحبالا از سلامت پیکربندی به شما میدهد.
فعالسازی و بررسی وضعیت در اوبونتو ۲۴.۰۴
در اوبونتو ۲۴.۰۴ سرور، بسته apparmor از پیش نصب و فعال است. برای اطمینان، ابتدا وضعیت سرویس و پروفایلهای بارگذاریشده را بررسی میکنیم:
# بررسی وضعیت سرویس apparmor
sudo systemctl status apparmor
# فهرست کامل پروفایلهای بارگذاریشده
sudo aa-status
# نمونه خروجی apparmor 4.0.1:
# apparmor module is loaded.
# 47 profiles are loaded.
# 35 profiles are in enforce mode.
# 12 profiles are in complain mode.
# 0 profiles are in kill mode.
# 0 profiles are in unconfined mode.
اگر ماژول غیرفعال است، آن را با پارامتر kernel در GRUB روشن کنید:
enforce: هر عملی خارج از قواعد مسدود و در /var/log/audit/audit.log ثبت میشود.
complain: چیزی مسدود نمیشود، اما تخلفها ثبت میگردند. حالت طلایی برای یادگیری رفتار برنامه.
disable: پروفایل بهطور کامل خنثی میشود؛ فقط برای اشکالزدایی موقت توصیه میشود.
kill: تازه در نسخه ۴.۰ افزوده شد. نهتنها مسدود میکند، بلکه پردازش را با SIGKILL میبندد.
جابهجایی بین این حالتها با فرمانهای زیر انجام میشود:
# تغییر یک پروفایل به complain
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
# بازگرداندن به enforce
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
# غیرفعالسازی موقت
sudo aa-disable /etc/apparmor.d/usr.sbin.nginx
# بارگذاری مجدد پس از ویرایش
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
چگونه یک پروفایل AppArmor سفارشی بسازیم؟
فرض کنید یک اسکریپت داخلی به نام /usr/local/bin/report-sync.sh دارید که فقط باید در /var/log/reports/ بنویسد و به https://api.internal.example.com متصل شود. ساخت پروفایل با aa-genprof در چند گام انجام میشود.
گام ۱: شروع نشست یادگیری
sudo aa-genprof /usr/local/bin/report-sync.sh
# در ترمینال دیگر، اسکریپت را اجرا و همه سناریوهای عادی را طی کنید:
sudo -u reportuser /usr/local/bin/report-sync.sh --once
sudo -u reportuser /usr/local/bin/report-sync.sh --retry
# بازگردید و کلید S (Scan) را بزنید تا رخدادها اسکن شوند.
گام ۲: پاسخ به پرسشهای تعاملی
ابزار برای هر دسترسی مشاهدهشده میپرسد: Allow، Deny، یا Inherit. پاسخهای رایج:
A = Allow: اجازه دائم برای این مسیر.
G = Glob: تعمیم به الگویی مثل /var/log/reports/**.
I = Inherit: زیرپردازشها همان پروفایل والد را ادامه دهند.
نمونه پروفایل نهایی. این را میتوانید عیناً بهعنوان الگو استفاده کنید:
abi <abi/4.0>,
include <tunables/global>
profile report-sync /usr/local/bin/report-sync.sh {
include <abstractions/base>
include <abstractions/bash>
include <abstractions/openssl>
include <abstractions/nameservice>
include <abstractions/ssl_certs>
# قابلیتهای هسته مجاز
capability net_bind_service,
# مسیرهای فایل
/usr/local/bin/report-sync.sh r,
/usr/bin/bash ix,
/usr/bin/curl ix,
/usr/bin/jq ix,
# دادههای خواندنی
/etc/report-sync/*.conf r,
/etc/ssl/certs/ca-certificates.crt r,
# لاگ و خروجی
/var/log/reports/** rw,
/var/log/reports/ r,
/tmp/report-sync.*.tmp rw,
# شبکه (فقط TCP خروجی)
network inet stream,
network inet6 stream,
# منع صریح خواندن راز
deny /etc/shadow r,
deny /root/** rwx,
# قواعد شرطی (ویژگی نسخه 4.x)
if not exists /var/log/reports/ {
/var/log/reports/ w,
}
}
گام ۴: بارگذاری و آزمون در حالت complain
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.report-sync.sh
sudo aa-complain /etc/apparmor.d/usr.local.bin.report-sync.sh
# اجرای یک هفته در complain و سپس تحلیل با aa-logprof
sudo aa-logprof
پس از حذف تمام هشدارهای کاذب، پروفایل را به enforce منتقل کنید. اگر روی سرور همزمان از فایروال nftables استفاده میکنید، به راهنمای پیکربندی nftables مراجعه کنید تا این لایههای دفاعی همدیگر را تکمیل کنند.
ادغام AppArmor با کانتینرهای Docker
از زمان Docker Engine 1.13، پروفایل داخلی docker-default بهطور خودکار به هر کانتینر اعمال میشود مگر آنکه با --security-opt "apparmor=unconfined" غیرفعال شود. این پروفایل ۹۵٪ سناریوها را پوشش میدهد، ولی برای سرویسهای حساس باید پروفایل اختصاصی تعریف کنید.
در محیطهای Kubernetes، از field securityContext.appArmorProfile در PodSpec (پشتیبانی رسمی از نسخه ۱.۳۰) برای اعلام همان پروفایل استفاده کنید. برای درک عمیقتر چرخه امنسازی کانتینر، مقاله امنسازی کانتینرهای داکر یک نقشه راه کامل میدهد.
عیبیابی و رفع خطاهای رایج
در ۹۵٪ موارد، خطاهای AppArmor از سه دسته میآیند: مسیر ناشناخته، قابلیت کم، و mount ممنوعه. ابزار اصلی تحلیل، dmesg یا ausearch است:
# مشاهده تمام رخدادهای DENIED در ساعت گذشته
sudo ausearch -m AVC,USER_AVC -ts recent | aa-decode
# نمونه رخداد رد شده:
# type=AVC apparmor="DENIED" operation="open" profile="report-sync"
# name="/etc/secret.env" pid=48212 comm="cat"
# requested_mask="r" denied_mask="r" fsuid=1002
برای اضافهکردن قاعده جدید بدون بازنویسی کل پروفایل، از aa-logprof استفاده کنید:
sudo aa-logprof
# ابزار بهطور تعاملی هر تخلف را نشان میدهد و
# پیشنهاد Allow/Deny/Glob میدهد و پروفایل را بهروزرسانی میکند.
سه خطای بسیار رایج و راهحل آنها:
DENIED capability net_admin: باید capability net_admin, را به پروفایل بیفزایید. اگر برنامه فقط برای bind به پورت پایینتر از ۱۰۲۴ نیاز دارد، از capability net_bind_service, استفاده کنید که محدودتر است.
DENIED "exec": باینری هدف نیاز به transition دارد. از ix (inherit)، Px (پروفایل خود)، یا Ux (unconfined) در انتهای مسیر استفاده کنید؛ هرگز Ux را برای کد ناامن به کار نبرید.
Profile not loading after edit: خطای سینتکس. با sudo apparmor_parser -Q /etc/apparmor.d/<file> پیش از بارگذاری، پروفایل را اعتبارسنجی کنید.
بهترین شیوهها برای محیط تولید
در استقرارهای بزرگ، اعمال دستی AppArmor عملی نیست. تیمهای DevSecOps معمولاً پروفایلها را در قالب Infrastructure-as-Code نگه میدارند و از طریق Ansible یا Puppet توزیع میکنند. یک سیاست پخته باید موارد زیر را رعایت کند:
نسخهگذاری پروفایلها در Git و اعمال با pull-based configuration management؛ هرگز مستقیماً روی سرور تولید ویرایش نکنید.
چرخه استقرار complain → enforce: هر پروفایل جدید حداقل ۷۲ ساعت در complain در محیط staging میماند تا لبههای استفاده کشف شوند.
مانیتورینگ رخدادهای DENIED با ارسال audit.log به SIEM (مانند Wazuh یا Splunk). هر پیک ناگهانی میتواند نشانه سازش باشد.
پاکسازی پروفایلهای استفادهنشده: پروفایل بیاستفاده امنیت اضافه نمیکند، ولی سطح حمله ابزار را افزایش میدهد.
ترکیب با seccomp و capabilities: AppArmor لایه دوم است؛ لایه اول همیشه حذف قابلیتهای غیرضروری از capabilities(7) و سیاست seccomp سفتگیرانه است.
برای تیمهایی که بهدنبال چارچوب ممیزی هستند، ترکیب پروفایلهای AppArmor با اسکن دورهای Lynis و پلاگینهای ARF/SCAP باعث میشود گزارشهای انطباق CIS Benchmark Ubuntu 24.04 با کمترین دستکاری قبول شوند. اگر با SIEM متنباز کار میکنید، راهنمای Wazuh نشان میدهد چگونه رخدادهای AppArmor را به قوانین هشدار تبدیل کنید.
در نهایت، به یاد داشته باشید که AppArmor «آخرین خط دفاع» نیست بلکه یک لایه از یک استراتژی دفاع در عمق است. طبق مستندات CIS Benchmark اوبونتو ۲۴.۰۴، همراه با AppArmor باید حداقل امتیاز پیکربندی kernel، فایروال، SSH و ممیزی auditd نیز بهطور همزمان بهبود یابد.
پرسشهای متداول
آیا AppArmor کارایی سیستم را کاهش میدهد؟
خیر، سربار AppArmor در بارهای معمول کمتر از ۱٪ است و در بنچمارکهای Canonical روی kernel 6.8 عملاً قابل اندازهگیری نیست. تنها در بارهای بسیار I/O-محور با میلیونها فراخوانی open() در ثانیه ممکن است چند درصد اضافه ببینید.
آیا میتوان AppArmor و SELinux را همزمان استفاده کرد؟
نه بهعنوان LSM اصلی. کرنل لینوکس امکان بارگذاری چند LSM را با پرچم lsm= فراهم میکند، ولی در عمل توزیعها یکی را انتخاب میکنند. Ubuntu از AppArmor و RHEL از SELinux استفاده میکند و تلاش برای مخلوطکردن آنها معمولاً به پروفایلهای ناسازگار میانجامد.
چگونه از قفلشدن (lockout) هنگام تنظیم اشتباه پروفایل جلوگیری کنم؟
همیشه پروفایل جدید را ابتدا در حالت complain بگذارید و پس از ۷۲ ساعت لاگگیری، آن را به enforce منتقل کنید. برای اورژانس، پارامتر kernel apparmor=0 در گراب موقتاً همه پروفایلها را غیرفعال میکند.
آیا AppArmor از کانتینرهای rootless پشتیبانی میکند؟
بله. Podman و Docker rootless میتوانند پروفایل کاربر-فضا را با --security-opt اعمال کنند، مشروط بر آنکه پروفایل مورد نظر پیشتر توسط root در هسته بارگذاری شده باشد (بارگذاری پروفایل همچنان امتیاز root میخواهد).
تفاوت ix، Px و Ux در قواعد اجرا چیست؟
ix (inherit exec) پروفایل والد را ادامه میدهد. Px باعث میشود فرزند پروفایل مختص خود را بارگذاری کند و Ux کنترل را کاملاً برمیدارد و فرزند unconfined اجرا میشود. استفاده از Ux فقط برای ابزارهای مورد اعتماد سیستم پیشنهاد میشود.