امن‌سازی SSH: ورود با کلید، تغییر پورت و Fail2ban (بدون قفل شدن پشت در)

هر سروری که پورت SSH آن روی اینترنت باز است، از همان دقایق اول هدف تلاش‌های خودکار برای حدس رمز قرار می‌گیرد. کافی است چند دقیقه journalctl -u ssh را نگاه کنید تا ببینید. امن‌سازی SSH جزو اولین کارهایی است که روی هر سرور باید انجام شود، اما یک خطر جدی هم دارد: یک اشتباه کوچک می‌تواند دسترسی خودتان را به سرور قطع کند.

به همین دلیل این آموزش را به ترتیبی نوشته‌ایم که در هر مرحله راه برگشت داشته باشید. پیش‌فرض ما Ubuntu 24.04 است.

قانون طلایی: یک نشست باز نگه دارید

در تمام مدت این آموزش، یک نشست SSH که با آن وارد سرور شده‌اید را باز نگه دارید و نبندید. هر تغییر را در یک ترمینال دوم و با یک اتصال جدید تست کنید. تغییرات sshd روی نشست‌های باز اثر ندارد، پس اگر چیزی خراب شد، از همان نشست اول اصلاحش می‌کنید. علاوه بر این، بدانید در صورت قفل شدن، چطور به کنسول سرور (KVM، VNC یا کنسول پنل ارائه‌دهنده) دسترسی پیدا می‌کنید.

قدم ۱: ساخت کلید ed25519

روی سیستم خودتان (نه سرور) اجرا کنید:

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

برای کلید یک Passphrase بگذارید. اگر لپ‌تاپ گم یا آلوده شود، Passphrase آخرین مانع است. ssh-agent باعث می‌شود لازم نباشد آن را مدام وارد کنید. کلید ed25519 کوتاه، سریع و امن است و توسط همه‌ی نسخه‌های امروزی OpenSSH پشتیبانی می‌شود.

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

ssh-copy-id -i ~/.ssh/id_ed25519.pub ali@server.example.com

در ویندوز که ssh-copy-id ندارد، محتوای فایل .pub را دستی به انتهای ~/.ssh/authorized_keys کاربر روی سرور اضافه کنید و مطمئن شوید دسترسی‌ها درست است:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

قدم ۳: تست ورود با کلید، قبل از هر چیز دیگر

در یک ترمینال جدید:

ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no ali@server.example.com

اگر بدون پرسیدن رمز کاربر وارد شدید (فقط Passphrase کلید را پرسید)، ورود با کلید کار می‌کند. همچنین مطمئن شوید این کاربر می‌تواند sudo اجرا کند. تا این مرحله موفق نشده، سراغ مرحله‌ی بعد نروید.

قدم ۴: تنظیمات sshd در یک فایل جداگانه

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

ls /etc/ssh/sshd_config.d/
nano /etc/ssh/sshd_config.d/00-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowUsers ali deploy
  • PermitRootLogin no ورود مستقیم root را کاملاً می‌بندد. اگر ابزاری (مثلاً سیستم بکاپ) به ورود root با کلید نیاز دارد، از prohibit-password استفاده کنید که فقط ورود root با رمز را می‌بندد.
  • AllowUsers فقط به کاربران نام‌برده اجازه‌ی ورود می‌دهد. اگر نام کاربر خودتان را فراموش کنید، قفل می‌شوید. این خط را با دقت بنویسید.
  • MaxAuthTries را خیلی کم نکنید: اگر ssh-agent شما چند کلید داشته باشد، هر کلید یک تلاش حساب می‌شود.

قبل از اعمال، صحت تنظیمات را بررسی کنید و ببینید sshd در نهایت چه مقادیری را اعمال خواهد کرد:

sshd -t && echo OK
sshd -T | grep -Ei 'passwordauthentication|permitrootlogin|maxauthtries|allowusers|^port'

اگر sshd -t خطا داد، سرویس را ری‌استارت نکنید. اگر خروجی sshd -T هنوز passwordauthentication yes نشان می‌دهد، فایل دیگری زودتر از فایل شما خوانده شده است. حالا اعمال کنید:

systemctl reload ssh

و دوباره در یک ترمینال جدید ورود را تست کنید. ورود با رمز هم باید رد شود:

ssh -o PubkeyAuthentication=no ali@server.example.com
# انتظار: Permission denied (publickey)

قدم ۵: تغییر پورت (و نکته‌ی Ubuntu 24.04)

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

ufw allow 2222/tcp
ufw status

در Ubuntu 24.04 (و از نسخه‌ی 22.10 به بعد)، SSH به‌طور پیش‌فرض با Socket Activation اجرا می‌شود: پورت را واحد ssh.socket در systemd باز می‌کند، نه خود sshd. این را بررسی کنید:

systemctl is-active ssh.socket
systemctl is-enabled ssh.socket

در Ubuntu 24.04 یک Generator در systemd، مقدار Port و ListenAddress را از تنظیمات sshd می‌خواند و ssh.socket را بر اساس آن می‌سازد. پس خط پورت را به فایل تنظیمات اضافه کنید:

echo "Port 2222" >> /etc/ssh/sshd_config.d/00-hardening.conf
sshd -t && echo OK
systemctl daemon-reload
systemctl restart ssh.socket

اگر ssh.socket فعال نیست و SSH به روش سنتی اجرا می‌شود، به‌جای دو خط آخر، systemctl restart ssh کافی است. در هر حال، نتیجه را بررسی کنید:

ss -tlnp | grep -E ':22|:2222'

رفتار Socket Activation در نسخه‌های مختلف Ubuntu تغییر کرده است. در Ubuntu 22.10 و 23.04 تغییر پورت از طریق sshd_config کافی نبود و باید فایل override برای ssh.socket ساخته می‌شد. اگر نسخه‌ی دیگری دارید یا خروجی ss پورت جدید را نشان نمی‌دهد، یادداشت‌های انتشار و فایل /usr/share/doc/openssh-server/README.Debian.gz نسخه‌ی خودتان را بخوانید.

اتصال روی پورت جدید را تست کنید:

ssh -p 2222 ali@server.example.com

فقط بعد از موفقیت این تست، پورت قدیمی را در فایروال ببندید:

ufw delete allow 22/tcp
ufw delete allow OpenSSH

یادتان باشد پورت جدید را در Security Group یا فایروال ارائه‌دهنده‌ی سرور، ابزارهای بکاپ، CI/CD و هر جایی که به سرور SSH می‌کند هم به‌روز کنید.

قدم ۶: Fail2ban

Fail2ban لاگ‌ها را می‌خواند و IPهایی را که چند بار پشت سر هم ورود ناموفق دارند، برای مدتی مسدود می‌کند:

apt install -y fail2ban

فایل‌های پیش‌فرض را تغییر ندهید؛ تنظیمات را در /etc/fail2ban/jail.local بنویسید:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

[sshd]
enabled = true
port    = 2222
backend = systemd

در ignoreip آدرس IP ثابت دفتر یا VPN خود را بگذارید تا خودتان مسدود نشوید. Ubuntu 24.04 به‌طور پیش‌فرض فایل‌های لاگ سنتی SSH را نمی‌سازد، به همین دلیل backend = systemd را گذاشتیم تا Fail2ban مستقیم از journal بخواند.

systemctl enable --now fail2ban
systemctl restart fail2ban
fail2ban-client status sshd

اگر IP خودتان مسدود شد، از یک اتصال دیگر یا کنسول:

fail2ban-client set sshd unbanip 198.51.100.7

قدم ۷ (اختیاری): ورود دومرحله‌ای

برای سرورهای حساس، می‌توانید علاوه بر کلید، کد یک‌بارمصرف (TOTP) را هم الزامی کنید. این کار با ماژول PAM بسته‌ی libpam-google-authenticator و تنظیم AuthenticationMethods publickey,keyboard-interactive در sshd انجام می‌شود. چون در این حالت باید KbdInteractiveAuthentication را دوباره فعال کنید و فایل /etc/pam.d/sshd را تغییر دهید، احتمال اشتباه بالاتر است؛ آن را فقط با همان قانون نشست باز و تست در ترمینال دوم انجام دهید. جایگزین ساده‌تر، کلیدهای سخت‌افزاری FIDO2 با نوع کلید ed25519-sk است.

چک‌لیست نهایی

  • ورود با کلید برای همه‌ی کاربرانی که لازم دارند تست شده است.
  • sshd -T مقادیر مورد انتظار را نشان می‌دهد و ورود با رمز رد می‌شود.
  • پورت جدید در ufw و فایروال ارائه‌دهنده باز و پورت قدیمی بسته است.
  • Fail2ban فعال است و IP مدیریتی در ignoreip قرار دارد.
  • راه دسترسی اضطراری (کنسول) را می‌شناسید و تست کرده‌اید.
  • کلیدهای افرادی که دیگر نیازی به دسترسی ندارند از authorized_keys حذف شده است.

امن‌سازی SSH فقط یکی از بندهای امنیت سرور است. بقیه‌ی موارد را در چک‌لیست سلامت سرور لینوکس مرور کنید، و اگر احتمال می‌دهید سرور قبلاً آلوده شده، اول بازیابی سایت هک‌شده را بخوانید؛ چون بستن در بعد از ورود مهاجم کافی نیست.

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

دیدگاهتان را بنویسید

جستجو

فهرست مطالب