بلاگ/سخت‌سازی سرور لینوکس با SELinux: مدیریت حالت Enforcing، Context فایل‌ها و Policy روی RHEL، Rocky Linux، CentOS و AlmaLinux
به‌روز شده

سخت‌سازی سرور لینوکس با SELinux: مدیریت حالت Enforcing، Context فایل‌ها و Policy روی RHEL، Rocky Linux، CentOS و AlmaLinux

1405/07/160 بازدید
سخت‌سازی سرور لینوکس با SELinux: مدیریت حالت Enforcing، Context فایل‌ها و Policy روی RHEL، Rocky Linux، CentOS و AlmaLinux

سخت‌سازی سرور لینوکس با SELinux: مدیریت حالت Enforcing، Context فایل‌ها و Policy روی RHEL، Rocky Linux، CentOS و AlmaLinux

راه‌اندازی SELinux روی سرور لینوکس خانواده RHEL برای سخت‌سازی دسترسی سرویس‌ها

اگر سرویسی روی سرور با یک کاربر سیستمی اجرا شود و دسترسی فایلی آن کاربر بیشتر از چیزی باشد که همان سرویس واقعاً لازم دارد، یک باگ یا پیکربندی اشتباه کافی است تا آن دسترسی اضافه مورد سوءاستفاده قرار گیرد. SELinux همین شکاف را با یک لایه کنترل دسترسی اجباری (MAC) می‌پوشاند که مستقل از permission معمول فایل عمل می‌کند و تصمیم می‌گیرد هر پردازش فقط به چه فایل‌ها، پورت‌ها و قابلیت‌هایی اجازه دسترسی دارد.

در توزیع‌های خانواده Red Hat -شامل RHEL، Rocky Linux، CentOS Stream و AlmaLinux- SELinux با policy «targeted» از ابتدا فعال است. توزیع‌های دبیان‌محور مثل اوبونتو به‌جای آن از AppArmor استفاده می‌کنند که مدل ساده‌تری دارد. این راهنما راه‌اندازی SELinux در سرور لینوکس را از مدیریت حالت enforcing/permissive تا کار با context فایل‌ها، Boolean‌ها و رفع خطای دسترسی با audit2allow پوشش می‌دهد.

SELinux چیست و چرا در RHEL و مشتقات آن فعال است؟

permission معمول لینوکس (owner، group، other) بر اساس هویت کاربر تصمیم می‌گیرد. SELinux یک لایه اضافه بر همین مدل است: هر فایل، پردازش، پورت و دستگاه یک برچسب امنیتی (context) به شکل user:role:type:level دارد و policy مشخص می‌کند کدام type اجازه دسترسی به کدام type دیگر را دارد. حتی اگر پردازشی با root اجرا شود، اگر type آن اجازه دسترسی به یک فایل را در policy نداشته باشد، درخواست رد می‌شود.

برای دیدن وضعیت کلی SELinux روی سرور:

sestatus

خروجی این دستور حالت فعلی (enforcing/permissive/disabled)، نوع policy بارگذاری‌شده (معمولاً targeted) و مسیر فایل‌های policy را نشان می‌دهد.

مدیریت حالت Enforcing، Permissive و Disabled

حالت فعلی را با یک دستور می‌بینید:

getenforce

برای تغییر موقت (تا ریبوت بعدی) بدون ویرایش فایل تنظیمات:

sudo setenforce 1   # enforcing
sudo setenforce 0   # permissive

برای تغییر دائمی، فایل تنظیمات را ویرایش کنید:

# /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted

اگر سروری قبلاً با SELINUX=disabled اجرا می‌شده و حالا می‌خواهید آن را روی enforcing برگردانید، فایل‌ها برچسب ندارند و فعال‌سازی مستقیم عملاً هر درخواست را رد می‌کند. پیش از ریبوت باید یک relabel کامل درخواست بدهید:

sudo touch /.autorelabel
sudo reboot

این relabel بسته به تعداد فایل‌های سرور ممکن است چند دقیقه طول بکشد و سرور در این مدت پاسخگو نخواهد بود؛ بهتر است در یک پنجره تعمیرات برنامه‌ریزی‌شده انجام شود.

مقایسه سه حالت:

حالترفتارکاربرد مناسب
Enforcingدسترسی خارج از policy رد و در audit log ثبت می‌شودسرور تولید
Permissiveهیچ دسترسی رد نمی‌شود، فقط در audit log ثبت می‌شودتست policy جدید، عیب‌یابی
Disabledماژول SELinux در kernel بارگذاری نمی‌شودتوصیه نمی‌شود برای سرور تولید

مقایسه سه حالت SELinux: enforcing، permissive و disabled و تفاوت رفتار هرکدام در برابر درخواست دسترسی

در حالت disabled کل زیرساخت SELinux در kernel خاموش می‌شود، نه فقط policy targeted. برگرداندن آن به enforcing همان relabel کامل بالا را لازم دارد. برای عیب‌یابی موقت، permissive همیشه گزینه امن‌تری نسبت به disabled است چون می‌توانید بدون قطع سرویس ببینید policy چه چیزی را رد می‌کرد.

مدیریت Context فایل‌ها

برای دیدن context فعلی فایل‌ها و پردازش‌ها:

ls -Z /var/www/html
ps -Z -C httpd

ستون type در خروجی (مثل httpd_sys_content_t) همان چیزی است که policy برای تطبیق دسترسی استفاده می‌کند. کپی‌کردن فایل در یک دایرکتوری معمولاً context پیش‌فرض همان مسیر را به فایل جدید می‌دهد، اما mv یا کپی با cp -a context مبدا را حفظ می‌کند. نتیجه این است که یک فایل منتقل‌شده از /tmp به /var/www/html ممکن است context نادرست داشته باشد و httpd به آن دسترسی نداشته باشد، حتی اگر permission فایل درست باشد.

راه‌حل برای برگرداندن context به مقدار پیش‌فرض policy:

sudo restorecon -Rv /var/www/html

برای مسیرهایی که خارج از مسیرهای پیش‌فرض policy هستند (مثلاً یک web root سفارشی زیر /srv)، باید قاعده را به‌صورت دائمی در policy ثبت کنید، نه فقط context فعلی فایل را عوض کنید:

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
sudo restorecon -Rv /srv/web

فرق chcon و semanage fcontext همین‌جاست: chcon فقط context همان فایل مشخص را تغییر می‌دهد و با هر restorecon بعدی یا هر relabel به مقدار قبلی برمی‌گردد. semanage fcontext قاعده را در پایگاه‌داده policy ثبت می‌کند، پس هر بار که restorecon اجرا شود همان نتیجه درست را می‌دهد.

Boolean‌های SELinux برای تنظیم رفتار سرویس‌ها

برای بعضی رفتارهای رایج، policy از قبل یک کلید روشن/خاموش به اسم Boolean دارد و لازم نیست module جدیدی ساخته شود. برای مثال، اگر Nginx یا httpd باید به یک backend روی پورت دیگری در شبکه وصل شود:

getsebool -a | grep httpd_can_network
sudo setsebool -P httpd_can_network_connect on

فلگ -P تغییر را دائمی می‌کند؛ بدون آن، تغییر فقط تا ریبوت بعدی باقی می‌ماند. قبل از روشن‌کردن یک Boolean، نام و توضیح آن را با semanage boolean -l | grep <کلیدواژه> بررسی کنید تا مطمئن شوید دقیقاً همان رفتاری را باز می‌کند که لازم دارید، نه یک اجازه کلی‌تر.

رفع خطای دسترسی با audit2allow

وقتی context و Boolean مناسب موجود نیست و یک درخواست مشروع رد می‌شود، SELinux آن را به‌عنوان AVC (Access Vector Cache) denial در /var/log/audit/audit.log ثبت می‌کند. گردش کار معمول برای رفع این خطا:

sudo ausearch -m avc -ts recent | audit2allow -m mymodule
sudo ausearch -m avc -ts recent | audit2allow -M mymodule
sudo semodule -i mymodule.pp

دستور اول فقط پیش‌نمایش قانون پیشنهادی را نشان می‌دهد، دستور دوم همان قانون را در فایل mymodule.pp کامپایل می‌کند و دستور سوم آن را به policy فعال اضافه می‌کند. پیش از نصب، محتوای فایل .te تولیدشده را حتماً بخوانید:

cat mymodule.te

audit2allow هر چیزی را که در بازه زمانی انتخابی رد شده بوده مجاز می‌کند، بدون توجه به این‌که آن رد واقعاً یک خطای پیکربندی بوده یا رفتار نرمال policy برای جلوگیری از یک حمله. ساخت module از یک بازه طولانی یا از audit log چند سرویس مختلف معمولاً باز کردن دسترسی بیش از نیاز واقعی است؛ بهتر است هر بار فقط AVC denial مربوط به همان مشکل مشخص را بررسی کنید.

برای توضیح خوانا‌تر همان denial، ابزار setroubleshoot کمک می‌کند:

sudo sealert -a /var/log/audit/audit.log

SELinux در RHEL، Rocky Linux، CentOS و AlmaLinux چه فرقی دارد؟

Rocky Linux و AlmaLinux از کد منبع بسته‌های RHEL بازساخت می‌شوند، پس پکیج selinux-policy-targeted و رفتار دستورهای بالا در این دو عملاً با RHEL یکسان است. تفاوت اصلی در زمان‌بندی انتشار و پشتیبانی تجاری است، نه در منطق SELinux.

توزیعمنبع Policyنکته عملی
RHELپکیج رسمی Red Hatپشتیبانی و بروزرسانی رسمی policy از طریق اشتراک
Rocky Linuxبازساخت از کد منبع RHELرفتار SELinux عملاً یکسان با RHEL
AlmaLinuxبازساخت از کد منبع RHELرفتار SELinux عملاً یکسان با RHEL
CentOS Streamشاخه بالادست RHELممکن است نسخه جدیدتر policy را زودتر و با چرخه پایداری کوتاه‌تر دریافت کند

برای سرور تولید، این یعنی مستندات و راه‌حل‌های SELinux مربوط به RHEL روی Rocky Linux و AlmaLinux هم مستقیماً کاربرد دارند؛ فقط روی CentOS Stream باید انتظار تغییرات policy را زودتر از نسخه پایدار RHEL داشته باشید.

چک‌لیست راه‌اندازی SELinux روی سرور تولید

برای این‌که SELinux واقعاً فعال بماند و مانع کار روزمره نشود:

  • حالت enforcing را پیش‌فرض نگه دارید؛ برای عیب‌یابی به‌جای disabled از permissive موقت استفاده کنید.
  • برای مسیرهای سفارشی همیشه semanage fcontext را ثبت کنید، نه فقط chcon روی فایل‌های فعلی.
  • پیش از فعال‌کردن هر Boolean، توضیح آن را با semanage boolean -l بخوانید.
  • هر module ساخته‌شده با audit2allow را قبل از نصب در فایل .te بازبینی کنید.
  • وضعیت و تاریخچه denial را دوره‌ای با sealert یا بررسی مستقیم audit log چک کنید، نه فقط وقتی سرویسی از کار می‌افتد.

برای انتخاب نوع زیرساخت مناسب، راهنمای خرید سرور ابری تفاوت سرور ابری، VPS و سرور اختصاصی را توضیح می‌دهد. اگر سرور شما روی RHEL، Rocky Linux یا AlmaLinux اجرا می‌شود و برای فعال‌نگه‌داشتن SELinux در enforcing به دسترسی کامل root و امکان ریبوت برای relabel نیاز دارید، مشخصات سرور ابری آریاسرویس را بررسی کنید و توزیع RHEL-محور مدنظرتان را از ابتدا روی آن نصب کنید.

جمع‌بندی

راه‌اندازی SELinux در سرور لینوکس یعنی enforcing را پیش‌فرض نگه دارید، context فایل‌ها را با semanage fcontext به‌جای تغییرات یک‌بارمصرف مدیریت کنید، برای رفتارهای شناخته‌شده از Boolean استفاده کنید و هر خروجی audit2allow را قبل از نصب بازبینی کنید. خاموش‌کردن SELinux سریع‌ترین راه برای رفع یک خطای دسترسی به نظر می‌رسد، اما همان لایه‌ای را حذف می‌کند که برای همین منظور اضافه شده است.

SELinux یکی از چند لایه سخت‌سازی سرور است، نه همه آن. کنار آن، امن‌سازی دسترسی SSH و فایروال nftables را هم بررسی کنید؛ هر سه با هم تصویر کامل‌تری از سخت‌سازی یک سرور RHEL-محور می‌دهند.