لاگ auth.log را باز کردهای و میبینی از سه قاره مختلف روی پورت 22 تلاش ورود میشود. یا بدتر: یک Accepted password for root وسط انبوه Failed password نشسته. اگر هنوز با رمز وارد میشوی، مشکل «اگر» نیست، «کِی» است. ورود با کلید SSH این سطح حمله را تقریباً صفر میکند، به شرطی که درست انجامش بدهی و قبل از بستن رمز، یک راه فرار برای خودت باز کنی.
قبل از هر کاری: یک نشست پشتیبان باز نگه دار
این را جدی بگیر. یک ترمینال SSH دوم باز کن، وارد شو، و تا پایان کار آن را نبند. اگر sshd_config را خراب کنی و نشست فعلیات قطع شود، دیگر راهی برای برگشت نداری مگر از کنسول KVM هاستینگ. من بارها دیدهام که مدیر سرور بعد از systemctl restart sshd خودش را بیرون انداخته و تا صبح منتظر پاسخ تیکت مانده.
قبل از هر تغییری، از فایل تنظیمات نسخه بگیر:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak-$(date +%F)
ساخت کلید SSH: کدام الگوریتم و چرا
روی سیستم خودت، نه روی سرور، اجرا کن:
ssh-keygen -t ed25519 -a 100 -C "ali@laptop-1403"
گزینه -a 100 تعداد دورهای KDF را برای محافظت از passphrase کلید خصوصی بالا میبرد. اگر سیستم قدیمی داری که ed25519 را پشتیبانی نمیکند، -t rsa -b 4096 بزن. کلید RSA 2048 را دیگر نساز؛ در عمل هنوز شکسته نشده، ولی حاشیه امنیتش آنقدر کم شده که ارزش ریسک ندارد.
روی passphrase کلید خصوصی اصرار میکنم. کلید بدون passphrase یعنی هر کسی که فایل ~/.ssh/id_ed25519 را بردارد، دقیقاً همان دسترسی تو را دارد. با ssh-agent یک بار در روز آن را وارد میکنی و بقیه روز راحت کار میکنی.
انتقال کلید عمومی به سرور
سادهترین راه:
ssh-copy-id -i ~/.ssh/id_ed25519.pub ali@server-ip
اگر سرور روی پورت غیر پیشفرض است، -p 2222 را اضافه کن. اگر ssh-copy-id نداری، دستی انجامش بده:
cat ~/.ssh/id_ed25519.pub | ssh ali@server-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
دسترسیها اینجا حیاتیاند. اگر ~/.ssh مجوز 755 داشته باشد یا authorized_keys قابل نوشتن توسط group باشد، sshd کلید را بیصدا رد میکند. بیصدا. یعنی در لاگ چیزی نمیبینی جز Authentication refused: bad ownership or modes که خیلیها از رویش رد میشوند.
تنظیم sshd_config برای ورود فقط با کلید SSH
حالا سراغ فایل اصلی برو. این خطوط را در /etc/ssh/sshd_config تنظیم کن:
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
ChallengeResponseAuthentication no
UsePAM yes
AllowUsers ali deploy
MaxAuthTries 3
LoginGraceTime 20
نکتهای که خیلیها اشتباه میکنند: PermitRootLogin no را با prohibit-password اشتباه میگیرند. اولی ورود root را کلاً میبندد، دومی فقط رمز root را میبندد و کلید را مجاز میگذارد. اگر کلید root داری و میخواهی از آن استفاده کنی، prohibit-password بگذار. اگر نه، no بگذار و از یک کاربر عادی با sudo کار کن.
AllowUsers را دستکم نگیر. بدون آن، هر کاربر سیستمی با شل معتبر میتواند تلاش ورود کند. با آن، فقط دو نامی که نوشتی اجازه دارند.
قبل از restart، تنظیمات را تست کن
sshd -t
اگر خروجی خالی بود، تنظیمات سالم است. اگر خطا داد، همانجا اصلاح کن. بعد:
systemctl reload sshd
از reload استفاده کن نه restart. reload نشستهای فعال را قطع نمیکند. حالا در همان ترمینال دوم که باز نگه داشته بودی، یک نشست جدید باز کن. اگر با کلید وارد شد، ترمینال اول را ببند و برو سراغ کار بعدی.
اینجا اشتباه میکنند: بستن رمز قبل از تست کلید
الگوی تکراری این است: مدیر PasswordAuthentication no را ست میکند، reload میزند، نشست فعلیاش قطع نمیشود، خیالش راحت میشود و میرود. فردا صبح که میخواهد وصل شود، Permission denied (publickey) میگیرد. علت معمولاً یکی از این سه است: کلید در authorized_keys کاربر اشتباه است، مجوز فایلها خراب است، یا AllowUsers نام کاربری را جا انداخته. در هر سه حالت، پیام خطا یکسان است و کمکی نمیکند.
راه تشخیص: در سرور journalctl -u ssh -f را باز کن و از سیستم دیگر وصل شو. خط userauth_pubkey: key type ssh-ed25519 not in PubkeyAcceptedAlgorithms یا Authentication refused: bad ownership or modes دقیقاً میگوید کجا را باید درست کنی.
راه فرار: اگر خودت را بیرون انداختی
اولین کاری که میکنی، از کنسول اضطراری هاستینگ وارد شو. اگر آن هم نداری، از یک کاربر دیگر که هنوز دسترسی دارد استفاده کن. اگر هیچکدام نیست، باید از حالت rescue یا بوت اضطراری سرور استفاده کنی و دیسک را mount کنی.
وقتی برگشتی، این ترتیب را رعایت کن:
PasswordAuthentication yesرا موقتاً برگردان وreloadبزن.- با رمز وارد شو و مشکل کلید را ریشهای حل کن.
- دوباره رمز را ببند و این بار از یک سیستم دیگر تست کن.
یک نکته عملی: قبل از بستن رمز، همیشه یک کاربر دوم با کلید جداگانه بساز. اگر کلید اصلیات گم شد یا passphrase را فراموش کردی، آن کاربر دوم نجاتت میدهد. این کار پنج دقیقه وقت میگیرد و یک شب بیخوابی را حذف میکند.
لایههای بعدی: fail2ban و محدودسازی پورت
بستن رمز، حملات brute-force را بیاثر میکند ولی لاگها را پر میکند و پهنای باند میخورد. امنیت SSH؛ از تغییر پورت تا fail2ban و کلید عمومی را ببین و یک jail ساده برای sshd راه بینداز:
[sshd]
enabled = true
port = 22
maxretry = 3
bantime = 3600
تغییر پورت بهتنهایی امنیت نیست، فقط نویز را کم میکند. کسی که سرور را هدف گرفته، پورت را پیدا میکند. ولی اگر لاگهایت پر از تلاش ورود است و میخواهی سیگنال را از نویز جدا کنی، ارزشش را دارد.
اگر سرور پشت ترافیک مخرب سنگین است، قبل از هر تنظیمی مطمئن شو لایه شبکه هم پوشش دارد. محافظت در برابر DDoS سرورنت این لایه را برای سرویسهای ابری پوشش میدهد و اجازه میدهد بدون قطعی، تنظیمات SSH را اعمال کنی.
کلید را کجا نگه نداریم
کلید خصوصی روی سرور نمیماند. نه در /root/.ssh، نه در پوشه پروژه، نه در مخزن Git. اگر برای deploy از سرور به سرور دیگر وصل میشوی، کلید را روی همان مبدأ نگه دار و با ssh-agent forwarding کار کن. اگر تیم داری، مدیریت رمز عبور در تیمها؛ چرا اشتراک در چت ممنوع است؟ را بخوان؛ همان منطق برای کلیدها هم صادق است.
برای اینکه بفهمی چه کسی، کِی و از کجا وارد شده، لاگها را دستنخورده نگه دار. لاگ ممیزی چیست و چگونه آن را دستنخورده نگه داریم؟ دقیقاً همین موضوع را باز میکند و برای پاسخ دادن به سؤال «چه کسی این کار را کرد» حیاتی است.
چکلیست نهایی قبل از بستن رمز
| مورد | وضعیت درست |
|---|---|
مجوز ~/.ssh | 700 |
مجوز authorized_keys | 600 |
| مالکیت فایلها | خود کاربر، نه root |
| تست ورود با کلید | از یک سیستم دیگر، قبل از بستن رمز |
| کاربر پشتیبان | حداقل یکی، با کلید جداگانه |
| دسترسی کنسول | تأیید شده |
اگر همه ردیفها سبز است، PasswordAuthentication no را ست کن، sshd -t بزن، reload کن و از یک سیستم دیگر تست کن. اگر تست موفق بود، ترمینال پشتیبان را ببند و برو سراغ fail2ban.
پرسشهای پرتکرار
چرا بعد از بستن رمز، همچنان پیام Permission denied (publickey) میگیرم؟
در نود درصد موارد مشکل مجوز فایل است، نه خود کلید. sshd اگر ~/.ssh مجوز 700 نداشته باشد یا authorized_keys قابل نوشتن توسط دیگران باشد، کلید را بیصدا رد میکند. با journalctl -u ssh -f همزمان با تلاش ورود، پیام دقیق را ببین.
حالت دوم این است که کلید در authorized_keys کاربر اشتباه نشسته. اگر با ssh ali@server وصل میشوی، کلید باید در /home/ali/.ssh/authorized_keys باشد، نه در /root/.ssh.
آیا تغییر پورت SSH بهتنهایی امنیت را بالا میبرد؟
نه. تغییر پورت فقط حجم اسکنهای خودکار را کم میکند و لاگها را خوانا نگه میدارد. کسی که سرور را هدف گرفته، با یک اسکن ساده پورت جدید را پیدا میکند. امنیت واقعی از کلید عمومی، بستن رمز و محدود کردن کاربران مجاز میآید.
اگر پورت را عوض کردی، یادت باشد در فایروال و در fail2ban هم همان پورت را ست کنی، وگرنه بعد از ریبوت دسترسیات قطع میشود.
کلید خصوصی را کجا نگه دارم که امن بماند؟
روی سیستم خودت، در ~/.ssh با مجوز 600، و همیشه با passphrase. از کلید خصوصی نسخه پشتیبان رمزنگاریشده بگیر و آن را جدا از لپتاپ نگه دار. کلید خصوصی هرگز روی سرور مقصد نمیماند و هرگز در مخزن Git قرار نمیگیرد.
اگر کلید لو رفت، فقط حذفش از authorized_keys کافی نیست؛ باید کلید جدید بسازی و کلید قدیمی را از همه سرورهایی که به آن دسترسی داشت حذف کنی.
چطور بفهمم کسی با کلید من وارد سرور شده؟
در /var/log/auth.log یا خروجی journalctl -u ssh دنبال خط Accepted publickey for بگرد. هر خط شامل نام کاربر، اثر انگشت کلید و IP مبدأ است. اگر IP ناشناس دیدی، همان لحظه کلید را از authorized_keys بردار.
برای اینکه این لاگها بعداً قابل استناد بمانند، باید دستنخورده و جدا از سرور نگهداری شوند. اگر سرور را از دست بدهی، لاگهای روی همان سرور هم از دست میروند.
دیدگاهها ۰
هنوز دیدگاهی ثبت نشده؛ اولین نفر باشید!