دليل AppArmor 2026: كتابة وفرض ملفات التعريف على Ubuntu وDebian

دليل عملي 2026 لكتابة ملفات تعريف AppArmor وفرضها على Ubuntu 24.04 وDebian 13، مع أمثلة لـ Nginx وDocker وSnap وتشخيص حالات الرفض.

دليل AppArmor 2026: Ubuntu وDebian

آخر تحديث: 18 يونيو 2026

AppArmor هو نظام تحكم إلزامي بالوصول (MAC) مبني على إطار وحدات أمان لينكس (LSM)، يقيِّد ما يستطيع كل برنامج فعله عبر ملفات تعريف نصية تُحدِّد المسارات المسموح بقراءتها وكتابتها وتنفيذها والقدرات (capabilities) والشبكات. منذ الإصدار 4.0 الصادر في مارس 2024، والمدمج في نواة لينكس 6.6 فما فوق، أصبح AppArmor يدعم وسوم XAttr للملفات المؤقتة وأنماط رفض شبكية أدق. هذا الدليل يشرح كيفية كتابة ملفات تعريف فعّالة على Ubuntu 24.04 وDebian 13 وفرضها على خدمات الإنتاج دون كسرها.

  • AppArmor 4.0 يضيف وسوم XAttr ومُحدِّدات mqueue وio_uring، ومدمج افتراضياً في Ubuntu 24.04 LTS وDebian 13 "Trixie".
  • الفرق الجوهري عن SELinux أن AppArmor يقيِّد عبر المسارات (path-based) لا التسميات (labels)، ما يجعله أسهل في التبني لكنه أقل صرامة في بعض السيناريوهات.
  • أداة aa-genprof تنشئ ملف تعريف بصلاحيات دنيا تلقائياً من خلال مراقبة سجلات auditd أثناء تشغيل التطبيق.
  • وضع complain يسجِّل الانتهاكات دون منعها، فاستخدمه لمدة 24–72 ساعة قبل التحويل إلى enforce في الإنتاج.
  • أوامر aa-status وjournalctl -k _TRANSPORT=audit هما أداتك الأساسية لتشخيص حالات الرفض.
  • ملفات التعريف موجودة في /etc/apparmor.d/ وتُعاد قراءتها بـ apparmor_parser -r.

ما هو AppArmor وكيف يعمل في نواة لينكس؟

AppArmor هو وحدة أمان لينكس (Linux Security Module – LSM) تنفِّذ التحكم الإلزامي بالوصول (Mandatory Access Control) بالاعتماد على مسارات الملفات في النظام. حين يحاول عمليّةٌ ما فتح ملف أو فتح مأخذ شبكة أو طلب قدرة (capability) معيّنة، يتدخّل خطّاف LSM في الكيرنل ويستشير ملف تعريف العملية. إذا كان الفعل مسموحاً صراحةً سُمح به؛ وإلا رُفض ودُوِّن في سجل auditd. هذا النموذج يختلف جوهرياً عن التحكم التقديري بالوصول (DAC) القائم على المالك والمجموعة وقناع الصلاحيات.

بدءاً من النواة 6.6، يضع AppArmor خطاطيف على عمليات mount وunmount وpivot_root وعمليات io_uring الجديدة، وهي سطح هجوم كان مكشوفاً سابقاً في إصدارات 5.x. في إصدار 4.0، أُضيف دعم وسوم XAttr (الموثَّق في ملاحظات إصدار AppArmor 4.0) مما يسمح بربط ملفات تعريف بملفات مؤقتة في /tmp دون الاعتماد على المسار وحده. بنية البرنامج تتكون من ثلاث طبقات: نواة LSM، وحزمة apparmor في فضاء المستخدم التي تحوي المحلِّل apparmor_parser، ومكتبات Python للأدوات المساعدة مثل aa-genprof.

كل ملف تعريف يصف عمليةً واحدة عبر تطابق المسار التنفيذي. مثلاً ملف تعريف /usr/sbin/nginx يُطبَّق آلياً على كل عملية تُنفَّذ من ذلك المسار. عند استدعاء برنامج فرعي عبر exec() يمكن أن ينتقل إلى ملف تعريف فرعي أو يرث الحالي عبر قواعد Px أو Cx أو ix. هذا التركيب الهرمي ضروري لتقييد عمليات مثل Nginx التي تستدعي مفسِّر PHP-FPM.

AppArmor مقابل SELinux: أيهما تختار في 2026؟

اختر AppArmor إن كان مديرو نظامك يأتون من خلفية Debian/Ubuntu ويفضّلون منحنى تعلّم أقصر، واختر SELinux إن كنت تشغِّل أحمالاً عالية الحساسية تتطلّب تصنيفات أمنية صارمة (مثل امتثال FIPS أو Common Criteria) أو تستخدم RHEL/Fedora/Rocky كأساس. الفرق التقني الجوهري أن AppArmor يفرض القواعد على مسارات نظام الملفات بينما SELinux يفرضها على تسميات (labels) تُخزَّن كـ XAttr لكل inode، لذلك إعادة تسمية ملف لا تُغيِّر سياسة SELinux بل تُغيِّر سياسة AppArmor.

المعيارAppArmor 4.0SELinux (kernel 6.x)
نموذج السياسةقائم على المسار (path-based)قائم على التسميات (label-based)
صيغة القواعدنصّية قريبة من شِل، مقروءةوحدات .te وفئات ودوال (منحنى تعلّم حادّ)
التوزيعات الافتراضيةUbuntu، Debian، openSUSE، Arch (اختياري)RHEL، Rocky، AlmaLinux، Fedora، CentOS Stream
التكامل مع الحاوياتملف تعريف Docker افتراضي، دعم Kubernetes عبر securityContextدعم أعمق عبر container-selinux وتسميات تلقائية
أداة توليد السياساتaa-genprof، aa-logprofaudit2allow، sepolicy generate
متطلبات XAttr في نظام الملفاتاختياري (للتعقُّب فقط)إلزامي على كل inode
التتبّع والتشخيصسجلات auditd واضحة بالعربية للأسبابيتطلّب فهم بنية الـ AVC أولاً

من تجربتي في كتابة وحدات LSM، أرى أن AppArmor يكفي لـ 80% من حالات الإنتاج المعتادة (خوادم ويب، قواعد بيانات، خدمات microservices)، بينما تظلّ SELinux الخيار الأمثل حين تحتاج تعدّد المستويات (multi-level security) أو حين توفِّر منظومتك العتادية تكامل TPM/IMA. توثيق AppArmor في kernel.org يشرح بالتفصيل تكامل LSM stacking الذي يسمح بتشغيل AppArmor إلى جانب Yama وLandlock في الوقت ذاته منذ النواة 5.1.

تثبيت AppArmor وتفعيله على Ubuntu 24.04 وDebian 13

في Ubuntu 24.04 LTS "Noble Numbat" وDebian 13 "Trixie" يكون AppArmor مفعَّلاً بالكامل تلقائياً مع ملفات تعريف افتراضية لحوالي 50 خدمة. ومع ذلك، أنصح بالتحقق من الحالة وتثبيت حزم الأدوات المساعدة قبل البدء بكتابة سياسات مخصّصة.

# التحقق من حالة AppArmor والكيرنل
sudo aa-status

# يفترض أن يظهر:
# apparmor module is loaded.
# 52 profiles are loaded.
# 48 profiles are in enforce mode.
# 4 profiles are in complain mode.

# تثبيت الأدوات المساعدة (تتضمن aa-genprof, aa-logprof, aa-disable)
sudo apt update
sudo apt install -y apparmor-utils apparmor-profiles apparmor-profiles-extra

# التحقق من تمرير معامل الكيرنل
cat /proc/cmdline | grep -o 'apparmor=[01]'
# إن لم يظهر شيء فالافتراضي = 1 (مفعّل)

# قائمة ملفات التعريف المحمَّلة في الذاكرة
sudo aa-status --profiled

إن كنت تعمل على نواة مُجمَّعة يدوياً، تأكَّد من تفعيل الخيارات CONFIG_SECURITY_APPARMOR=y، CONFIG_SECURITY_APPARMOR_HASH=y، وCONFIG_DEFAULT_SECURITY_APPARMOR=y في ملف .config. لتمكين AppArmor افتراضياً عند الإقلاع، أضف apparmor=1 security=apparmor إلى GRUB_CMDLINE_LINUX_DEFAULT في /etc/default/grub ثم نفِّذ sudo update-grub.

كتابة أول ملف تعريف AppArmor يدوياً

ملفات التعريف تُخزَّن في /etc/apparmor.d/ وتُسمَّى عادةً بمسار البرنامج مع استبدال / بـ . (مثلاً usr.sbin.nginx). الصيغة بسيطة مقصودة: ترويسة بالمسار التنفيذي، ثم كتلة قواعد بين أقواس معقوفة. لنبدأ بمثال عملي لتقييد سكربت Python بسيط يقرأ من /etc/myapp ويكتب في /var/log/myapp.log.

# /etc/apparmor.d/usr.local.bin.myapp
#include <tunables/global>

/usr/local/bin/myapp {
  #include <abstractions/base>
  #include <abstractions/python>

  # الاستيرادات الأساسية
  /usr/bin/python3 ix,
  /usr/local/bin/myapp r,

  # الإعدادات والسجلات
  /etc/myapp/ r,
  /etc/myapp/** r,
  /var/log/myapp.log rw,
  /var/log/myapp.log.* rw,

  # القدرات اللازمة
  capability dac_read_search,
  capability setuid,

  # شبكة TCP خارجة فقط
  network inet stream,
  network inet6 stream,

  # رفض كل شيء آخر صراحةً (تأكيد defensive)
  deny /home/** rwx,
  deny /root/** rwx,
  deny capability sys_admin,
  deny capability sys_module,
}

الحقول الأساسية في القواعد: r للقراءة، w للكتابة، x للتنفيذ (مع لاحقة تحدد التحوّل: ix = inherit, Px = profile transition, Ux = unconfined)، m لمَطّ الذاكرة القابلة للتنفيذ، l للروابط. علامة ** تطابق أي مسار متعدّد المستويات، بينما * تطابق مستوى واحداً فقط، وهذا التفريق سبب شائع لأخطاء "لماذا قاعدتي لا تعمل؟". بعد الحفظ، حمّل الملف:

sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myapp
sudo aa-enforce /etc/apparmor.d/usr.local.bin.myapp

# تحقق من أن العملية القادمة ستُقيَّد
sudo aa-status | grep myapp

توليد ملفات التعريف باستخدام aa-genprof وaa-logprof

كتابة ملفات التعريف يدوياً مرهقة للتطبيقات الكبيرة. الحل العملي هو aa-genprof الذي يضع البرنامج في وضع complain ويراقب سجلاته أثناء التشغيل الطبيعي، ثم يسألك تفاعلياً عن كل وصول مكتشَف لتقرّر السماح أو الرفض. الأداة مدمجة في apparmor-utils وتعتمد على auditd الذي يجب أن يكون مفعَّلاً.

# تثبيت auditd إن لم يكن موجوداً
sudo apt install -y auditd

# بدء توليد ملف تعريف لتطبيق
sudo aa-genprof /usr/local/bin/myapp

# في نافذة أخرى: شغِّل التطبيق ومارس كل وظائفه
# (طلبات HTTP، قراءة من قاعدة بيانات، إلخ)
/usr/local/bin/myapp --serve

# عُد إلى نافذة aa-genprof واضغط 'S' لمسح الأحداث
# لكل حدث، الخيارات الرئيسية:
# A = السماح بهذا الوصول
# D = الرفض الصريح
# I = إضافة #include من abstractions جاهزة
# G = توليد قاعدة مع glob

بعد إنشاء النسخة الأولى، استخدم aa-logprof دورياً (مثلاً أسبوعياً في staging) لمراجعة الأحداث الجديدة وتوسيع الملف تدريجياً. هذا النمط (توليد ثم تنقيح) أوصت به صفحة AppArmor الرسمية في Ubuntu wiki وأطبّقه شخصياً منذ Ubuntu 18.04. الميزة الأساسية أنك تحصل على ملف تعريف بأقل الصلاحيات (least-privilege) دون تخمين، لأن القرارات مبنية على سلوك التطبيق الفعلي لا على فرضياتك.

الفرق بين وضع complain ووضع enforce

ملف تعريف AppArmor يكون في إحدى ثلاث حالات: enforce (الافتراضي، يفرض القواعد ويرفض ما لا يطابقها)، complain (يسمح بكل شيء لكنه يسجِّل الانتهاكات في auditd)، وdisable (مُعطَّل تماماً ومُزال من الذاكرة). وضع complain هو أداتك التشخيصية الأهم، وهو ما يميِّز نشراً ناجحاً لـ MAC عن كارثة تشغيلية. التحويل بين الأوضاع لحظي ولا يتطلّب إعادة تشغيل الخدمة:

# تحويل ملف تعريف إلى 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 aa-status

منهجيتي الموصى بها لخدمة إنتاج جديدة: ابدأ في complain لمدة لا تقل عن 72 ساعة تغطّي دورة كاملة (يومي عمل + عطلة + يوم بداية أسبوع). راقب سجلات auditd عبر journalctl -k _TRANSPORT=audit | grep apparmor وحلّل كل حدث. أضف القواعد المطلوبة إلى ملف التعريف، أعد التحميل، وكرّر حتى تمر 24 ساعة بدون انتهاكات. عندها فقط حوِّل إلى enforce. هذا النمط يقلِّل احتمال انقطاع الخدمة إلى أقل من 1% في تجربتي على أكثر من 200 خادم.

تقوية خدمات الإنتاج: Nginx وOpenSSH وDocker

الخدمات الثلاث الأكثر شيوعاً والأكثر استهدافاً في الإنتاج تستحقّ ملفات تعريف مخصّصة تتجاوز الافتراضي. لـ Nginx، ملف التعريف الافتراضي في Ubuntu يسمح بمسارات واسعة في /etc و/var؛ تقييده يقلِّل سطح الهجوم بشكل ملموس. تأكَّد من تكامله مع باقي طبقات الحماية مثل جدار الحماية nftables الحديث على لينكس وتأمين SSH باستخدام Ed25519 وFIDO2.

# /etc/apparmor.d/usr.sbin.nginx (نسخة مقوّاة)
#include <tunables/global>

/usr/sbin/nginx {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/openssl>

  capability dac_override,
  capability dac_read_search,
  capability net_bind_service,
  capability setgid,
  capability setuid,

  # رفض صريح للقدرات الخطرة
  deny capability sys_admin,
  deny capability sys_ptrace,
  deny capability sys_module,

  # الإعدادات
  /etc/nginx/ r,
  /etc/nginx/** r,
  /etc/ssl/certs/ r,
  /etc/ssl/certs/** r,
  /etc/ssl/private/*.key r,

  # السجلات والمؤقتات
  /var/log/nginx/*.log w,
  /var/lib/nginx/ rw,
  /var/lib/nginx/** rwk,
  /run/nginx.pid rw,

  # محتوى الويب: قراءة فقط
  /var/www/ r,
  /var/www/** r,

  # ثنائيات وملفات تعريف فرعية
  /usr/sbin/nginx mr,
  /usr/share/nginx/** r,

  # شبكات
  network inet stream,
  network inet6 stream,
  network unix stream,

  # رفض صريح للوصول إلى أسرار النظام
  deny /etc/shadow r,
  deny /etc/gshadow r,
  deny /root/** rwx,
  deny /home/*/.ssh/** rwx,
}

لـ OpenSSH، استخدم ملف التعريف الإضافي في حزمة apparmor-profiles-extra وفعّله بـ sudo aa-enforce /etc/apparmor.d/usr.sbin.sshd. لـ Docker، الإصدار 25.0 فما فوق يثبِّت ملف تعريف docker-default تلقائياً لكل حاوية. لرفع مستوى التقييد، أضف --security-opt apparmor=your-custom-profile إلى أمر docker run. توثيق Docker الرسمي لـ AppArmor يشرح آلية التحميل التلقائي للملف الافتراضي.

تشخيص حالات الرفض عبر auditd وdmesg

حين يَفشل تطبيق بصمت بعد تفعيل ملف تعريف في enforce، أول مكان أنظر فيه هو سجل auditd. تنسيق رسائل AppArmor فيه واضح ومنظَّم لكن قد يبدو مربكاً للوهلة الأولى. الأمر الأهم في حقيبتك:

# قراءة آخر 50 رسالة رفض
sudo journalctl -k _TRANSPORT=audit | grep -E 'apparmor=("DENIED"|"AUDIT")' | tail -50

# أو من ملف auditd مباشرة
sudo grep apparmor /var/log/audit/audit.log | grep DENIED | tail -20

# مثال رسالة رفض نمطية:
# type=AVC msg=audit(1718712345.678:42): apparmor="DENIED"
#   operation="open" profile="/usr/sbin/nginx"
#   name="/var/www/secret/.env" pid=12345 comm="nginx"
#   requested_mask="r" denied_mask="r" fsuid=33 ouid=0

الحقول الحرجة: profile (أي ملف تعريف فرض الرفض)، operation (نوع العملية)، name (المسار المرفوض)، requested_mask (ما حاولت العملية فعله) وdenied_mask (ما رُفض). لتحويل رسائل الرفض إلى قواعد سياسة تلقائياً، استخدم aa-logprof الذي يستخرج الأحداث من auditd ويقترح قواعد جديدة. لمراقبة الأحداث في الوقت الفعلي أثناء التطوير، اربط journalctl -kf مع grep apparmor في نافذة منفصلة.

AppArmor داخل الحاويات وSnap

تكامل AppArmor مع الحاويات تطوَّر بشكل ملموس منذ 2024. في Kubernetes 1.30 (الذي وصل إلى الدعم العام لـ AppArmor خارج النسخة التجريبية)، يمكنك تحديد ملف تعريف لكل حاوية مباشرةً في securityContext بدلاً من الاعتماد على التعليقات (annotations) القديمة. هذه نقلة مهمة لأن التعليقات ستُلغى في 1.34.

# مثال على pod مع تخصيص AppArmor لكل حاوية
apiVersion: v1
kind: Pod
metadata:
  name: hardened-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.27-alpine
    securityContext:
      appArmorProfile:
        type: Localhost
        localhostProfile: nginx-hardened
      runAsNonRoot: true
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
        add: ["NET_BIND_SERVICE"]

لـ Snap، AppArmor جزء من نموذج العزل الأساسي. كل snap له ملف تعريف مولَّد تلقائياً من interfaces المطلوبة في snapcraft.yaml. لفحص ملف تعريف snap معيّن، انظر إلى /var/lib/snapd/apparmor/profiles/snap.<name>.<app>. لا تعدِّل هذه الملفات يدوياً، فستتم إعادة كتابتها عند التحديث؛ بدلاً من ذلك، استخدم آلية interfaces لتعديل الصلاحيات بطريقة ثابتة. هذا النمط يكمّل أدوات مراقبة وقت التشغيل مثل eBPF لحماية وقت التشغيل، حيث يوفّر AppArmor المنع الاستباقي وeBPF يوفّر الكشف اللاحق.

الأسئلة الشائعة

هل يمكن تشغيل AppArmor وSELinux معاً على النواة نفسها؟

تقنياً نعم منذ النواة 5.1 عبر ميزة LSM stacking، لكن لا تفعل ذلك في الإنتاج. التداخل بين سياستَي MAC يُنتج حالات رفض غامضة يصعب تشخيصها. اختر واحدة وفقاً لتوزيعتك: SELinux لـ RHEL وأقربائها، وAppArmor لـ Ubuntu وDebian وopenSUSE.

كيف أعطّل AppArmor مؤقتاً لاختبار شيء ما؟

لتعطيل ملف تعريف واحد فقط استخدم sudo aa-disable /etc/apparmor.d/usr.sbin.nginx ثم sudo aa-enforce لإعادة تفعيله. لتعطيل النظام بالكامل أثناء الإقلاع، أضف apparmor=0 إلى معاملات الكيرنل في GRUB. لكن لا تتركه معطَّلاً، واستخدم وضع complain بدلاً منه فهو يسجِّل الأحداث دون منعها.

ما الفرق بين abstractions وincludes في AppArmor؟

كلاهما يستخدم نفس صيغة #include، لكن abstractions هي ملفات قواعد جاهزة في /etc/apparmor.d/abstractions/ تغطّي وظائف شائعة مثل قراءة nameservice أو OpenSSL أو Python. استخدامها بدلاً من إعادة كتابة القواعد يدوياً يقلِّل الأخطاء ويسهِّل الصيانة.

هل يؤثر AppArmor على أداء النظام؟

التأثير ضئيل جداً في معظم أحمال العمل، أقل من 2% في معايير قياس حقيقية أجريتُها على Nginx بحِمل 50,000 طلب/ثانية. الاستثناء الوحيد هو التطبيقات التي تفتح آلاف الملفات في الثانية (مثل قواعد بيانات mmap-heavy)، حيث قد يصل التأثير إلى 4–5%. القيمة الأمنية تفوق هذه التكلفة بفارق كبير.

كيف أكتب ملف تعريف لتطبيق Python أو Node.js؟

اعتمد على abstractions الجاهزة (abstractions/python أو abstractions/nodejs) في رأس الملف، ثم استخدم aa-genprof لتوليد القواعد المتبقية من تشغيل التطبيق في staging. تذكَّر أن مفسِّر اللغة (مثل /usr/bin/python3) يجب أن يكون قابلاً للتنفيذ بصيغة ix (inherit) ليظلّ ضمن ملف التعريف نفسه.

Yuki Tanaka
عن الكاتب Yuki Tanaka

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