پیکربندی SSH: گزینه‌های امنیتی مهم در sshd_config

راهنمای دقیق گزینه‌های امنیتی sshd_config با مقدار توصیه‌شده و اثر هرکدام؛ از PermitRootLogin تا AllowTcpForwarding، همراه با خطاهای واقعی و رفع آن‌ها.

۶ دقیقه به‌روزرسانی ۵ مهر ۱۴۰۵

سرور را تازه بالا آورده‌اید، با ssh root@IP وارد می‌شوید و همه‌چیز کار می‌کند. بعد لاگ /var/log/auth.log را باز می‌کنید و می‌بینید در ۲۴ ساعت گذشته ۴٬۳۰۰ تلاش ناموفق ورود از ۱۹۰ آی‌پی مختلف ثبت شده است. اینجاست که باید /etc/ssh/sshd_config را جدی بگیرید. این مقاله فهرست گزینه‌هایی است که واقعاً روی سطح حمله اثر دارند، مقدار توصیه‌شده هرکدام، و چیزی که در عمل خراب می‌شود.

قبل از هر تغییری: یک نشست پشتیبان باز بگذارید

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

sshd -t
systemctl reload sshd

خروجی sshd -t اگر خالی بود یعنی سینتکس درست است. اگر خطا داشت، همان‌جا متوقف شوید. دستور reload اتصال‌های فعال را قطع نمی‌کند؛ restart می‌کند. برای تغییرات sshd_config تقریباً همیشه reload کافی است.

گزینه‌هایی که واقعاً سطح حمله را کم می‌کنند

PermitRootLogin

مقدار توصیه‌شده: prohibit-password یا no. تفاوت این دو مهم است. prohibit-password ورود root با رمز را می‌بندد ولی کلید عمومی را قبول می‌کند. no هر ورودی برای root را می‌بندد و باید با کاربر عادی وارد شوید و بعد sudo بزنید. من no را ترجیح می‌دهم، به شرطی که از قبل یک کاربر با دسترسی sudo و کلید نصب‌شده داشته باشید. اگر ندارید، اول آن را بسازید، بعد این خط را عوض کنید.

PasswordAuthentication و ChallengeResponseAuthentication

مقدار توصیه‌شده: no برای هر دو. تا وقتی ورود با رمز باز است، حمله دیکشنری روی SSH جواب می‌دهد و هیچ فایروالی جلوی آن را نمی‌گیرد چون ترافیک روی پورت ۲۲ قانونی است. با no کردن این دو، حمله رمز کاملاً بی‌اثر می‌شود. هزینه‌اش این است که اگر کلید خصوصی را گم کنید، دسترسی را از دست می‌دهید و باید از کنسول یا حالت rescue سرور را برگردانید. اگر این ریسک برایتان قابل قبول نیست، حداقل PasswordAuthentication no را برای root بگذارید و برای یک کاربر مشخص باز نگه دارید.

PubkeyAuthentication و AuthorizedKeysFile

مقدار توصیه‌شده: PubkeyAuthentication yes و AuthorizedKeysFile .ssh/authorized_keys. روی مجوز فایل‌ها حساس باشید: chmod 700 ~/.ssh و chmod 600 ~/.ssh/authorized_keys. اگر مجوز authorized_keys باز باشد، sshd بی‌صدا آن را نادیده می‌گیرد و در لاگ چیزی شبیه Authentication refused: bad ownership or modes می‌بینید. این خطا را زیاد دیده‌ام و تقریباً همیشه مشکل مجوز است، نه کلید.

Port

تغییر پورت پیش‌فرض از ۲۲ به چیز دیگر، امنیت واقعی اضافه نمی‌کند؛ فقط حجم لاگ اسکنرهای خودکار را کم می‌کند. اگر پشت فایروال یا fail2ban هستید، ارزشش را دارد. اگر نه، فقط پیچیدگی اضافه کرده‌اید. من پورت را عوض می‌کنم ولی به‌عنوان لایه اصلی امنیتی روی آن حساب نمی‌کنم.

AllowUsers و DenyUsers

مقدار توصیه‌شده: AllowUsers deploy admin. این گزینه لیست سفید است؛ هر کاربری که در آن نباشد، حتی با کلید معتبر، رد می‌شود. اگر سرور چند کاربر دارد و می‌خواهید مطمئن شوید حساب‌های سرویس مثل www-data یا mysql هرگز SSH نمی‌زنند، این خط را بگذارید. توجه کنید که AllowUsers و AllowGroups با هم جمع می‌شوند، نه اینکه جایگزین هم شوند.

MaxAuthTries و LoginGraceTime

مقدار توصیه‌شده: MaxAuthTries 3 و LoginGraceTime 30. پیش‌فرض MaxAuthTries عدد ۶ است. با ۳، هر اتصال بعد از سه تلاش ناموفق بسته می‌شود و هزینه حمله دیکشنری بالا می‌رود. LoginGraceTime پیش‌فرض ۱۲۰ ثانیه است؛ ۳۰ ثانیه کافی است و تعداد اتصال‌های نیمه‌باز را کم می‌کند.

X11Forwarding و AllowTcpForwarding

مقدار توصیه‌شده: X11Forwarding no و AllowTcpForwarding no مگر اینکه واقعاً به تونل SSH نیاز داشته باشید. اگر از SSH به‌عنوان پروکسی یا برای تونل دیتابیس استفاده می‌کنید، AllowTcpForwarding را روی local بگذارید نه yes. این محدودیت جلوی سوءاستفاده از سرور به‌عنوان رله را می‌گیرد.

ClientAliveInterval و ClientAliveCountMax

مقدار توصیه‌شده: ClientAliveInterval 300 و ClientAliveCountMax 2. این دو با هم یعنی اگر کلاینت ۱۰ دقیقه پاسخ ندهد، اتصال بسته می‌شود. برای سرورهایی که نشست‌های رهاشده زیاد دارند مفید است. اگر روی اتصال بی‌کیفیت کار می‌کنید، این عدد را بالا ببرید وگرنه وسط کار قطع می‌شوید.

این‌جا اشتباه می‌کنند

رایج‌ترین اشتباهی که دیده‌ام این است: کاربر PasswordAuthentication no را در انتهای فایل اضافه می‌کند، ولی بالاتر در همان فایل یک خط PasswordAuthentication yes از قبل وجود دارد. در sshd_config اولین مقداری که برای هر کلید خوانده شود برنده است، نه آخرین. نتیجه این است که سرویس ری‌استارت می‌شود، لاگ هیچ خطایی نشان نمی‌دهد، ولی ورود با رمز همچنان کار می‌کند و کاربر فکر می‌کند تنظیم اعمال شده. راه درست: خط قدیمی را کامنت کنید یا حذف کنید، بعد خط جدید را بگذارید. برای اطمینان، خروجی مؤثر را ببینید:

sshd -T | grep -i passwordauth

دستور sshd -T پیکربندی نهایی بعد از اعمال همه قواعد را چاپ می‌کند. اگر آنجا passwordauthentication no دیدید، تنظیم واقعاً اعمال شده است.

مقایسه مقدار پیش‌فرض و توصیه‌شده

گزینهپیش‌فرضتوصیه‌شدهاثر
PermitRootLoginprohibit-passwordnoبستن کامل ورود root
PasswordAuthenticationyesnoبی‌اثر شدن حمله رمز
MaxAuthTries63کاهش تلاش در هر اتصال
LoginGraceTime12030کاهش اتصال نیمه‌باز
X11Forwardingyesnoحذف سطح حمله بی‌استفاده
AllowTcpForwardingyesno یا localجلوگیری از رله شدن سرور

بعد از بستن SSH، نوبت چیست

وقتی ورود با رمز بسته شد، fail2ban دیگر کار زیادی ندارد چون چیزی برای حدس زدن باقی نمانده. اما اگر سرویس‌های دیگری روی همان سرور دارید، امنیت MySQL را جدی بگیرید؛ حذف کاربر ناشناس و محدودکردن دسترسی به localhost بخشی از همان کار است. برای سرورهایی که به‌عنوان میزبان وب کار می‌کنند، نصب گواهینامه SSL هم قدم بعدی منطقی است. اگر روی سرور ابری یا سرور اختصاصی سرورنت کار می‌کنید، این تنظیمات روی هر دو یکسان اعمال می‌شود و از کنسول مدیریت هم می‌توانید در صورت قفل شدن دسترسی، از حالت rescue استفاده کنید.

یک نکته عملی: قبل از اعمال تغییرات، یک نسخه پشتیبان از فایل بگیرید و آن را جایی خارج از سرور نگه دارید. cp /etc/ssh/sshd_config /root/sshd_config.bak کافی است، ولی اگر سرور از دسترس خارج شود، آن بکاپ هم از دسترس خارج است. انتقال فایل با scp و rsync راه سریع کشیدن نسخه پشتیبان به ماشین محلی است.

پرسش‌های پرتکرار

چرا بعد از PasswordAuthentication no هنوز با رمز وارد می‌شوم؟

چون احتمالاً یک خط PasswordAuthentication yes بالاتر در همان فایل وجود دارد و sshd اولین مقدار را می‌خواند. با sshd -T | grep -i passwordauth مقدار مؤثر را چک کنید. اگر yes بود، خط قدیمی را حذف یا کامنت کنید و سرویس را reload کنید.

تفاوت prohibit-password و no در PermitRootLogin چیست؟

prohibit-password ورود root با رمز را می‌بندد ولی کلید عمومی را قبول می‌کند. no هر روش ورود برای root را می‌بندد و باید با کاربر عادی وارد شوید و بعد sudo بزنید. اگر کاربر sudo با کلید نصب‌شده دارید، no انتخاب امن‌تری است.

آیا تغییر پورت SSH امنیت را بیشتر می‌کند؟

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

اگر کلید SSH را گم کنم چه می‌شود؟

اگر ورود با رمز را بسته باشید، دسترسی SSH را از دست می‌دهید. در این حالت باید از کنسول مدیریت سرور یا حالت rescue استفاده کنید تا فایل authorized_keys را اصلاح کنید یا رمز را موقتاً باز کنید. به همین دلیل همیشه یک کاربر دوم با کلید جداگانه به‌عنوان راه پشتیبان نگه دارید.

آیا این مطلب برایتان مفید بود؟