سرور را تحویل گرفتهاید، IP و رمز root در دست است، و اولین کاری که خیلیها میکنند این است که با ssh root@IP وارد میشوند و بلافاصله پورت SSH را عوض میکنند. نیم ساعت بعد، پنجرهٔ ترمینال قطع میشود و دیگر نمیتوانند وارد شوند. اگر همین حالا در این نقطه ایستادهاید، ترتیب کارها را عوض کنید. سختسازی سرور یک چکلیست نیست که از بالا به پایین اجرا شود؛ ترتیبی دارد که اگر رعایت نشود، خودتان را از سرور بیرون میاندازید.
قبل از هر تغییری، یک راه برگشت بسازید
هر تغییری که امکان قطع دسترسی دارد باید یک مسیر بازگشت داشته باشد. دو راه دارید: یا از پنل مدیریت سرور کنسول KVM/VNC را باز نگه دارید، یا از قبل یک کاربر دوم با دسترسی sudo ساخته باشید که مستقل از کاربر فعلی کار کند.
adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
حالا در یک ترمینال دوم با ssh deploy@IP وارد شوید و باز بماند. تمام تغییرات بعدی را از آن ترمینال انجام دهید. اگر جایی قفل شدید، همان ترمینال باز نجاتتان میدهد. اگر کار از کار گذشت و هیچ راهی نداشتید، بازنصب سرور و کار با حالت rescue آخرین گزینه است؛ ولی رسیدن به آن نقطه یعنی یک ساعت کار اضافه.
اول بهروزرسانی، بعد هر چیز دیگر
سروری که تازه تحویل داده میشود معمولاً ایمیجی دارد که چند هفته یا چند ماه از انتشارش گذشته. قبل از نصب هر بستهای، مخازن را بهروز کنید:
apt update && apt upgrade -y
apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades
روی Debian 12 و Ubuntu 22.04 این دستورها بدون مشکل اجرا میشوند. اگر کرنل بهروز شد، needrestart یا reboot لازم است؛ ولی ریبوت را به بعد از تنظیم فایروال موکول کنید تا اگر سرور بالا نیامد، بدانید مشکل از کجاست.
اینجا اشتباه میکنند: خیلیها apt upgrade را روی سروری اجرا میکنند که هنوز فایروال ندارد و بعد از ریبوت میبینند سرویسهایشان بالا نمیآیند، چون نسخهٔ جدید یک کانفیگ را بازنویسی کرده. قبل از ارتقای بستههای اصلی، apt list --upgradable را ببینید و اگر MySQL یا Nginx در لیست بود، اول بکاپ کانفیگ بگیرید.
SSH را طوری ببندید که خودتان بیرون نمانید
ترتیب مهم است. اول کلید عمومی را روی سرور بگذارید، بعد رمز را غیرفعال کنید. اگر برعکس عمل کنید، بین دو مرحله دسترسیتان قطع میشود.
- کلید عمومی را در
~/.ssh/authorized_keysکاربر جدید قرار دهید. - در یک ترمینال جدا با کلید وارد شوید و مطمئن شوید کار میکند.
- فایل
/etc/ssh/sshd_config.d/99-hardening.confرا بسازید. - با
sshd -tصحت کانفیگ را تست کنید. - با
systemctl reload sshdاعمال کنید، نه restart.
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 20
AllowUsers deploy
دربارهٔ تغییر پورت SSH: من پیشفرض 22 را نگه میدارم. تغییر پورت امنیت واقعی اضافه نمیکند، فقط نویز لاگ را کم میکند و در عوض اگر فایروال را اشتباه تنظیم کنید یا ISP پورت را ببندد، وقتتان تلف میشود. اگر اصرار دارید، پورت جدید را اول در فایروال باز کنید، بعد sshd را reload کنید، و پورت قدیمی را چند روز باز نگه دارید.
فایروال: فقط چیزی که لازم است
روی Ubuntu و Debian، ufw سادهترین راه است. ولی قبل از فعالسازی، پورت SSH را اضافه کنید:
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose
اگر روی سرور Docker دارید، یک نکتهٔ مهم: Docker قوانین iptables خودش را مستقیم مینویسد و ufw را دور میزند. یعنی ممکن است پورتی که در ufw بسته است، از بیرون قابل دسترسی باشد. با docker ps ببینید کدام پورتها publish شدهاند و در compose فقط پورتهایی را bind کنید که واقعاً لازم است، مثلاً 127.0.0.1:3306:3306 بهجای 3306:3306. برای راهاندازی درست، راهاندازی داکر روی VPS را ببینید.
اگر سرویس MySQL دارید، حتماً پورت 3306 را از بیرون ببندید. حتی اگر رمز قوی دارید، اسکنرها مدام تلاش میکنند. امنیت MySQL و محدودکردن دسترسیها مراحل حذف کاربر ناشناس و بستن bind-address را پوشش میدهد.
Fail2ban و پایش: وقتی حمله شروع میشود
بعد از بستن SSH، لاگ /var/log/auth.log را نگاه کنید. اگر سرور چند ساعت در اینترنت بوده، صدها تلاش ناموفق میبینید. Fail2ban اینها را خودکار بلاک میکند:
apt install -y fail2ban
systemctl enable --now fail2ban
fail2ban-client status sshd
خروجی fail2ban-client status sshd تعداد فعلی بلاکشدهها را نشان میدهد. اگر عدد صفر است و سرور چند روز در اینترنت بوده، یعنی jail درست فعال نشده یا لاگ در مسیر دیگری است.
پایش را جدی بگیرید. یک سرور بدون مانیتورینگ، وقتی پر میشود یا لود بالا میرود، تا لحظهای که سایت از دسترس خارج شود خبر نمیدهد. ابزارهایی مثل htop، iotop و netdata کافیاند. اگر لود بالا رفت و نفهمیدید چرا، تشخیص علت لود بالای سرور گامبهگام جلو میرود.
SSL، بکاپ، و آنچه بعد از سختسازی میماند
سختسازی سرور بدون گواهی SSL کامل نیست. اگر سرویس وب دارید، Certbot سریعترین راه است:
apt install -y certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com
بعد از نصب، systemctl list-timers | grep certbot را بزنید تا مطمئن شوید تایمر تمدید فعال است. گواهیهای Let's Encrypt نود روز اعتبار دارند و اگر تمدید خودکار کار نکند، سایتتان یک روز صبح با خطای امنیتی بالا نمیآید. نصب گواهینامه رایگان با Certbot خطاهای رایج تمدید را هم پوشش میدهد.
بکاپ را فراموش نکنید. سختسازی جلوی خیلی چیزها را میگیرد، ولی جلوی حذف اشتباهی فایل را نمیگیرد. یک اسکریپت ساده با rsync یا scp که شبانه به یک مقصد دیگر بکاپ بفرستد، از هر فایروالی ارزشمندتر است. انتقال فایل با scp و rsync الگوی درست را نشان میدهد.
چه چیزی را میشود به بعد موکول کرد
سختسازی کامل یک روز کار است. اگر عجله دارید، این ترتیب را رعایت کنید: بهروزرسانی، کاربر sudo، کلید SSH، غیرفعالکردن رمز، فایروال. SELinux یا AppArmor، پایش پیشرفته، و سختسازی سطح کرنل را میتوانید به هفتهٔ بعد بسپارید. ولی این پنج مورد را همان روز اول انجام دهید.
اگر سرور را تازه از یک ارائهدهنده گرفتهاید و نمیخواهید همهٔ این کارها را دستی انجام دهید، یک هاست لینوکس مدیریتشده با تنظیمات اولیهٔ امن، نقطهٔ شروع سبکتری است؛ ولی اگر کنترل کامل میخواهید، همان سرور خام با چکلیست بالا جواب میدهد.
پرسشهای پرتکرار
چرا بعد از تغییر پورت SSH دیگر نمیتوانم وارد شوم؟
احتمالاً فایروال پورت جدید را باز نکرده یا سرویس sshd را restart کردهاید و کانفیگ خطا داشته. با کنسول KVM وارد شوید، sshd -t را اجرا کنید تا خطای کانفیگ را ببینید، و مطمئن شوید ufw allow NEWPORT/tcp قبل از reload اجرا شده. تا وقتی ترمینال دوم باز دارید، این مشکل چند دقیقهای حل میشود.
آیا غیرفعالکردن ورود root کافی است؟
نه. اگر PasswordAuthentication yes بماند، حملهٔ brute-force روی کاربران دیگر ادامه دارد. هر دو را با هم ببندید و فقط ورود با کلید را باز بگذارید. همچنین AllowUsers را تنظیم کنید تا فقط کاربرانی که میخواهید اجازهٔ ورود داشته باشند.
ufw و iptables را با هم استفاده کنم؟
خیر. ufw یک لایهٔ مدیریت روی iptables است و اگر همزمان قوانین خام iptables بنویسید، بعد از ریبوت یا reload ممکن است قوانینتان پاک شوند. یکی را انتخاب کنید. اگر Docker دارید، بدانید که Docker قوانین خودش را جدا مینویسد و باید پورتها را در سطح خود کانتینر محدود کنید.
بعد از سختسازی، چطور بفهمم کسی تلاش ورود کرده؟
با fail2ban-client status sshd تعداد بلاکشدهها را ببینید و journalctl -u ssh --since "24 hours ago" | grep Failed را اجرا کنید. اگر عدد بلاکشدهها بالاست ولی هیچکدام از IPهای خودتان نیست، سیستم درست کار میکند. اگر IP خودتان بلاک شده، با fail2ban-client set sshd unbanip IP آزادش کنید.