سختسازی سرور لینوکس با AppArmor: ساخت و اجرای پروفایل امنیتی برای Nginx و سایر سرویسها

اگر یک سرویس روی سرور شما نفوذ کند، سؤال واقعی این است که آن سرویس بعد از نفوذ چه کارهایی میتواند بکند. پرمیشنهای فایل و کاربر عادی لینوکس برای این سؤال جواب کافی نمیدهند، چون اگر فرایند Nginx با کاربر www-data اجرا شود و همان کاربر به چند فایل حساس دیگر هم دسترسی داشته باشد، یک آسیبپذیری در یک ماژول یا کانفیگ اشتباه کافی است تا آن دسترسی سوءاستفاده شود. AppArmor دقیقاً همین شکاف را میپوشاند: محدود میکند هر برنامه فقط به همان فایلها، پورتها و قابلیتهایی که واقعاً لازم دارد دسترسی داشته باشد، حتی اگر کاربری که آن را اجرا میکند دسترسی بیشتری داشته باشد. این فقط یکی از لایههای سختسازی و افزایش امنیت سرور لینوکس است و معمولاً کنار تنظیمات دیگری مثل فایروال به کار میرود.
این مقاله پیکربندی AppArmor در اوبونتو را از صفر تا ساخت یک پروفایل واقعی برای Nginx جلو میبرد، بعد همان روش را برای سرویسهای دیگر هم تعمیم میدهد.
AppArmor چیست و چرا باید آن را فعال کنید؟
AppArmor یک ماژول کنترل دسترسی اجباری (MAC) در کرنل لینوکس است. برخلاف پرمیشنهای معمول فایل که بر اساس کاربر و گروه تصمیم میگیرند، AppArmor بر اساس «مسیر برنامه» تصمیم میگیرد: برای هر برنامه یک پروفایل تعریف میشود که دقیقاً مشخص میکند آن برنامه به کدام فایلها، کدام قابلیتهای کرنل (capabilities) و کدام منابع شبکه دسترسی دارد. هر چیزی خارج از این پروفایل رد میشود، حتی اگر کاربری که برنامه را اجرا کرده دسترسی کامل داشته باشد.
روی اوبونتو و دبیان، AppArmor از قبل نصب و فعال است و بخشی از چند پکیج پایه (مثل tcpdump, dhclient) پروفایل پیشفرض دارند. چیزی که معمولاً نصب نیست، پروفایل برای سرویسهایی مثل Nginx، PHP-FPM یا MySQL است، چون اینها معمولاً بعد از نصب پایه اضافه میشوند.

مقایسه AppArmor و SELinux
SELinux قدرتمندتر و دقیقتر است، اما یادگیری و نگهداری آن هم سنگینتر است. برای اکثر سرورهای اوبونتو/دبیان که این توزیعها بهصورت پیشفرض از AppArmor استفاده میکنند، جابهجایی به SELinux معمولاً توجیهی ندارد.
| ویژگی | AppArmor | SELinux |
|---|---|---|
| مدل کنترل دسترسی | بر اساس مسیر فایل برنامه | بر اساس لیبل امنیتی (context) |
| توزیع پیشفرض | اوبونتو، دبیان | RHEL، CentOS، Fedora |
| منحنی یادگیری | سادهتر، پروفایلهای خوانا | پیچیدهتر، نیاز به مدیریت context |
| ساخت پروفایل خودکار | aa-genprof + aa-logprof | audit2allow |
| حالت تست بدون قطع سرویس | complain | permissive |
نتیجه عملی: روی اوبونتو همان ابزاری را تقویت کنید که از قبل در کرنل فعال است، بهجای اینکه یک سیستم کنترل دسترسی موازی نصب کنید. AppArmor جایگزین فایروال نیست؛ فایروال ترافیک شبکه را فیلتر میکند و AppArmor دسترسی برنامه به فایلسیستم و قابلیتهای کرنل را محدود میکند، این دو مکمل هم هستند نه جایگزین هم.
بررسی وضعیت و نصب ابزارهای مدیریت AppArmor
قبل از ساخت پروفایل، وضعیت فعلی را ببینید:
sudo aa-status
خروجی این دستور سه بخش دارد: پروفایلهایی که در حالت enforce هستند، پروفایلهایی که در حالت complain هستند و پردازشهایی که پروفایل ندارند. اگر Nginx در لیست سوم باشد، یعنی هنوز هیچ محدودیتی روی آن اعمال نشده.
ابزارهای لازم برای ساخت و مدیریت پروفایل در پکیج جدا هستند:
sudo apt update
sudo apt install apparmor apparmor-utils apparmor-profiles
apparmor-profiles شامل پروفایلهای آمادهٔ چند سرویس رایج است؛ قبل از نوشتن پروفایل از صفر، ارزش دارد بررسی کنید که آیا پروفایلی برای سرویس مدنظرتان از قبل در این پکیج هست یا نه.
حالتهای enforce، complain و disable
هر پروفایل AppArmor در یکی از این سه حالت قرار میگیرد و تغییر حالت بدون ریاستارت سرویس ممکن است:
| حالت | رفتار | کاربرد |
|---|---|---|
| enforce | هر دسترسی خارج از پروفایل بلاک و در لاگ ثبت میشود | پروفایل نهایی و تستشده |
| complain | دسترسی خارج از پروفایل مجاز است اما در لاگ ثبت میشود | ساخت و دیباگ پروفایل جدید |
| disabled | پروفایل بار نمیشود، هیچ محدودیتی اعمال نمیشود | عیبیابی اضطراری یا سرویسهایی که فعلاً پروفایل ندارند |
برای تغییر حالت یک پروفایل مشخص:
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
sudo aa-disable /etc/apparmor.d/usr.sbin.nginx
نکته مهم: هیچوقت یک پروفایل تازهساخته را مستقیم در حالت enforce قرار ندهید. اول چند روز در حالت complain اجرا شود تا مطمئن شوید هیچ درخواست قانونی سرویس بلاک نمیشود.
ساخت پروفایل AppArmor برای Nginx
تولید خودکار پروفایل پایه با aa-genprof
aa-genprof ترافیک واقعی برنامه را رصد میکند و بر اساس آن یک پروفایل پیشنهاد میدهد:
sudo aa-genprof nginx
بعد از اجرای این دستور، در یک ترمینال دیگر چند درخواست واقعی به Nginx بزنید (بازکردن چند صفحه، آپلود فایل، اگر PHP-FPM پشت آن است چند درخواست داینامیک). ابزار برای هر دسترسی جدیدی که Nginx تلاش میکند انجام دهد از شما میپرسد که آیا اجازه داده شود، رد شود یا بهصورت یک الگوی کلیتر (glob) اجازه داده شود. بعد از پایان، پروفایل در /etc/apparmor.d/usr.sbin.nginx ذخیره میشود و بهصورت پیشفرض در حالت complain فعال است.
ویرایش دستی پروفایل
پروفایل تولیدشده را باز کنید و آن را دستی تنظیم کنید، چون aa-genprof همه مسیرهای لازم را (مثل مسیرهای لاگ، SSL، یا دایرکتوری اپلیکیشن) تشخیص نمیدهد:
#include <tunables/global>
/usr/sbin/nginx {
#include <abstractions/base>
#include <abstractions/nameservice>
capability net_bind_service,
capability setuid,
capability setgid,
network inet stream,
network inet6 stream,
/etc/nginx/** r,
/var/log/nginx/*.log w,
/var/www/html/** r,
/etc/ssl/certs/** r,
/etc/letsencrypt/** r,
/run/nginx.pid rw,
/usr/sbin/nginx mr,
deny /home/** rwklx,
deny /root/** rwklx,
}
چند نکته در این پروفایل:
capability net_bind_serviceلازم است چون Nginx روی پورت ۸۰/۴۴۳ (زیر ۱۰۲۴) بایند میشود.- دسترسی به
/var/www/htmlفقط خواندنی (r) است؛ Nginx نباید بتواند فایل اپلیکیشن را بنویسد. - خطوط
denyصریح برای/homeو/rootحتی اگر در بقیه پروفایل چیزی اجازه این مسیرها را نداده باشد، یک لایه اطمینان اضافه میکنند و در لاگ بهوضوح علامتگذاری میشوند. - اگر از PHP-FPM پشت Nginx استفاده میکنید، باید سوکت unix آن (معمولاً در
/run/php/) را هم به پروفایل اضافه کنید.
پروفایل AppArmor جایگزین تنظیمات امنیتی سطح خود Nginx نیست؛ برای مهمترین ترفندهای امنیتی وبسرور Nginx همچنان باید جدا از این پروفایل اقدام کنید.
بعد از ویرایش، پروفایل را دوباره بار کنید:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
تست در حالت complain و رفع خطا با aa-logprof
بعد از چند روز اجرا در حالت complain، لاگ را بررسی کنید:
sudo journalctl -k | grep -i apparmor
# یا
sudo dmesg | grep -i apparmor
هر رد دسترسی بهصورت یک خط DENIED با مسیر دقیق فایل و نوع عملیات (read/write/exec) ثبت میشود. بهجای افزودن دستی هر خط، از aa-logprof استفاده کنید تا این لاگها را بخواند و پیشنهاد بهروزرسانی پروفایل بدهد:
sudo aa-logprof
این ابزار برای هر DENIED در لاگ از شما میپرسد چه کاری انجام شود و تغییرات را مستقیم در فایل پروفایل اعمال میکند. وقتی چند روز متوالی لاگ خالی از DENIED بود، پروفایل را به enforce ببرید:
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
sudo aa-status | grep nginx
تعمیم به سرویسهای دیگر: PHP-FPM، MySQL و SSH
همین روش (نصب پروفایل پایه در صورت وجود، ساخت با aa-genprof در صورت نبود، تست در complain، enforce بعد از پاکشدن لاگ) برای هر سرویسی که روی سرور شما قرار دارد قابل تکرار است:
- PHP-FPM: محدود کنید کدام دایرکتوریها قابل اجرا هستند و کدام فقط قابل خواندن. اگر اپلیکیشن شما آپلود فایل دارد، مسیر آپلود باید جدا و با دسترسی نوشتن محدود تعریف شود.
- MySQL/MariaDB: پروفایل آماده معمولاً همراه پکیج توزیع نصب میشود؛ فقط بررسی کنید مسیر دیتادایرکتوری واقعی سرور شما (اگر از مسیر پیشفرض
/var/lib/mysqlفرق دارد) در پروفایل اضافه شده باشد. - SSH: کمتر رایج است چون OpenSSH معمولاً نیاز زیادی به محدودسازی AppArmor ندارد، اما اگر سرور شما قاعدههای دسترسی سختگیرانه میخواهد، میتوانید دسترسی
sshdبه فایلهای کلید و/etc/ssh/را هم صریح تعریف کنید. این را جدا از امنسازی دسترسی SSH به سرور لینوکس (کلید، غیرفعال کردن رمز عبور، fail2ban) در نظر بگیرید؛ آنها لایه دیگری از سختسازی هستند، نه جایگزین این پروفایل.
نکته عملی: پروفایلها را در Git یا ابزار IaC که برای سرور استفاده میکنید نگه دارید، نه فقط در /etc/apparmor.d/. وقتی سروری جدید راهاندازی میکنید یا سرور فعلی را بازسازی میکنید، همان پروفایلهای تستشده دوباره قابل استفاده خواهند بود.
عیبیابی رایج
اگر بعد از enforce کردن یک پروفایل، سرویس رفتار عجیب نشان داد (مثلاً خطای ۵۰۲ از Nginx یا یک فایل که قبلاً باز میشد الان باز نمیشود)، اولین قدم همیشه همان دستور چککردن لاگ است:
sudo dmesg | grep DENIED | tail -20
اگر مسیر یا capability رد شده را در خط DENIED دیدید، بهجای حذف کامل پروفایل یا غیرفعالکردن AppArmor، فقط همان یک خط را به پروفایل اضافه کنید و دوباره apparmor_parser -r بزنید. غیرفعالکردن کامل AppArmor برای حل یک خطای موقت، همان شکافی را دوباره باز میکند که از اول هدف بستهشدنش بود.
جمعبندی
پیکربندی AppArmor در اوبونتو یک کار یکباره نیست؛ هر سرویس جدیدی که روی سرور نصب میکنید باید همین چرخه (ساخت پروفایل، تست در complain، enforce) را طی کند. اما هزینهٔ این کار در مقابل محدودکردن شعاع آسیب یک آسیبپذیری ناشناخته در Nginx یا هر سرویس دیگر، کم است.
اگر این مرحله را روی یک سرور تست پیش از انتقال به production انجام میدهید، یک سرور مجازی ابری آریانت برای همین کار مناسب است — snapshot بگیرید، پروفایل را بسازید و تست کنید، و اگر چیزی اشتباه پیش رفت به snapshot برگردید بدون ریسک روی سرور اصلی.




