آموزش SSH Key و اتصال امن به سرور لینوکس

خلاصه آموزش SSH Key برای اتصال امن به سرور لینوکس: روی سیستم خودتان با دستور ssh-keygen -t ed25519 یک جفت کلید بسازید، کلید عمومی را با ssh-copy-id به فایل authorized_keys سرور اضافه کنید، ورود با کلید را در یک پنجره جدید تست کنید و بعد در sshd_config ورود با رمز عبور را غیرفعال کنید. کلید خصوصی هرگز نباید از سیستم شما خارج شود.

مراحل زیر برای کسی است که سرور لینوکس (مجازی یا اختصاصی) دارد و می‌خواهد ورود با رمز عبور را با کلید جایگزین کند. اگر تازه با لینوکس شروع کرده‌اید، لینوکس چیست و دستورات پایه لینوکس را ببینید. SSH فقط یکی از لایه‌های امنیت سرور است و تصویر کامل‌تر را در راهنمای امنیت لینوکس می‌یابید. دستورها بر اساس مستندات رسمی OpenSSH (شاخه 10.x) و Microsoft نوشته شده‌اند و روی توزیع‌های رایج مانند Ubuntu، Debian و خانواده RHEL قابل استفاده‌اند.

SSH Key چیست و چرا از رمز عبور امن‌تر است؟

SSH Key یک جفت کلید رمزنگاری است: کلید خصوصی (Private Key) که فقط روی سیستم شما می‌ماند و کلید عمومی (Public Key) که روی سرور قرار می‌گیرد. هنگام اتصال، سرور از کلاینت می‌خواهد ثابت کند کلید خصوصی متناظر را دارد و کلاینت این کار را با امضای دیجیتال انجام می‌دهد؛ خود کلید خصوصی هیچ‌وقت روی شبکه ارسال نمی‌شود.

در مقایسه با رمز عبور، کلید قابل حدس زدن نیست و حملات Brute Force روی آن عملاً بی‌اثر است. اگر سرور مقصد هم آلوده شده باشد، مهاجم فقط کلید عمومی شما را به دست می‌آورد و به رمزی که شاید در سرورهای دیگر هم به کار برده باشید نمی‌رسد. نقطه ضعف اصلی، خود فایل کلید خصوصی است؛ به همین دلیل آن را با یک Passphrase رمزگذاری کنید.

آموزش SSH Key: کدام نوع کلید را انتخاب کنیم؟

نوع کلیدوضعیتکاربرد
Ed25519پیشنهاد اصلی؛ نوع پیش‌فرض ssh-keygen در نسخه‌های جدید OpenSSHکلید کوتاه، سریع و امن برای تقریباً همه سرورهای امروزی
RSA با حداقل 3072 بیتهمچنان پشتیبانی می‌شودفقط برای سیستم‌ها یا تجهیزات قدیمی که Ed25519 را نمی‌شناسند
ECDSAپشتیبانی می‌شودوقتی الزام سازمانی به منحنی‌های NIST وجود دارد
Ed25519-SK و ECDSA-SKنیازمند کلید سخت‌افزاری FIDO2کلید خصوصی بدون حضور فیزیکی کلید سخت‌افزاری قابل استفاده نیست
DSAحذف‌شدهدر OpenSSH 10 به‌طور کامل حذف شده و نباید استفاده شود

ساخت SSH Key در لینوکس و macOS

ترمینال را باز کنید و دستور زیر را اجرا کنید. بخش ‎-C فقط یک توضیح است که بعداً کمک می‌کند بدانید هر کلید متعلق به کدام دستگاه است:

ssh-keygen -t ed25519 -C "ali@work-laptop"

ssh-keygen مسیر ذخیره را می‌پرسد؛ با Enter مسیر پیش‌فرض انتخاب می‌شود. سپس Passphrase را دو بار وارد کنید. نتیجه دو فایل است:

  • ~/.ssh/id_ed25519: کلید خصوصی؛ آن را با کسی به اشتراک نگذارید و در ایمیل، پیام‌رسان یا مخزن Git قرار ندهید.
  • ~/.ssh/id_ed25519.pub: کلید عمومی؛ این فایل روی سرورها قرار می‌گیرد.

اگر برای هر پروژه کلید جداگانه می‌خواهید، نام فایل را با ‎-f تعیین کنید. گزینه ‎-a تعداد تکرار تابع مشتق‌سازی کلید را بالا می‌برد تا در صورت سرقت فایل، حدس زدن Passphrase دشوارتر شود:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_projectx -C "projectx-deploy"

# Change the passphrase of an existing key
ssh-keygen -p -f ~/.ssh/id_ed25519

ساخت SSH Key در ویندوز

با OpenSSH داخلی ویندوز

ویندوز ۱۰ (نسخه 1809 به بعد) و ویندوز ۱۱ کلاینت OpenSSH را به‌صورت داخلی دارند. PowerShell یا Windows Terminal را باز کنید و همان دستور را اجرا کنید. فایل‌ها در پوشه C:\Users\USERNAME\.ssh ذخیره می‌شوند. جزئیات بیشتر در مستندات Microsoft درباره احراز هویت با کلید در OpenSSH آمده است.

ssh-keygen -t ed25519 -C "ali@windows-pc"

با PuTTYgen

اگر از PuTTY استفاده می‌کنید، آخرین نسخه را فقط از صفحه رسمی دانلود PuTTY دریافت کنید (در زمان نگارش نسخه 0.85) و این مراحل را انجام دهید:

  1. PuTTYgen را اجرا کنید و در بخش Parameters گزینه EdDSA را با منحنی Ed25519 انتخاب کنید.
  2. روی Generate کلیک و ماوس را در کادر خالی حرکت دهید تا کلید ساخته شود.
  3. در فیلدهای Key passphrase و Confirm passphrase، رمز کلید را وارد کنید.
  4. با Save private key، کلید خصوصی را با پسوند ‎.ppk ذخیره کنید.
  5. متن کادر Public key for pasting into OpenSSH authorized_keys file را کپی کنید؛ این همان کلید عمومی است که روی سرور قرار می‌گیرد.
  6. در PuTTY، مسیر Connection → SSH → Auth → Credentials را باز و فایل ‎.ppk را در Private key file for authentication انتخاب کنید.

برای استفاده از کلید OpenSSH در PuTTY، از منوی Conversions گزینه Import key و برای تبدیل برعکس، Export OpenSSH key را انتخاب کنید. برنامه Pageant هم نقش ssh-agent را برای PuTTY بازی می‌کند.

انتقال کلید عمومی به سرور

روش پیشنهادی: ssh-copy-id

در لینوکس ساده‌ترین روش ssh-copy-id است. این دستور یک بار با رمز عبور وارد سرور می‌شود، کلید عمومی را به فایل ‎~/.ssh/authorized_keys کاربر مقصد اضافه می‌کند و دسترسی‌های لازم را تنظیم می‌کند. اگر در macOS این دستور در دسترس نبود، از روش دستی استفاده کنید.

ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@203.0.113.10

# If SSH listens on a non-default port
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 deploy@203.0.113.10

در این مثال deploy یک کاربر عادی با دسترسی sudo و ‎203.0.113.10 یک آدرس نمونه است.

از ویندوز با PowerShell

ویندوز ssh-copy-id ندارد، اما می‌توانید محتوای کلید عمومی را از طریق خود SSH به سرور لینوکس بفرستید:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

روش دستی

اگر ورود SSH با رمز عبور ندارید و فقط کنسول پنل سرور در اختیارتان است، محتوای فایل ‎.pub را کپی کنید و روی سرور با کاربر مقصد این دستورها را اجرا کنید. هر کلید باید در یک خط کامل و بدون شکستگی قرار بگیرد:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys    # paste the public key on a single line
chmod 600 ~/.ssh/authorized_keys

پیش از بستن رمز عبور، ورود با کلید را تست کنید

نشست فعلی را باز نگه دارید تا اگر ورود با کلید کار نکرد، دسترسی‌تان به سرور قطع نشود. سپس در یک پنجره ترمینال جدید اجرا کنید:

ssh -i ~/.ssh/id_ed25519 deploy@203.0.113.10

# Show which authentication method succeeded
ssh -v deploy@203.0.113.10 true 2>&1 | grep -i "authenticated"

اگر در خروجی عبارت using “publickey” را دیدید و به جای رمز عبور کاربر فقط Passphrase کلید از شما خواسته شد، کلید درست کار می‌کند.

غیرفعال کردن ورود با رمز عبور در sshd_config

تنظیمات سرویس SSH در فایل ‎/etc/ssh/sshd_config قرار دارد. پیش از ویرایش، این دو نکته از مستندات رسمی sshd_config را در نظر بگیرید:

  • برای بیشتر گزینه‌ها، sshd اولین مقداری را که می‌خواند اعمال می‌کند و مقادیر بعدی همان گزینه نادیده گرفته می‌شوند.
  • در نسخه‌های جدید Ubuntu و Debian و در RHEL 9 و مشتقات آن، خط Include /etc/ssh/sshd_config.d/*.conf در ابتدای فایل اصلی قرار دارد و فایل‌های این پوشه به ترتیب الفبایی نام خوانده می‌شوند. در برخی ایمیج‌های ابری، فایلی مانند 50-cloud-init.conf مقدار PasswordAuthentication yes را تنظیم می‌کند و تغییر شما در فایل اصلی بی‌اثر می‌ماند.

برای همین، تنظیمات را در فایل جداگانه‌ای بگذارید که نامش زودتر از بقیه خوانده شود:

# /etc/ssh/sshd_config.d/00-hardening.conf
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PermitEmptyPasswords no
MaxAuthTries 3
AllowUsers deploy
گزینهمقدارتوضیح
PubkeyAuthenticationyesورود با کلید (مقدار پیش‌فرض هم yes است)
PasswordAuthenticationnoورود با رمز عبور بسته می‌شود؛ مقدار پیش‌فرض yes است
KbdInteractiveAuthenticationnoChallengeResponseAuthentication نام مستعار منسوخ همین گزینه است؛ اگر باز بماند، از مسیر PAM ممکن است هنوز بتوان با رمز وارد شد
PermitRootLoginno یا prohibit-passwordno ورود root را کاملاً می‌بندد؛ prohibit-password (پیش‌فرض OpenSSH) ورود root را فقط با کلید مجاز می‌کند
MaxAuthTries3حداکثر تلاش احراز هویت در هر اتصال؛ پیش‌فرض 6 است
AllowUsersdeployفقط کاربران نام‌برده اجازه ورود دارند؛ نام همه کاربران مجاز را با فاصله بنویسید

مقدار no یا prohibit-password برای root؟

اگر با یک کاربر عادی و sudo کار می‌کنید، PermitRootLogin no امن‌تر است، چون حتی با سرقت کلید، مهاجم مستقیم به root نمی‌رسد. prohibit-password برای حالتی مناسب است که ابزاری مانند اسکریپت بکاپ یا سیستم اتوماسیون ناچار است با root و کلید وارد شود. پیش از قرار دادن no مطمئن شوید کاربر deploy واقعاً می‌تواند sudo اجرا کند؛ روش ساخت کاربر و مدیریت sudo را در مدیریت دسترسی در لینوکس ببینید.

بررسی و اعمال تنظیمات

پیش از راه‌اندازی مجدد سرویس، درستی نحو فایل‌ها را با sshd -t بررسی کنید و با sshd -T مقدار نهایی هر گزینه را ببینید. خروجی sshd -T همان مقداری است که sshd واقعاً اعمال می‌کند، پس اثر فایل‌های sshd_config.d را هم آشکار می‌کند:

sudo sshd -t
sudo sshd -T | grep -Ei "passwordauthentication|kbdinteractiveauthentication|permitrootlogin|pubkeyauthentication"

# Debian / Ubuntu
sudo systemctl restart ssh

# RHEL / Rocky Linux / AlmaLinux
sudo systemctl restart sshd

راه‌اندازی مجدد سرویس SSH نشست‌های باز فعلی را قطع نمی‌کند. پس از آن، باز هم در یک پنجره جدید ورود با کلید را تست کنید و فقط در صورت موفقیت نشست قدیمی را ببندید. اگر دسترسی را از دست دادید، از کنسول VNC یا پنل مدیریت سرور وارد شوید و تنظیمات را اصلاح کنید.

درباره تغییر پورت SSH

تغییر پورت 22 تعداد تلاش‌های خودکار در لاگ‌ها را کم می‌کند، اما جایگزین کلید و بستن رمز عبور نیست. اگر پورت را تغییر می‌دهید، ابتدا پورت جدید را در فایروال باز کنید (آموزش کانفیگ iptables در لینوکس)، روی سیستم‌های دارای SELinux پورت جدید را برای SSH تعریف کنید و در Ubuntu 22.10 و نسخه‌های جدیدتر که SSH به‌صورت socket-activated اجرا می‌شود، پس از تغییر دستورهای systemctl daemon-reload و systemctl restart ssh.socket را اجرا کنید.

مدیریت کلیدها با ssh-agent

اگر روی کلید Passphrase گذاشته‌اید، ssh-agent آن را یک بار باز می‌کند و در حافظه نگه می‌دارد تا در هر اتصال دوباره از شما پرسیده نشود. در ویندوز، سرویس ssh-agent به‌صورت پیش‌فرض غیرفعال است و دو دستور اول بخش ویندوز باید در PowerShell با دسترسی Administrator اجرا شوند:

# Linux
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l

# macOS: store the passphrase in Keychain
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# Windows PowerShell (first two commands as Administrator)
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

درباره Agent Forwarding (گزینه ‎-A یا ForwardAgent) احتیاط کنید: کسی که روی سرور مقصد دسترسی root دارد، تا زمان باز بودن اتصال می‌تواند از Agent شما برای ورود به سرورهای دیگر استفاده کند. برای عبور از یک سرور واسط، به جای آن از ProxyJump استفاده کنید.

ساده‌سازی اتصال با فایل ssh config

به جای نوشتن IP، کاربر، پورت و مسیر کلید در هر اتصال، آن‌ها را در فایل ‎~/.ssh/config (در ویندوز C:\Users\USERNAME\.ssh\config) تعریف کنید:

Host web01
    HostName 203.0.113.10
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
    AddKeysToAgent yes

Host db01
    HostName 10.0.0.21
    User deploy
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump web01

حالا کافی است بنویسید ssh web01. گزینه IdentitiesOnly باعث می‌شود فقط کلید مشخص‌شده امتحان شود و ProxyJump اتصال به db01 را که فقط از داخل شبکه خصوصی در دسترس است از طریق web01 برقرار می‌کند، بدون اینکه کلید خصوصی شما روی web01 قرار بگیرد.

رفع خطاهای رایج SSH Key

خطای Permission denied (publickey)

رایج‌ترین علت، دسترسی نادرست فایل‌ها روی سرور است. گزینه StrictModes (پیش‌فرض yes) باعث می‌شود sshd اگر پوشه خانه، ‎~/.ssh یا authorized_keys برای کاربران دیگر قابل نوشتن باشد، کلید را نپذیرد. دسترسی مناسب هر مسیر در جدول زیر آمده است:

مسیردسترسی مناسب
پوشه خانه کاربر روی سروربدون دسترسی نوشتن برای group و others
‎~/.ssh700
‎~/.ssh/authorized_keys600
کلید خصوصی روی کلاینت600
کلید عمومی (‎.pub)644
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R deploy:deploy ~/.ssh

# RHEL family with SELinux enforcing
restorecon -Rv ~/.ssh

# Read the reason in the server log
sudo journalctl -u ssh -n 50 --no-pager     # Debian / Ubuntu
sudo journalctl -u sshd -n 50 --no-pager    # RHEL / Rocky / AlmaLinux

علت‌های دیگر: کلید در authorized_keys کاربر دیگری قرار گرفته، خط کلید هنگام کپی شکسته شده، یا AllowUsers نام کاربر را شامل نمی‌شود.

هشدار UNPROTECTED PRIVATE KEY FILE

این پیام روی کلاینت یعنی فایل کلید خصوصی برای کاربران دیگر قابل خواندن است و SSH از استفاده آن خودداری می‌کند. در لینوکس و macOS دستور chmod 600 ~/.ssh/id_ed25519 را اجرا کنید. در ویندوز از Properties → Security فایل، ارث‌بری دسترسی را غیرفعال کنید و فقط حساب کاربری خودتان را باقی بگذارید.

خطای Too many authentication failures

وقتی چند کلید در ssh-agent بارگذاری شده، کلاینت ممکن است همه را امتحان کند و پیش از رسیدن به کلید درست به سقف MaxAuthTries سرور برسد. در فایل config برای آن سرور IdentityFile و IdentitiesOnly yes را تعیین کنید.

سرور هنوز رمز عبور را می‌پذیرد

خروجی sshd -T را بررسی کنید. اگر PasswordAuthentication هنوز yes است، فایلی در پوشه sshd_config.d مقدار شما را بازنویسی کرده است. با دستور زیر آن را پیدا و اصلاح کنید، یا فایل تنظیمات خود را با نامی بسازید که زودتر خوانده شود:

sudo grep -ri "passwordauthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

هشدار REMOTE HOST IDENTIFICATION HAS CHANGED

این پیام یعنی کلید میزبان سرور با آنچه قبلاً در known_hosts ذخیره شده متفاوت است. اگر مطمئن هستید سرور دوباره نصب شده یا IP به سرور جدیدی داده شده، رکورد قدیمی را با ssh-keygen -R 203.0.113.10 حذف کنید. اگر دلیل تغییر را نمی‌دانید اتصال را ادامه ندهید، چون ممکن است حمله مرد میانی باشد.

سوالات متداول

اگر کلید خصوصی گم شود یا لپ‌تاپ سرقت شود چه کنم؟

از دستگاه یا کنسول دیگری وارد سرورها شوید و خط مربوط به آن کلید را از ‎~/.ssh/authorized_keys همه سرورها حذف کنید، سپس کلید جدید بسازید. به همین دلیل برای هر دستگاه کلید جداگانه با توضیح مشخص (‎-C) بسازید تا لغو دسترسی یک دستگاه ساده باشد.

آیا گذاشتن Passphrase روی SSH Key ضروری است؟

برای کلید شخصی بله؛ بدون Passphrase هر کسی که به فایل کلید دسترسی پیدا کند به همه سرورهای شما دسترسی دارد. با ssh-agent مجبور نیستید هر بار آن را وارد کنید.

آیا می‌توان از یک کلید برای چند سرور استفاده کرد؟

بله، کلید عمومی را می‌توان روی هر تعداد سرور قرار داد و این کار امنیت را کم نمی‌کند، چون کلید عمومی محرمانه نیست. اما برای هر دستگاه کلاینت کلید جداگانه بسازید و کلید خصوصی را بین دستگاه‌ها کپی نکنید.

Ed25519 بهتر است یا RSA؟

برای سرورهای امروزی Ed25519 انتخاب پیشنهادی است و ssh-keygen در نسخه‌های جدید OpenSSH به‌صورت پیش‌فرض آن را می‌سازد. RSA را فقط برای سیستم‌هایی به کار ببرید که Ed25519 را پشتیبانی نمی‌کنند و در این صورت طول کلید را کمتر از 3072 بیت انتخاب نکنید.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *