اگر همین حالا با پیام Permission denied جلوی یک systemctl restart گیر کردهاید، یا برای بار چندم با sudo کارتان را راه انداختهاید و بعد به این فکر افتادهاید که چرا همهچیز را با روت انجام نمیدهید، این متن برای شماست. مسئله این نیست که روت خوب است یا بد. مسئله این است که کدام کار واقعاً به روت نیاز دارد و کدام کار فقط به این دلیل با روت انجام میشود که کسی حوصلهی تنظیم مجوزها را نداشته.
چه کاری واقعاً به دسترسی روت نیاز دارد
روت یک ویژگی امنیتی نیست؛ یک بایپس امنیتی است. کرنل لینوکس برای هر عملیات، مجوز را از روی UID و capabilityها چک میکند. UID صفر یعنی همهی این چکها رد میشوند. به همین دلیل فهرست کارهایی که بدون روت ممکن نیست، کوتاه و مشخص است:
- باز کردن پورت زیر 1024 (مثل 80 و 443) بدون تنظیم
CAP_NET_BIND_SERVICE - mount و unmount کردن فایلسیستم، تغییر پارتیشنبندی، اجرای
fsckروی دیسک mountشده - تغییر مالکیت فایل به کاربر دیگر با
chown - نصب بسته در مسیرهای سیستمی، نوشتن در
/etcو/usr - مدیریت unitهای systemd در سطح سیستم، خواندن ژورنال کامل با
journalctl - تغییر قواعد فایروال و بارگذاری ماژول کرنل
هر چیز دیگری که «فقط با روت کار میکند»، تقریباً همیشه مشکل مجوز فایل یا مالکیت دایرکتوری است. مثلاً سرویس PHP-FPM که با کاربر www-data اجرا میشود و نمیتواند در /var/www/site/uploads بنویسد، با روت هم درست نمیشود؛ فقط مشکل را پنهان میکند تا روزی که یک آپلود مخرب با همان دسترسی اجرا شود.
خطای رایج: روت بهجای رفع مشکل مجوز
اینجا اشتباه میکنند. کاربر با chmod -R 777 روی دایرکتوری پروژه مشکل را حل میکند، سایت بالا میآید، و سه ماه بعد سرور به یک پوستهی وب تبدیل شده است. نشانهاش همیشه یک چیز نیست، اما الگوی تکرارشونده دارد: فایلهای عجیب در /tmp، پروسههای ناشناس با نامهایی شبیه kworker که با ps aux دیده میشوند، و ترافیک خروجی بالا در ساعاتی که سایت بازدید ندارد.
راه درست این است که مالکیت را به کاربر سرویس بدهید و مجوز را محدود کنید:
chown -R www-data:www-data /var/www/site
find /var/www/site -type d -exec chmod 755 {} \;
find /var/www/site -type f -exec chmod 644 {} \;
اگر سرویس به نوشتن نیاز دارد، فقط همان یک دایرکتوری را باز کنید، نه کل پروژه. این تفاوت بین یک آسیبپذیری محدود و یک سرور کاملاً در اختیار مهاجم است.
sudo در برابر su: کدام را انتخاب کنم
ورود مستقیم با کاربر root از طریق SSH را کنار بگذارید. نه به خاطر توصیهی کلیشهای، بلکه به این دلیل عملی که وقتی همه با یک حساب وارد میشوند، در /var/log/auth.log نمیفهمید کدام انسان کدام دستور را زده است. با sudo هر اجرا با نام کاربری واقعی ثبت میشود و میتوانید بعداً بپرسید چه کسی rm -rf را زده است.
| روش | مناسب برای | هزینهای که میپردازید |
|---|---|---|
sudo با کاربر شخصی | تیم چندنفره، سرور تولیدی | یک مرحلهی اضافه در هر دستور، نیاز به مدیریت /etc/sudoers |
su - با رمز روت | سرور تکنفره، تعمیر اضطراری | رمز روت مشترک میشود، ردپای کاربری از بین میرود |
| ورود مستقیم root با کلید SSH | هیچجا، بهجز لحظهی راهاندازی اولیه | هر اسکریپت خودکار میتواند کل سرور را ببرد |
اگر مجبورید برای یک اسکریپت خاص دسترسی بدون رمز بدهید، آن را محدود کنید، نه باز:
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp.service
این خط در /etc/sudoers.d/deploy فقط اجازهی ریاستارت یک سرویس مشخص را میدهد. اگر همان کاربر بخواهد bash را با sudo اجرا کند، رد میشود. تفاوت این دو حالت را وقتی میفهمید که یک توکن CI/CD لو برود.
روت و سرویسها: جایی که واقعاً خطر میسازید
بیشتر سرویسهای لینوکس امروز با کاربر اختصاصی و بدون روت اجرا میشوند. اگر unit سفارشی مینویسید و در آن User=root میگذارید، دارید یک آسیبپذیری احتمالی در Nginx یا Node.js را به یک نفوذ کامل تبدیل میکنید. ساختار درست unit و وابستگیها را در فایل unit در systemd میبینید، اما قاعدهی ساده این است: اگر سرویس به پورت زیر 1024 نیاز دارد، capability بدهید نه روت کامل.
[Service]
User=appuser
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
خط NoNewPrivileges=true را جدی بگیرید. بدون آن، هر پروسهی فرزند میتواند دوباره بالا برود و کل محدودیت را دور بزند.
وقتی روت تنها راه است
بعضی وقتها واقعاً راه دیگری نیست. بازیابی سروری که فایلسیستمش read-only شده، باز کردن قفل یک دیتابیس خراب، یا برگرداندن دسترسی SSH بعد از یک chmod اشتباه روی /etc/ssh. در این حالتها از کنسول اضطراری یا حالت rescue استفاده کنید، کار را تمام کنید، و بلافاصله بعدش بررسی کنید چه چیزی خراب شده بود. لاگها را قبل از هر تغییری بردارید؛ محل دقیق لاگ هر سرویس را در محل لاگ لینوکس فهرست کردهایم.
یک نکتهی عملی که کمتر گفته میشود: قبل از هر دستور مخرب با روت، مسیر فعلی را با pwd چک کنید و از rm -rf با متغیر خالی پرهیز کنید. الگوی rm -rf "$DIR"/* وقتی DIR خالی باشد به rm -rf /* تبدیل میشود. این خطا در سرورهای تولیدی واقعاً اتفاق میافتد و بازگرداندنش ساعتها طول میکشد.
پیکربندی SSH که واقعاً جلوی فاجعه را میگیرد
سه خط در /etc/ssh/sshd_config بیشترین اثر را دارند:
PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy admin
بعد از تغییر، قبل از بستن نشست فعلی، در یک ترمینال دوم تست کنید که ورود با کلید کار میکند. اگر این کار را نکنید و sshd را ریاستارت کنید، خودتان را از سرور بیرون انداختهاید و باید از کنسول وارد شوید. اگر پورت SSH را هم عوض میکنید، قواعد فایروال را قبل از ریاستارت اضافه کنید؛ مرجع سریع دستورات را در دستورات فایروال لینوکس داریم.
روی سرورهای تولیدی، این تنظیمات را در قالب تصویر اولیه یا اسکریپت provisioning بگذارید، نه دستی. اگر سرور اختصاصی یا ابری را تازه تحویل گرفتهاید، همین چند خط اولین کاری است که باید انجام دهید. برای بارهای کاری سبکتر، یک هاست لینوکس هم همین سطح از کنترل را میدهد بدون آنکه خودتان درگیر کرنل و پارتیشنبندی شوید.
پرسشهای پرتکرار
آیا غیرفعال کردن ورود روت از SSH کافی است؟
نه. PermitRootLogin no فقط ورود مستقیم را میبندد. اگر کاربری با sudo بدون رمز داشته باشید یا رمز ضعیف روی حساب دیگری باشد، مهاجم همان مسیر را میرود. باید PasswordAuthentication no را هم فعال کنید و کلیدها را مدیریت کنید.
چرا بعد از sudo، فایلهای ساختهشده مالک root هستند؟
چون دستور با UID صفر اجرا شده و فایلهای جدید با همان مالک ساخته میشوند. این باعث میشود سرویس بعداً نتواند آنها را بخواند یا تغییر دهد. راهحل، اجرای دستور با sudo -u www-data یا اصلاح مالکیت بعد از کار است.
تفاوت sudo و doas چیست و کدام را انتخاب کنم؟
doas سبکتر است و فایل پیکربندی سادهتری دارد، اما sudo امکانات بیشتری مثل ثبت لاگ تفصیلی و کنترل دقیق دستورات دارد. برای سرور تولیدی با چند اپراتور، sudo را انتخاب میکنم. برای یک ماشین شخصی که فقط میخواهید چند دستور را بالا ببرید، doas کافی است.
چطور بفهمم کسی از دسترسی روت سوءاستفاده کرده است؟
اول last و lastlog را ببینید، بعد grep sudo /var/log/auth.log را برای دستورات اجراشده چک کنید. کلیدهای ناشناس در ~/.ssh/authorized_keys و کرونجابهای جدید در /etc/cron.d دو جای رایج برای ماندگاری مهاجم هستند.
اگر فقط یک چیز از این متن بماند، این باشد: روت را برای کارهایی نگه دارید که واقعاً به آن نیاز دارند، و هر بار که به آن پناه میبرید، بپرسید مشکل اصلی چه بود. پاسخ تقریباً همیشه یک مجوز فایل است، نه کمبود دسترسی.