پرش به محتویات

۳. کاربران، گروه‌ها و مجوزها

کنترل دسترسی پایهٔ امنیت لینوکس است. اصل راهنما: حداقل دسترسی لازم (Least Privilege) برای هر کاربر و هر سرویس.

راهنمای سریع

فرمان کاربرد ریسک
id / whoami / getent passwd USER شناسایی کاربر بدون تغییر
last / lastlog / sudo lastb تاریخچهٔ ورود بدون تغییر
sudo -l -U USER مجوزهای sudo یک کاربر بدون تغییر
useradd / adduser / usermod ساخت و تغییر حساب تغییر
passwd -l / usermod -L / chage -E 0 قفل / منقضی‌کردن حساب تغییر
visudo ویرایش sudoers با اعتبارسنجی تغییر (اشتباه = قفل شدن از sudo)
userdel -r حذف حساب و پوشهٔ خانگی مخرب
setfacl / chown -R / chmod -R ACL و مجوز بازگشتی تغییر

شناسایی کاربران

whoami
id USER
getent passwd USER
getent group sudo              # RHEL: getent group wheel
getent passwd | less
last -n 20
lastlog | head
loginctl list-sessions         # نشست‌های فعال (systemd)

getent از پایگاه‌های پیکربندی‌شده سیستم (از جمله LDAP/SSSD در صورت تنظیم) پرس‌وجو می‌کند؛ معمولاً از خواندن مستقیم /etc/passwd جامع‌تر است.

ایجاد و مدیریت حساب

# Debian/Ubuntu (تعاملی)
sudo adduser appuser
# هر توزیع (غیرتعاملی)
sudo useradd -m -s /bin/bash -c "نام کامل" appuser
sudo passwd appuser

sudo usermod -aG GROUP appuser      # افزودن به گروه (بدون -a گروه‌های دیگر پاک می‌شود!)
sudo gpasswd -d appuser GROUP       # حذف از یک گروه
sudo usermod -s /bin/bash appuser
sudo chage -l appuser               # سیاست انقضای رمز
  • usermod -aG: افزودن به گروه بدون حذف گروه‌های فعلی؛ حذف -a عضویت‌های دیگر را از بین می‌برد.
  • گروه مدیران: Debian/Ubuntu → sudo؛ RHEL/Rocky → wheel.
  • اعمال عضویت جدید گروه نیاز به ورود دوباره کاربر دارد (id در نشست جاری عوض نمی‌شود).

عضویت در گروه docker = دسترسی root

هر کسی که عضو گروه docker باشد می‌تواند با docker run -v /:/host ... کل سیستم را بخواند و بنویسد؛ این معادل root بدون sudo و بدون لاگ sudo است. این گروه را مثل sudo مدیریت کنید (Docker).

حساب سرویس (Service account)

# بدون شل ورودی، بدون پوشهٔ خانگی، UID سیستمی
sudo useradd --system --no-create-home --shell /usr/sbin/nologin svc-myapp
sudo install -d -o svc-myapp -g svc-myapp -m 750 /var/lib/myapp
  • هر سرویس حساب جدا داشته باشد؛ هیچ سرویسی به‌عنوان root اجرا نشود مگر دلیل مستند.
  • حساب سرویس رمز ندارد و نباید ورود SSH داشته باشد (nologin + نبود authorized_keys).

غیرفعال‌سازی و حذف

sudo passwd -l appuser              # قفل رمز (SSH با کلید همچنان ممکن است!)
sudo usermod -L -e 1 appuser        # قفل رمز + منقضی‌کردن حساب (امن‌تر)
sudo chage -E 0 appuser             # منقضی فوری
sudo pkill -KILL -u appuser         # قطع همهٔ پردازش‌های او (با احتیاط)
sudo loginctl terminate-user appuser

# قبل از حذف: بکاپ و فایل‌های متعلق به او
sudo tar -czf /root/appuser-home-$(date +%F).tgz -C /home appuser
sudo find / -xdev -user appuser -ls 2>/dev/null | head
sudo userdel appuser                # حساب را حذف می‌کند، پوشه را نگه می‌دارد
sudo userdel -r appuser             # حساب + پوشهٔ خانگی (مخرب)

قفل‌کردن گذرواژه الزاماً حساب را از تمام روش‌های ورود غیرفعال نمی‌کند؛ کلید SSH (~/.ssh/authorized_keys)، توکن‌ها و cron/at باقی می‌مانند. هنگام خروج کارمند: حساب را منقضی کنید، authorized_keys را بررسی/حذف کنید، cron او را ببینید، سپس بعد از دورهٔ نگهداری حذف کنید.

مجوزهای فایل

مجوزهای rwx برای مالک (u)، گروه (g) و دیگران (o) تعریف می‌شوند.

عدد نماد کاربرد معمول
600 rw------- کلید خصوصی، فایل رمز، .env
640 rw-r----- فایل پیکربندی قابل‌خواندن برای گروه سرویس
644 rw-r--r-- فایل عمومی خواندنی
700 rwx------ پوشهٔ خصوصی (~/.ssh)
750 rwxr-x--- پوشهٔ سرویس با دسترسی گروه
755 rwxr-xr-x مسیر قابل‌پیمایش / اسکریپت عمومی
ls -l
chmod 600 ~/.ssh/id_ed25519
chmod 700 ~/.ssh
chmod 640 /etc/myapp/app.conf
chown root:root /etc/myapp/app.conf
namei -l /var/www/html/index.php     # مجوز همهٔ اجزای مسیر (علت رایج Permission denied)

برای پوشه‌ها x یعنی «اجازهٔ عبور». بدون x روی همهٔ پوشه‌های والد، فایلی که خودش 644 است هم خوانده نمی‌شود.

بیت‌های ویژه و umask

بیت عدد اثر مثال
setuid 4000 فایل با مجوز مالک اجرا می‌شود /usr/bin/passwd
setgid 2000 روی پوشه: فایل‌های جدید گروه پوشه را می‌گیرند پوشهٔ مشترک تیم
sticky 1000 روی پوشه: فقط مالک فایل می‌تواند حذفش کند /tmp (1777)
sudo chmod 2775 /srv/shared          # setgid: گروه پوشه به فایل‌های جدید ارث می‌رسد
sudo chmod +t /srv/dropbox
umask                                # پیش‌فرض ساخت: 022 → فایل 644، پوشه 755
umask 027                            # برای این نشست؛ فایل 640، پوشه 750

ACL

وقتی «مالک/گروه/دیگران» کافی نیست (مثلاً یک کاربر مشخص فقط یک فایل را بخواند):

getfacl /srv/shared
sudo setfacl -m u:reporter:r-- /srv/shared/report.csv
sudo setfacl -m u:reporter:rwx /srv/shared/reports
sudo setfacl -d -m g:team:rwX /srv/shared/reports   # پیش‌فرض برای فایل‌های جدید آینده
sudo setfacl -x u:reporter /srv/shared/report.csv   # حذف یک ورودی
sudo setfacl -b /srv/shared/report.csv              # حذف همهٔ ACL ها
getfacl -R /srv/shared | less

برای عبور از مسیر، دایرکتوری‌های والد نیز باید مجوز x مناسب داشته باشند. وجود ACL با + انتهای ls -l (مثل -rw-r--r--+) دیده می‌شود؛ آن را نادیده نگیرید.

sudo و امنیت حساب

sudo visudo                                   # ویرایش اصلی با اعتبارسنجی
sudo visudo -f /etc/sudoers.d/90-appteam      # ترجیحاً فایل جدا (drop-in)
sudo visudo -c                                # فقط بررسی نحو همهٔ فایل‌ها
sudo -l -U appuser

نمونهٔ drop-in حداقلی (فقط restart یک سرویس، بدون رمز):

# /etc/sudoers.d/90-appteam   (مجوز باید 0440 و مالک root باشد)
%appteam ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp, /usr/bin/systemctl status myapp
  • فرمان‌ها را با مسیر کامل و آرگومان دقیق مجاز کنید؛ NOPASSWD: ALL یا مجوز shell/editor (vim، less، find، docker) معادل root است.
  • فایل‌های /etc/sudoers.d با نام دارای . یا ~ نادیده گرفته می‌شوند (نگاه کنید sudo -l واقعاً آن را می‌بیند).
  • هرگز /etc/sudoers را با ویرایشگر معمولی باز نکنید؛ یک خطای نحوی کل sudo را از کار می‌اندازد.
  • لاگ sudo: /var/log/auth.log (Debian) / /var/log/secure (RHEL) / journalctl _COMM=sudo.

سیاست رمز و قفل خودکار

sudo chage -M 90 -m 1 -W 14 appuser     # حداکثر 90 روز، هشدار 14 روز قبل
sudo chage -l appuser
# قفل بعد از تلاش ناموفق (RHEL / pam_faillock)
sudo faillock --user appuser
sudo faillock --user appuser --reset

ممیزی حساب‌ها (دوره‌ای)

# فقط یک حساب باید UID 0 داشته باشد
awk -F: '$3 == 0 {print $1}' /etc/passwd

# حساب‌های بدون رمز
sudo awk -F: '($2 == "") {print $1}' /etc/shadow

# حساب‌های دارای شل ورودی
grep -vE '(nologin|false)$' /etc/passwd

# اعضای گروه‌های قدرتمند
getent group sudo wheel docker adm 2>/dev/null

# کلیدهای SSH مجاز همهٔ کاربران (شناسایی کلید ناشناس)
sudo find /home /root -name authorized_keys -exec sh -c 'echo "== $1"; cat "$1"' _ {} \;

# فایل‌های یتیم
sudo find / -xdev \( -nouser -o -nogroup \) -ls 2>/dev/null | head

خطاهای رایج

نشانه علت احتمالی روش بررسی
عضویت گروه جدید اثر ندارد نشست قدیمی است خروج و ورود دوباره؛ id
sudo: unable to resolve host نام میزبان در /etc/hosts نیست hostnamectl و /etc/hosts
بعد از ویرایش sudoers، sudo کار نمی‌کند خطای نحو pkexec visudo یا کنسول/ریکاوری؛ دفعهٔ بعد visudo -c
کاربر قفل است ولی هنوز SSH می‌زند ورود با کلید authorized_keys و chage -E 0
Permission denied با chmod 777 هم حل نشد SELinux/AppArmor یا ACL ls -Z ، getfacl ، ausearch -m avc
su: Authentication failure رمز اشتباه یا حساب root قفل است sudo -i یا حساب مدیر

نکات امنیتی و عملیاتی

  • فقط یک نفر/حساب برای هر هویت؛ حساب مشترک (admin) ردپا را از بین می‌برد.
  • ورود مستقیم root را غیرفعال کنید (SSH) و از sudo استفاده کنید تا هر کار به یک انسان برسد.
  • مجوز اجرا برای فایل‌های داده و 755 برای فایل‌های معمولی نگذارید.
  • تغییرات کاربران و sudoers را در تیکت ثبت کنید.

خلاصهٔ اجرایی

  1. حساب سرویس: --system، nologin، بدون رمز.
  2. گروه docker و مجوزهای shell در sudoers = root؛ محدود کنید.
  3. حساب خروجی: قفل رمز و chage -E 0 و بررسی authorized_keys.
  4. فقط با visudo (ترجیحاً drop-in) و با فرمان‌های دقیق.
  5. ماهانه ممیزی: UID 0، رمز خالی، کلیدهای SSH، اعضای گروه‌های ویژه.