WIUNIX ACADEMY
سختسازی سرویسهای systemd با آزمون و بازگشت امن
اول محدودیت نوشتن را در یک سرویس موقت بسنجید؛ سپس نیازهای برنامه را مشخص کنید و با یک drop-in قابل بازگشت، دسترسی همان سرویس را محدود کنید.
محیطت را انتخاب کنآموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
آیپی، دامنه یا پورت مثالها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای بهروزشده را کپی کن.
تنظیم مقادیر برای محیط من3 مقدار قابلتغییر
از اینجا شروع کن
در پایان چه چیزی خواهی داشت؟
منع و اجازهٔ نوشتن را عملاً از هم جدا کنید، نیازهای واقعی یک سرویس را بشناسید و محدودیت سازگار و قابل بازگشت برای آن بنویسید.
سیستمعاملها و نسخههای پوششدادهشده
مسیرهای این آموزش با مستندات رسمی ابزار و توزیع انتخابی بررسی شدهاند. فرمانهای آموزشی روی سرویس شما اجرا نشدهاند؛ نتیجهٔ محیط خودتان را در هر گام بررسی کنید.
قبل از شروع
- یک میزبان آزمایشی دارای systemd بهعنوان مدیر اصلی سیستم، دسترسی مجاز مدیریتی و پشتیبانی mount namespace.
- نام یک سرویس موجود و مسیرهای لازم برای نوشتن آن را میدانید؛ برای restart و بازگشت، زمان و بررسی سلامت مشخص است.
- ابزارهای این راهنما نصباند؛ user manager یا کانتینر فاقد مجوز namespace جایگزین این محیط نیست.
امتیاز ابزار جای آزمون برنامه را نمیگیرد
محدودیتهای systemd محیط اجرای برنامه را کنترل میکنند، اما آسیبپذیری کد یا کنترل دسترسی خود برنامه را اصلاح نمیکنند. امتیاز systemd-analyze بیانگر تنظیمات شناختهشده است، نه نتیجهٔ آزمون نفوذ.
ابتدا در یک سرویس موقت و بدون شنوندهٔ شبکه، دو رفتار مشخص را میسنجیم. بعد سراغ یک سرویس واقعی میرویم. نتیجهٔ آزمایش موقت را تأیید کامل محصورشدن برنامهٔ واقعی ندانید.
قدم بعدی
پیش از شروع، ابزار و تفاوتهای توزیع را بررسی کنید
این گام روی همان میزبان آزمایش یا عیبیابی اجرا میشود. نام و نسخهٔ سیستمعامل و بستههای فهرستشده را با محیط انتخابی تطبیق دهید. اگر ابزاری نصب نیست، ابتدا از مخزن رسمی فعال و روند مجاز مدیریت بستهٔ خود آن را نصب کنید؛ این آموزش سرور موجود را دوباره نصب یا مخزنش را عوض نمیکند.
در RHEL، مخزنهای مجاز همان اشتراک و در Rocky Linux و AlmaLinux، مخزنهای رسمی همان نسخه لازماند. نسخهٔ فرعیِ تحت پشتیبانی را بهروز نگه دارید؛ انتخاب نسخهٔ اصلی به معنی سازگاری تمام بستههای قدیمی یا سفارشی نیست. SELinux و سیاست رمزنگاری سیستم بخشی از محیطاند و برای عبور از خطا خاموش نمیشوند.
آزمایش mount و مجوز فایل، کنترل مستقل SELinux یا AppArmor را حذف نمیکند. روی Ubuntu و Debian لاگ denial پروفایلهای فعال را با زمان خطا تطبیق دهید. روی RPM، مالکیت و برچسب مسیر state و AVC مربوط به همان سرویس را بررسی کنید؛ برای آزمایش sandbox، SELinux را permissive نکنید. امتیاز exposure نیز تأیید امنیت برنامه نیست.
ترمینال میزبان مجاز معرفیشده در همین بخش
cat /etc/os-release
rpm -q systemd coreutils
command -v systemctl systemd-run systemd-analyzeبسته و ابزار لازم شناسایی شده است؛ خطا یا نبود ابزار را پیش از ادامه رفع کنید.
قدم بعدی
قبل از محدودکردن، نیاز سرویس را بشناسید
روی میزبان آزمایشی، unit و drop-inهای مؤثر example-app.service را بخوانید. کاربر اجرا، مسیرهای نوشتنی، سوکتها، دستگاهها، خانوادههای آدرس و helperهای لازم را مشخص کنید. فایل unit ممکن است مقدار خصوصی داشته باشد؛ خروجی کاملش را عمومی نکنید.
یک تنظیم برای همهٔ برنامهها مناسب نیست. برای مثال، محدودیت حافظهٔ قابل اجرا میتواند runtime دارای JIT را از کار بیندازد. امتیاز فعلی را فقط بهعنوان شاهد پیکربندی نگه دارید.
ترمینال همان میزبان معرفیشده در توضیح گام
systemd --version
sudo systemctl cat 'example-app.service'
sudo systemctl show 'example-app.service' -p User -p Group -p FragmentPath -p DropInPaths -p MainPID -p ProtectSystem -p ReadWritePaths
sudo systemd-analyze security 'example-app.service'تنظیم مؤثر و نیاز برنامه معلوم است؛ هنوز از روی امتیاز، امنبودن سرویس را نتیجه نگرفتهاید.
قدم بعدی
کنترل امنیتی میزبان را جداگانه بررسی کنید
همزمان با خطای ثبتشده، denial مربوط به فرایند و مسیر دقیق را پیدا کنید. نبود AVC یا شکست ابزار، بهتنهایی SELinux را از بررسی خارج نمیکند. برچسب، دامنهٔ فرایند و سیاست نصبشده را بررسی کنید؛ این گام مجوز جدید تولید نمیکند و SELinux خاموش نمیشود. بررسی restorecon در این پنل فقط پیشنمایش است و برچسب را تغییر نمیدهد. مجوز Unix، برچسب SELinux و ReadWritePaths سه بررسی جدا هستند؛ هر سه باید با کاربرد واقعی مسیر state سازگار باشند.
ترمینال میزبان مجاز معرفیشده در همین بخش
getenforce
sudo ausearch -m AVC,USER_AVC -ts recent
ls -Zd '/var/lib/example-app'
sudo restorecon -nRv '/var/lib/example-app'علت احتمالی را به شواهد همان خطا و سیاست مشخص میزبان مرتبط کردهاید؛ هیچ سیاست امنیتی یا قاعدهٔ فایروالی را غیرفعال یا تغییر ندادهاید.
قدم بعدی
برای آزمایش، شاخهای جدا و تازه بسازید
/var/lib/academy-sandbox-lab نباید دادهٔ برنامه، symlink یا مسیر mountشدهٔ سرویس عملیاتی باشد. اگر از قبل وجود دارد متوقف شوید. یک شاخهٔ خصوصی و زیرشاخهٔ state میسازیم و نشان میدهیم root در حالت عادی میتواند در والد بنویسد.
سرویس آزمایش بعدی عمداً root است تا منع ناشی از mount را با مالکیت معمول Unix اشتباه نگیریم. این انتخاب برای تفکیک آزمایش است؛ پیشنهاد اجرای برنامهٔ واقعی با root نیست.
ترمینال همان میزبان معرفیشده در توضیح گام
sudo test ! -e '/var/lib/academy-sandbox-lab' || exit 1
sudo mkdir -m 0700 -- '/var/lib/academy-sandbox-lab' || exit 1
sudo mkdir -m 0700 -- '/var/lib/academy-sandbox-lab/state'
sudo sh -c 'printf control > "$1/control-before"' sh '/var/lib/academy-sandbox-lab'
sudo stat -c '%U %G %a %n' '/var/lib/academy-sandbox-lab' '/var/lib/academy-sandbox-lab/control-before'شاخهٔ اختصاصی تازه، فایل کنترل و زیرشاخهٔ state با مالک root ایجاد شدهاند.
قدم بعدی
منع و اجازهٔ نوشتن را در یک اجرا ببینید
نام سرویس موقت باید آزاد باشد. فرایند آزمایش در namespace خودش فایلسیستم را فقطخواندنی میبیند و فقط state آزمایش برایش نوشتنی است. نوشتن در والد باید با خطایی مانند read-only filesystem رد شود؛ نوشتن در state باید موفق شود.
اگر فایل ممنوع ساخته شد، خود آزمایش شکست میخورد. خطای property یا نبود پشتیبانی namespace را قبولی ندانید. این پنل هیچ پورت شبکهای باز نمیکند.
ترمینال همان میزبان معرفیشده در توضیح گام
test "$(systemctl show -p LoadState --value 'example-app-academy-mount-probe.service')" = not-found || exit 1
sudo systemd-run --wait --pipe --collect --unit='example-app-academy-mount-probe' --property=Type=oneshot --property=ProtectSystem=strict --property='ReadWritePaths=/var/lib/academy-sandbox-lab/state' --property=NoNewPrivileges=yes --property=PrivateTmp=yes /bin/sh -c 'if touch "$1/forbidden-inside"; then echo UNEXPECTED_WRITE; exit 1; fi; printf allowed > "$1/state/allowed-inside"; test -s "$1/state/allowed-inside" || exit 1; echo ALLOWED_STATE_WRITE' sh '/var/lib/academy-sandbox-lab'خطای فقطخواندنی برای والد، پیام موفقیت state و پایان صفر دیده میشوند؛ نبود پشتیبانی یا منع نامرتبط، نتیجهٔ موفق این آزمون نیست.