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

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

1405/07/110 بازدید
سخت‌سازی سرور لینوکس با AppArmor: ساخت و اجرای پروفایل امنیتی برای Nginx و سایر سرویس‌ها

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

پیکربندی AppArmor در اوبونتو برای سخت‌سازی سرور

اگر یک سرویس روی سرور شما نفوذ کند، سؤال واقعی این است که آن سرویس بعد از نفوذ چه کارهایی می‌تواند بکند. پرمیشن‌های فایل و کاربر عادی لینوکس برای این سؤال جواب کافی نمی‌دهند، چون اگر فرایند Nginx با کاربر www-data اجرا شود و همان کاربر به چند فایل حساس دیگر هم دسترسی داشته باشد، یک آسیب‌پذیری در یک ماژول یا کانفیگ اشتباه کافی است تا آن دسترسی سوءاستفاده شود. AppArmor دقیقاً همین شکاف را می‌پوشاند: محدود می‌کند هر برنامه فقط به همان فایل‌ها، پورت‌ها و قابلیت‌هایی که واقعاً لازم دارد دسترسی داشته باشد، حتی اگر کاربری که آن را اجرا می‌کند دسترسی بیشتری داشته باشد. این فقط یکی از لایه‌های سخت‌سازی و افزایش امنیت سرور لینوکس است و معمولاً کنار تنظیمات دیگری مثل فایروال به کار می‌رود.

این مقاله پیکربندی AppArmor در اوبونتو را از صفر تا ساخت یک پروفایل واقعی برای Nginx جلو می‌برد، بعد همان روش را برای سرویس‌های دیگر هم تعمیم می‌دهد.

AppArmor چیست و چرا باید آن را فعال کنید؟

AppArmor یک ماژول کنترل دسترسی اجباری (MAC) در کرنل لینوکس است. برخلاف پرمیشن‌های معمول فایل که بر اساس کاربر و گروه تصمیم می‌گیرند، AppArmor بر اساس «مسیر برنامه» تصمیم می‌گیرد: برای هر برنامه یک پروفایل تعریف می‌شود که دقیقاً مشخص می‌کند آن برنامه به کدام فایل‌ها، کدام قابلیت‌های کرنل (capabilities) و کدام منابع شبکه دسترسی دارد. هر چیزی خارج از این پروفایل رد می‌شود، حتی اگر کاربری که برنامه را اجرا کرده دسترسی کامل داشته باشد.

روی اوبونتو و دبیان، AppArmor از قبل نصب و فعال است و بخشی از چند پکیج پایه (مثل tcpdump, dhclient) پروفایل پیش‌فرض دارند. چیزی که معمولاً نصب نیست، پروفایل برای سرویس‌هایی مثل Nginx، PHP-FPM یا MySQL است، چون این‌ها معمولاً بعد از نصب پایه اضافه می‌شوند.

پروفایل AppArmor به‌عنوان یک سپر دفاعی روی رک سرور در برابر حملات، در مقابل سروری که با پروفایل امنیتی ایمن و آماده شده است

مقایسه AppArmor و SELinux

SELinux قدرتمندتر و دقیق‌تر است، اما یادگیری و نگهداری آن هم سنگین‌تر است. برای اکثر سرورهای اوبونتو/دبیان که این توزیع‌ها به‌صورت پیش‌فرض از AppArmor استفاده می‌کنند، جابه‌جایی به SELinux معمولاً توجیهی ندارد.

ویژگیAppArmorSELinux
مدل کنترل دسترسیبر اساس مسیر فایل برنامهبر اساس لیبل امنیتی (context)
توزیع پیش‌فرضاوبونتو، دبیانRHEL، CentOS، Fedora
منحنی یادگیریساده‌تر، پروفایل‌های خواناپیچیده‌تر، نیاز به مدیریت context
ساخت پروفایل خودکارaa-genprof + aa-logprofaudit2allow
حالت تست بدون قطع سرویسcomplainpermissive

نتیجه عملی: روی اوبونتو همان ابزاری را تقویت کنید که از قبل در کرنل فعال است، به‌جای اینکه یک سیستم کنترل دسترسی موازی نصب کنید. 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 برگردید بدون ریسک روی سرور اصلی.

سرور مجازی ابری آریانت را ببینید