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

۸. SSH و مدیریت راه دور

SSH درِ اصلی هر سرور است؛ هم مهم‌ترین ابزار شما و هم اولین هدف مهاجم. دو قانون: هرگز خودتان را بیرون نکنید (نشست فعلی را تا تأیید اتصال جدید باز نگه دارید) و هر تغییر را اول اعتبارسنجی کنید (sshd -t).

راهنمای سریع

فرمان کاربرد ریسک
ssh -v / ssh -G HOST عیب‌یابی اتصال / تنظیمات مؤثر کلاینت بدون تغییر
sudo sshd -t / sudo sshd -T اعتبارسنجی / تنظیمات مؤثر سرور بدون تغییر
ssh-keygen -lf اثرانگشت کلید بدون تغییر
scp / rsync / sftp انتقال فایل تغییر
ssh-copy-id / ssh-keygen -R نصب کلید / حذف host key قدیمی تغییر
ویرایش sshd_config + reload سخت‌گیری مخرب (قفل شدن از سرور)
rsync --delete همگام‌سازی با حذف مخرب

اتصال و کپی فایل

ssh admin@SERVER_IP
ssh -p 2222 admin@SERVER_IP
ssh admin@SERVER_IP 'uptime; df -h /'                     # اجرای یک فرمان
ssh -t admin@SERVER_IP 'sudo systemctl status nginx'      # -t: برای فرمان‌های تعاملی (sudo)
scp ./file.txt admin@SERVER_IP:/tmp/
scp admin@SERVER_IP:/var/log/syslog ./syslog.remote
rsync -avh --progress ./project/ admin@SERVER_IP:/opt/project/
rsync -avhn ./project/ admin@SERVER_IP:/opt/project/      # -n: فقط نشان بده، انجام نده
sftp admin@SERVER_IP

در rsync، اسلش انتهای مسیر مبدأ مهم است: source/ محتویات را کپی می‌کند؛ source خود پوشه را هم در مقصد ایجاد می‌کند. همیشه اول با -n تست کنید. scp در نسخه‌های جدید OpenSSH از پروتکل SFTP استفاده می‌کند و برای کارهای جدی rsync/sftp ترجیح دارد.

کلید SSH

ssh-keygen -t ed25519 -C "admin@workstation"
ssh-copy-id admin@SERVER_IP
ssh -i ~/.ssh/id_ed25519 admin@SERVER_IP
ssh-add ~/.ssh/id_ed25519
ssh-add -l
ssh-keygen -lf ~/.ssh/id_ed25519.pub        # اثرانگشت (برای مقایسه)

کلید خصوصی را منتشر نکنید و برای آن passphrase در نظر بگیرید. مجوزهای رایج: ~/.ssh برابر 700 و کلید خصوصی برابر 600. برای هر شخص/دستگاه کلید جدا بسازید تا بتوان یکی را ابطال کرد.

محدودکردن کلید در authorized_keys

هر خط ~/.ssh/authorized_keys می‌تواند گزینه داشته باشد (پیش از نوع کلید):

# فقط از این شبکه، بدون tunnel/pty، و فقط یک فرمان (مثلاً حساب بکاپ)
from="192.0.2.0/24",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="/usr/local/bin/backup-receive" ssh-ed25519 AAAA... backup@host

فایل ~/.ssh/config (کلاینت)

# ~/.ssh/config   (مجوز 600)
Host bastion
    HostName 192.0.2.5
    User admin
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Host app-*
    User admin
    ProxyJump bastion          # عبور از bastion بدون agent forwarding
    ServerAliveInterval 30
    ServerAliveCountMax 3

Host app-prod1
    HostName 198.51.100.11
ssh app-prod1                  # از طریق bastion
ssh -J admin@192.0.2.5 admin@198.51.100.11    # یک‌باره، بدون config
ssh -G app-prod1 | grep -Ei '^(hostname|user|proxyjump|identityfile) '

از ForwardAgent yes (ssh -A) روی میزبان‌های غیرقابل‌اعتماد بپرهیزید: root آن سرور می‌تواند از agent شما سوءاستفاده کند. ProxyJump راه امن‌تر است.

تنظیمات و عیب‌یابی

ssh -v admin@SERVER_IP
ssh -vvv admin@SERVER_IP
sudo sshd -t
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|pubkeyauthentication|allowusers|port'
sudo systemctl status ssh
sudo journalctl -u ssh --since '-30 min'

در برخی توزیع‌ها نام سرویس sshd است (RHEL) و در بعضی ssh (Debian/Ubuntu؛ alias sshd هم معمولاً هست). sshd -T مقدار مؤثر نهایی را نشان می‌دهد؛ تنها منبع قابل‌اعتماد برای اینکه «چه چیزی واقعاً فعال است».

رویهٔ ایمن تغییر sshd (بدون قفل شدن)

  1. نشست فعلی را باز نگه دارید و یک نشست دوم (یا کنسول) آماده داشته باشید.
  2. نسخهٔ پشتیبان: sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
  3. اعمال تغییر، سپس sudo sshd -t (نباید خروجی بدهد).
  4. sudo sshd -T | grep ... برای تأیید مقدار مؤثر.
  5. sudo systemctl reload ssh (نه restart؛ reload اتصال‌های موجود را نمی‌کشد).
  6. از نشست جدید وارد شوید و تأیید کنید؛ فقط بعد از آن نشست قدیمی را ببندید.
  7. شبکه‌ای که ممکن است بعد از تغییر دسترسی نداشته باشد (فایروال): یک «برگرداننده» زمان‌دار: echo 'cp /etc/ssh/sshd_config.bak.DATE /etc/ssh/sshd_config && systemctl reload ssh' | sudo at now + 10 minutes و بعد از تأیید atrm.

پیکربندی امن‌تر

فایل معمولاً /etc/ssh/sshd_config یا فایل‌های زیر /etc/ssh/sshd_config.d/ است.

# /etc/ssh/sshd_config.d/10-hardening.conf   (نمونه)
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
AllowUsers admin1 admin2
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2

ترتیب فایل‌های sshd_config.d: اولین مقدار برنده است

در OpenSSH برای هر گزینه اولین مقدار خوانده‌شده معتبر است و فایل‌های .d به ترتیب حروف‌الفبا خوانده می‌شوند. فایل‌های cloud-init (مثل 50-cloud-init.conf با PasswordAuthentication yes) ممکن است تنظیم شما را بی‌اثر کنند. نام فایل خود را با عدد کوچک بگذارید (10-…) و حتماً با sshd -T مقدار مؤثر را ببینید، نه فقط فایل را.

  • ورود مستقیم root را در صورت امکان غیرفعال کنید.
  • احراز هویت کلیدی را ترجیح دهید، اما قبل از غیرفعال‌کردن گذرواژه، ورود کلیدی را از یک نشست جداگانه آزمایش کنید.
  • دسترسی کاربران را با AllowUsers یا AllowGroups محدود کنید.
  • تغییر پورت به‌تنهایی جایگزین کنترل دسترسی و به‌روزرسانی نیست (فقط نویز لاگ را کم می‌کند).
  • محدودکردن منبع با فایروال (ufw allow from 192.0.2.0/24 to any port 22) از هر تنظیم sshd مؤثرتر است.
  • ضد brute-force: fail2ban یا sshguard (امنیت).

تونل SSH

# تونل محلی: پورت محلی 15432 به پورت 5432 سرور مقصد
ssh -N -L 15432:127.0.0.1:5432 admin@SERVER_IP
# تونل معکوس: پورت 9000 روی سرور به سرویس محلی شما
ssh -N -R 9000:127.0.0.1:3000 admin@SERVER_IP
# SOCKS proxy پویا
ssh -N -D 1080 admin@SERVER_IP
# پس‌زمینه
ssh -f -N -L 15432:127.0.0.1:5432 admin@SERVER_IP

تونل را فقط برای سرویس‌هایی ایجاد کنید که مجاز به دسترسی به آن‌ها هستید؛ فراموش نکنید که تونل ممکن است کنترل‌های شبکه‌ای را دور بزند. تونل‌های پس‌زمینه را ببینید و ببندید: ps aux | grep 'ssh -f'.

هشدار تغییر کلید میزبان

@@@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @@@

این پیام یا یعنی سرور بازسازی/تعویض شده (بی‌خطر)، یا حملهٔ man-in-the-middle. قبل از هر کاری اثرانگشت را از راه امن دیگر (کنسول) با ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub مقایسه کنید؛ فقط بعد از اطمینان:

ssh-keygen -R SERVER_IP

StrictHostKeyChecking no را به‌صورت عمومی تنظیم نکنید.

خطاهای رایج

نشانه علت احتمالی روش بررسی
Permission denied (publickey) کلید نصب نیست/مجوزها اشتباه/کاربر ممنوع ssh -v ؛ سرور: journalctl -u ssh
Authentication refused: bad ownership or modes مجوز ~، ~/.ssh یا authorized_keys زیادی باز است chmod go-w ~ ; chmod 700 ~/.ssh ; chmod 600 ~/.ssh/authorized_keys
Too many authentication failures agent کلیدهای زیادی می‌فرستد ssh -o IdentitiesOnly=yes -i KEY
Connection refused sshd اجرا نیست / پورت اشتباه systemctl status ssh ، ss -lntp \| grep sshd
Connection timed out فایروال/مسیر/IP اشتباه nc -vz IP 22 ، traceroute
بعد از reload دسترسی نیست سینتکس/AllowUsers/فایروال کنسول؛ sshd -t ؛ برگرداندن بکاپ
تنظیم PasswordAuthentication اثر ندارد فایل .d با اولویت بالاتر sshd -T \| grep passwordauth
نشست بعد از چند دقیقه می‌میرد NAT/فایروال idle timeout ServerAliveInterval 30 ؛ tmux

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

  • کلید خصوصی بدون passphrase روی لپ‌تاپ = دسترسی به همهٔ سرورها اگر لپ‌تاپ برود. از ssh-agent + passphrase یا کلید سخت‌افزاری استفاده کنید.
  • کلید کارمند خارج‌شده را از همهٔ authorized_keysها حذف کنید (فهرست‌برداری: ممیزی حساب‌ها).
  • لاگ ورودها را مرکزی کنید؛ Accepted publickey از IP/ساعت غیرعادی را هشدار دهید.
  • ساعت و مجوز فایل‌ها را در ~/.ssh دوره‌ای بازبینی کنید.

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

  1. تغییر sshd: sshd -t ← sshd -T ← reload ← نشست جدید ← فقط بعد نشست قدیمی را ببند.
  2. مقدار مؤثر را با sshd -T بخوانید (ترتیب .d مهم است).
  3. ProxyJump به‌جای agent forwarding؛ کلید با passphrase.
  4. هشدار تغییر host key را جدی بگیرید.