آموزش مدیریت کلیدهای SSH و امنیت دسترسی به سرور
راهنمای جامع مدیریت کلیدهای SSH برای امنیت سرور. یاد بگیرید چگونه از الگوریتم ed25519 استفاده کنید، مجوزهای فایل sshd را تنظیم کرده و با فایل config دسترسیها را مدیریت کنید.
نحوه عملکرد کلیدهای SSH
یک کلید SSH شامل دو فایل است: یک کلید خصوصی که روی دستگاه شما باقی میماند و یک کلید عمومی که آن را در هر سروری که قصد ورود به آن را دارید، کپی میکنید. هنگام اتصال، سرور از کلید عمومی برای ارسال یک چالش (challenge) استفاده میکند که تنها کلید خصوصی متناظر قادر به پاسخگویی به آن است. کلید خصوصی هرگز دستگاه شما را ترک نمیکند، بنابراین هیچ راز امنیتی در شبکه جابهجا نمیشود و در صورت نفوذ به یک سرور، چیزی برای سرقت وجود ندارد. به همین دلیل است که کلیدها از رمزهای عبور امنتر هستند. مدیریت صحیح کلیدهای SSH به چهار عادت خلاصه میشود: یک کلید برای هر دستگاه، رعایت مجوزهای فایل مورد نیاز sshd، استفاده از فایل ~/.ssh/config برای جلوگیری از تایپ مکرر گزینهها، و دانستن نحوه حذف کلید در روزی که لپتاپ گم میشود.
این راهنما هر یک از این عادتها را در Ubuntu 24.04 پوشش میدهد، اگرچه تقریباً تمام موارد ذکر شده در اینجا برای هر سرور لینوکسی و هر نسخه جدید OpenSSH قابل اجرا است.
پیش از شروع، یک نکته واژگانی را مد نظر داشته باشید، زیرا از اشتباهات جدی جلوگیری میکند. کلید عمومی محرمانه نیست. شما میتوانید آن را در یک تیکت قرار دهید، از طریق ایمیل ارسال کنید یا منتشر کنید و هیچکس نمیتواند با استفاده از آن وارد سیستم شود. کلید خصوصی همان بخش محرمانه است. هر کسی که آن فایل را کپی کند و رمز عبور آن (در صورت وجود) را بداند، از نظر سرورهای شما، خودِ شما محسوب میشود.
ایجاد یک کلید: ed25519 گزینه پیشفرض مناسب است
روی کامپیوتر شخصی خود، نه روی سرور، دستور زیر را اجرا کنید:
ssh-keygen -t ed25519 -C "laptop"-t ed25519 نوع کلید را تعیین میکند. Ed25519 گزینه پیشفرض مدرن است: کلیدها کوتاه و سریع هستند و توسط تمام نسخههای OpenSSH از سال 2014 به بعد پشتیبانی میشوند. تنها زمانی به سراغ ssh-keygen -t rsa -b 4096 بروید که مجبور به برقراری ارتباط با دستگاه قدیمی هستید که از ed25519 پشتیبانی نمیکند. -C "laptop" یک توضیح (comment) تعیین میکند. این توضیح هیچ نقش رمزنگاری ندارد، اما روشی است که با آن میتوانید این کلید را در فایل authorized_keys سرور در دو سال آینده شناسایی کنید؛ بنابراین نام دستگاهی که کلید روی آن قرار دارد را انتخاب کنید.
ssh-keygen محل ذخیره کلید را میپرسد. مقدار پیشفرض، یعنی ~/.ssh/id_ed25519 را بپذیرید. سپس از شما یک passphrase میخواهد. حتماً یک مورد تنظیم کنید؛ بخش مربوط به passphrase در ادامه توضیح میدهد که چرا این کار در استفاده روزمره هیچ هزینهای برای شما ندارد. در نهایت دو فایل خواهید داشت: ~/.ssh/id_ed25519 که کلید خصوصی است و ~/.ssh/id_ed25519.pub که کلید عمومی است. نیمه عمومی را مشاهده کنید:
cat ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptopاین یک خط شامل موارد زیر است: نوع کلید، محتوای کلید و توضیح شما. همان خطی که در نهایت باید روی سرورهای خود قرار دهید.
یک کلید برای هر دستگاه، نه یک کلید برای هر سرور
سؤالی که همه در ابتدا میپرسند این است: آیا برای هر سرور به یک کلید جدید نیاز دارم؟ خیر. برای هر دستگاهی که با آن تایپ میکنید یک کلید بسازید و آن کلید عمومی را روی تمام سرورهایی که دستگاه باید به آنها دسترسی داشته باشد، قرار دهید. این کلید، دستگاه را شناسایی میکند. فایل authorized_keys روی هر سرور، فهرستی از دستگاههای مجاز است.
این مدلی است که مقیاسپذیر است و روشهای جایگزین، به شیوههای قابل پیشبینی شکست میخورند. داشتن یک کلید برای هر سرور به این معناست که یک لپتاپ با 20 سرور، 20 کلید خصوصی حمل میکند و شما ردِ اینکه کدام کلید مربوط به کدام سرور است را گم خواهید کرد. استفاده از یک کلید مشترک برای تمام دستگاهها بدتر است: وقتی لپتاپ دزدیده میشود، نمیتوانید دسترسی لپتاپ را بدون مسدود کردن دسترسی کامپیوتر رومیزی خود لغو کنید، زیرا هر دو کلید خصوصی یکسانی دارند؛ بنابراین مجبورید کلید را در همه جا جایگزین کرده و همزمان بین تمام دستگاهها توزیع کنید.
با مدل «یک کلید برای هر دستگاه»، هزینه گم شدن لپتاپ فقط یک خط در هر سرور است: خط مربوط به لپتاپ را از authorized_keys حذف کنید و سایر دستگاهها به کار خود ادامه میدهند. توضیحی که با -C تنظیم میکنید، همان چیزی است که پیدا کردن آن خط را آسان میکند.
قانون پشت این مدل این است: یک کلید خصوصی روی یک دستگاه ساخته میشود و با همان دستگاه از بین میرود. هرگز یک کلید خصوصی را به دستگاه دوم کپی نکنید و هرگز آن را روی سرور آپلود نکنید. وقتی دستگاه جدیدی به دسترسی نیاز دارد، یک کلید جدید روی همان دستگاه تولید کنید.
قرار دادن کلید عمومی روی سرور
سادهترین روش استفاده از ssh-copy-id است که همراه با OpenSSH ارائه میشود:
ssh-copy-id matt@10.0.0.10این دستور با استفاده از هر روشی که در حال حاضر کار میکند (معمولاً رمز عبور)، وارد سرور میشود، کلید عمومی شما را به فایل ~/.ssh/authorized_keys در سرور اضافه میکند و در صورت نبودن دایرکتوری یا فایل، آنها را با مجوزهای صحیح ایجاد میکند. با باز کردن یک نشست SSH جدید، آن را تست کنید: سرور باید بدون درخواست رمز عبور حساب کاربری، به شما اجازه ورود بدهد. اگر کلید شما دارای passphrase باشد، ممکن است سیستم خودتان آن را درخواست کند؛ این درخواست محلی است و مربوط به رمز عبور سرور نیست.
زمانی که ورود با رمز عبور از قبل غیرفعال شده باشد، ssh-copy-id نمیتواند وارد شود، بنابراین باید خط مربوطه را بهصورت دستی اضافه کنید. از طریق نشستی که هنوز فعال است یا کنسول وب ارائهدهنده سرور خود وارد شوید و دستور زیر را روی سرور اجرا کنید:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keysکلید عمومی واقعی خود را داخل کوتیشنها قرار دهید؛ این کلید باید همان خط کامل و واحد از فایل id_ed25519.pub باشد. فایل authorized_keys شامل یک کلید عمومی در هر خط است و این تمام پایگاه داده دسترسی شماست: افزودن یک دستگاه به معنای اضافه کردن یک خط جدید و لغو دسترسی یک دستگاه به معنای حذف آن خط است. در یک سرور تازه، این مرحله جزو 10 دقیقه اول راهاندازی یک VPS جدید است و باید درست پیش از غیرفعال کردن ورود با رمز عبور انجام شود.
مجوزهایی که باعث اختلال در ورود با کلید میشوند
این رایجترین دلیل شکست ورود با کلید است که از سمت کلاینت بدون هیچ پیامی رخ میدهد. سرویس sshd بهصورت پیشفرض روی Ubuntu 24.04 با StrictModes yes اجرا میشود؛ این یعنی اگر فایل authorized_keys توسط کاربران دیگر قابل ویرایش باشد، sshd از استفاده از آن خودداری میکند. اگر فایل، دایرکتوری ~/.ssh یا دایرکتوری home شما توسط هر کسی غیر از خودتان قابل نوشتن باشد، sshd کلید شما را نادیده میگیرد و بدون هیچ توضیحی در سمت کلاینت، به سراغ درخواست رمز عبور میرود. (نسخه OpenSSH در اوبونتو تنها یک مورد خاص را میپذیرد: فایلی که توسط گروه خصوصی خودتان قابل نوشتن باشد، به شرطی که هیچکس دیگری در آن گروه نباشد. به این مورد تکیه نکنید؛ مجوزها را مطابق زیر تنظیم کنید.) دلیل این اتفاق فقط در لاگ سرور ثبت میشود:
sudo grep 'Authentication refused' /var/log/auth.logدر ایمیجهای مینیمال که فاقد rsyslog هستند، فایل auth.log وجود ندارد؛ همان خط در ژورنال سیستم موجود است: sudo journalctl -u ssh | grep 'Authentication refused'.
Authentication refused: bad ownership or modes for file /home/matt/.ssh/authorized_keysراهحل شامل دو تغییر در مجوزها و یک بررسی مالکیت است که باید روی سرور و با کاربری مربوطه اجرا شود:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R matt:matt ~/.sshقانون کلی این است: 700 برای دایرکتوری .ssh و 600 برای تمام محتویات داخل آن. همین اعداد برای کامپیوتر شخصی شما نیز صدق میکنند، زیرا کلاینت هم این موارد را بررسی میکند. اگر کلید خصوصی توسط کاربران دیگر قابل خواندن باشد، ssh مستقیماً از پذیرش کلید خودداری میکند و این بار خطا بهصورت واضح نمایش داده میشود:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/matt/.ssh/id_ed25519' are too open.دستور chmod 600 ~/.ssh/id_ed25519 این مشکل را برطرف میکند.
~/.ssh/config: توقف تایپ گزینهها
یک فایل ~/.ssh/config روی کامپیوتر شخصی شما، به هر سرور یک نام کوتاه اختصاص میدهد و گزینههایی را که مدام تایپ میکنید، به خاطر میسپارد. آن را با دسترسی 600 ایجاد کنید و برای هر سرور یک بلوک Host اضافه کنید:
Host web1
HostName 10.0.0.10
User matt
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host db1
HostName 10.0.0.11
User matt
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yesاکنون ssh web1 جایگزین ssh -p 22 matt@10.0.0.10 میشود و همان نام کوتاه در scp، rsync و git نیز کار میکند، زیرا همه آنها این فایل را میخوانند. HostName آدرس واقعی است، User شما را از تایپ نام کاربری بینیاز میکند و IdentityFile مشخص میکند که کدام کلید ارائه شود.
IdentitiesOnly yes شایسته یک توضیح جداگانه است، زیرا یک خطای گیجکننده را برطرف میکند. وقتی agent شما چندین کلید در اختیار دارد، کلاینت آنها را یکییکی ارائه میدهد و سرور هر ارائه را به عنوان یک تلاش ناموفق ثبت میکند. با تعداد کافی کلید بارگذاریشده، پیش از آنکه کلید درست امتحان شود، با خطای Received disconnect: Too many authentication failures مواجه میشوید. IdentitiesOnly yes باعث میشود کلاینت فقط کلیدی را که در IdentityFile نام برده شده ارائه دهد، بنابراین آن خطا رخ نخواهد داد.
عبارتهای عبور (Passphrases) و ssh-agent
یک passphrase فایل کلید خصوصی را روی دیسک رمزنگاری میکند. بدون آن، هر کسی که فایل را کپی کند میتواند بلافاصله از آن استفاده کند؛ اما با وجود آن، فایل سرقتشده تا زمانی که passphrase حدس زده نشود، بیفایده است. برای کلیدی که روی لپتاپ قرار دارد، این دقیقاً همان حفاظتی است که نیاز دارید، زیرا لپتاپها ممکن است دزدیده شوند و نسخههای پشتیبان از آنها نشت کنند.
دلیل اینکه استفاده از passphrase در عمل هزینهای ندارد، ssh-agent است. این agent کلید رمزگشاییشده شما را در حافظه نگه میدارد، بنابراین شما در هر نشست ورود (login session) فقط یکبار passphrase را تایپ میکنید و تمام اتصالات بعدی بلافاصله برقرار میشوند. اکثر توزیعهای دسکتاپ لینوکس و macOS از قبل یک agent برای شما اجرا میکنند. کلید خود را با دستور زیر در آن بارگذاری کنید:
ssh-add ~/.ssh/id_ed25519دستور ssh-add -l کلیدهایی را که در حال حاضر در agent قرار دارند فهرست میکند. یک نکته احتیاطی: قابلیت agent forwarding (ssh -A) به سرور راه دور اجازه میدهد تا زمانی که شما متصل هستید، از agent شما برای احراز هویت در مقاصد بعدی استفاده کند؛ بنابراین این قابلیت را فقط برای سرورهایی که کاملاً به آنها اعتماد دارید فعال کنید و در حالت پیشفرض آن را خاموش نگه دارید.
چرخش و ابطال کلیدها: تمرین شرایط اضطراری گمشدن لپتاپ
ابطال یک کلید SSH ساده، چیزی جز حذف خط مربوط به آن از فایل authorized_keys در تمام سرورهایی که آن را دارند نیست. هیچ مرجع صدور گواهی (CA) برای اطلاعرسانی وجود ندارد و نیازی به انتظار برای تاریخ انقضا نیست. لحظهای که آن خط حذف شود، ورودهای جدید با آن کلید با شکست مواجه میشوند.
این تمرین را همین حالا انجام دهید، نه زمانی که در شرایط اضطراری هستید. یک سرور را انتخاب کنید، فایل ~/.ssh/authorized_keys را باز کنید و کلید را از طریق توضیحات (comment) آن پیدا کنید. خط مربوطه را با یک ویرایشگر حذف کنید یا آن را بر اساس توضیحات فیلتر کنید:
grep -v ' laptop$' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keysسپس از دستگاهی که کلیدش را ابطال کردهاید بررسی کنید که ورود دیگر ممکن نیست، و از دستگاه دیگری تأیید کنید که ورود همچنان به درستی کار میکند. به یک نکته توجه داشته باشید: حذف یک کلید، نشستهایی (sessions) را که از قبل باز هستند نمیبندد، زیرا کلید فقط در لحظه ورود بررسی میشود. اگر در حال ابطال دسترسی یک دستگاه سرقتی هستید، فایل who را نیز در سرور بررسی کنید و هر نشستی که نمیشناسید را خاتمه دهید.
چرخش کلید (Rotation) همان عملیات است اما با ترتیبی متفاوت: یک کلید جدید روی دستگاه تولید کنید، آن را با ssh-copy-id نصب کنید، تأیید کنید که کلید جدید اجازه ورود میدهد، و سپس خط مربوط به کلید قدیمی را حذف کنید. این کار را زمانی انجام دهید که دستگاهی تغییر مالکیت میدهد، زمانی که احتمال افشای کلید وجود دارد، یا وقتی کسی تیم را ترک میکند. انجام دستی این کار برای دو سرور مشکلی ندارد؛ اما برای بیست سرور، این وظیفهای برای اتوماسیون است و مدیریت چندین سرور لینوکسی نشان میدهد که چگونه میتوان وضعیت یکسان authorized_keys را به کل ناوگان سرورها اعمال کرد.
کارهایی که نباید انجام داد
- از یک کلید خصوصی مشترک برای تمام دستگاههای خود استفاده نکنید. این کار باعث میشود در صورت سرقت یک دستگاه، امکان ابطال دسترسی آن بدون جایگزینی کلید در تمام دستگاههای دیگر وجود نداشته باشد.
- کلید خصوصی را در مخزن git، حتی مخازن خصوصی، commit نکنید. اسکنرهای خودکار بهطور مداوم مخازن عمومی را پایش میکنند و کلیدهای لو رفته را در عرض چند دقیقه پس از push شدن آزمایش میکنند؛ همچنین اگر مخزنی در آینده عمومی شود، کل تاریخچهٔ آن فاش خواهد شد.
- کلید خصوصی لپتاپ خود را برای دسترسی سرور به سروری دیگر، روی آن آپلود نکنید. روی خودِ سرور یک کلید مجزا ایجاد کنید و همان کلید را دقیقاً در جایی که نیاز است، مجاز (authorize) کنید.
- کلید خصوصی را در چت، ایمیل یا سیستم تیکتینگ کپی نکنید. کلید عمومی، یعنی فایل
.pub، تنها بخشی است که مجاز به اشتراکگذاری آن هستید.
هنگامی که کلید شما بهطور مطمئن امکان ورود را فراهم کرد، گام بعدی را بردارید و احراز هویت با رمز عبور را غیرفعال کنید تا حملات حدس رمز عبور علیه سرور شما بهطور کامل بیاثر شود. پیکربندی مربوط به این کار در مقاومسازی SSH روی VPS موجود است.
FAQ
کلیدهای SSH چگونه بدون ارسال رمز عبور کار میکنند؟
سرور کلید عمومی شما را در ~/.ssh/authorized_keys نگهداری میکند. هنگام ورود، سرور یک چالش (challenge) ارسال میکند، کلاینت شما آن را با کلید خصوصی امضا میکند و سرور امضا را با کلید عمومی تأیید مینماید. کلید خصوصی هرگز دستگاه شما را ترک نمیکند، بنابراین چیزی برای رهگیری در حین انتقال وجود ندارد و هیچ دادهٔ قابل استفادهٔ مجددی برای سرقت از سرور موجود نیست. سروری که دچار رخنه شده باشد، فقط کلیدهای عمومی را لو میدهد که برای ورود به هیچ کجا قابل استفاده نیستند.
آیا باید برای همه سرورهایم از یک کلید SSH استفاده کنم؟
استفاده از یک کلید در چندین سرور صحیح است، به شرطی که آن کلید فقط روی یک دستگاه باقی بماند. قانون این است: یک کلید برای هر دستگاه، نه یک کلید برای هر سرور. کلید عمومی لپتاپ شما باید روی تمام سرورهایی که لپتاپ به آنها نیاز دارد قرار گیرد و دسکتاپ شما نیز کلید مخصوص خود را داشته باشد. این کار ابطال دسترسی را ساده میکند، زیرا در صورت گم شدن یک دستگاه، کافی است یک خط مشخص را از هر سرور حذف کنید و سایر دستگاهها همچنان به کار خود ادامه میدهند.
دایرکتوری .ssh و فایل authorized_keys باید چه مجوزهایی داشته باشند؟
مجوز 700 را برای ~/.ssh و مجوز 600 را برای authorized_keys و همچنین برای هر کلید خصوصی تنظیم کنید؛ مالک این فایلها باید همان کاربری باشد که از آنها استفاده میکند. سرویس sshd بهطور پیشفرض با StrictModes yes اجرا میشود، بنابراین اگر فایل یا دایرکتوری home توسط فرد دیگری غیر از شما قابل نوشتن باشد، sshd کلید شما را نادیده میگیرد و تنها ردپای آن، پیام Authentication refused: bad ownership or modes در لاگ احراز هویت یا journal سرور خواهد بود.
چگونه یک کلید SSH را از سرور حذف کنم؟
خط مربوط به کلید را از فایل ~/.ssh/authorized_keys در حسابی که برای آن مجاز شده است، حذف کنید. خط مورد نظر را از طریق کامنت آن (برچسبی که بعد از محتوای کلید قرار دارد) پیدا کنید. ورودهای جدید با آن کلید بلافاصله با شکست مواجه میشوند، اما نشستهای (sessions) باز همچنان فعال میمانند؛ بنابراین اگر دستگاهی سرقت شده است، هر نشست فعالی را نیز ببندید. این کار را در تمام سرورهایی که کلید روی آنها کپی شده است، تکرار کنید.
آیا به رمز عبور (passphrase) برای کلید SSH نیاز دارم؟
برای کلیدی که روی لپتاپ یا دسکتاپ قرار دارد، بله. رمز عبور، فایل کلید را رمزنگاری میکند تا در صورت سرقت یا نشت، کپی آن به تنهایی بیفایده باشد. همچنین ssh-agent باعث میشود که رمز را فقط یکبار در هر نشست وارد کنید و نه برای هر اتصال. کلیدهایی که توسط اتوماسیونهای بدون نظارت روی سرور استفاده میشوند معمولاً رمز عبور ندارند، زیرا انسانی برای وارد کردن آن حضور ندارد؛ این کلیدها را با محدود کردن دسترسیهای حساب مقصد محافظت کنید.