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

اگر سرویسی روی سرور با یک کاربر سیستمی اجرا شود و دسترسی فایلی آن کاربر بیشتر از چیزی باشد که همان سرویس واقعاً لازم دارد، یک باگ یا پیکربندی اشتباه کافی است تا آن دسترسی اضافه مورد سوءاستفاده قرار گیرد. 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 بارگذاری نمیشود | توصیه نمیشود برای سرور تولید |

در حالت 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-محور میدهند.




