পাবলিক আইপিতে নতুন সার্ভার চালু করলে কয়েক মিনিটের মধ্যেই লগইনের চেষ্টা আসতে শুরু করে। কেউ আপনাকে খেয়াল করেছে বলে নয় — পুরো IPv4 পরিসর অবিরাম স্ক্যান হয়, আর হার্ডেন না করা SSH পোর্ট নিজে থেকেই ধরা পড়ে।

ভালো খবর হলো, ছোট সার্ভারের প্রায় প্রতিটি বাস্তব আক্রমণের পেছনে থাকে চারটির কোনো একটি: অনুমান করা যায় এমন পাসওয়ার্ড, প্যাচ না করা সার্ভিস, খুলে রাখা এমন পোর্ট যা কখনোই খোলা থাকার কথা ছিল না, অথবা কোনো ফাইলে ফেলে রাখা ক্রেডেনশিয়াল। নিচের প্রথম চারটি ধাপ এই চারটিই বন্ধ করে। এরপরের সবকিছুই সত্যিকারের উন্নতি, তবে লাভের হার দ্রুত কমতে থাকে।

কমান্ডগুলো Ubuntu ও Debian-এর জন্য। RHEL, AlmaLinux বা Rocky-তে apt-এর বদলে dnf আর ufw-এর বদলে firewalld ব্যবহার করুন।

শুরুর আগে: দ্বিতীয় একটি SSH সেশন খুলে সংযুক্ত রাখুন। নিচের কয়েকটি ধাপ আপনাকে বাইরে আটকে দিতে পারে, আর খোলা একটি সেশনই ঠিক করে দেয় ব্যাপারটা একটা টাইপো সারানো হবে, নাকি কনসোল অ্যাক্সেসের জন্য সাপোর্ট টিকিট কাটা।

ধাপ ১ — SSH কী ব্যবহার করুন, পাসওয়ার্ড বন্ধ করুন

এই তালিকার সবচেয়ে মূল্যবান পরিবর্তন এটিই। পাসওয়ার্ড ব্রুট-ফোর্স করা যায়; ২৫৬ বিটের কী যায় না।

নিজের মেশিনে:

bash
ssh-keygen -t ed25519 -C "you@example.com"
ssh-copy-id you@your-server-ip

RSA নয়, Ed25519 — ছোট, দ্রুত, আর অন্তত সমান শক্তিশালী।

এগোনোর আগে কী কাজ করছে কি না পরীক্ষা করুন। নতুন একটি টার্মিনাল খুলে লগইন করুন। পাসওয়ার্ড চাইলে থামুন আর ঠিক করুন, কারণ পরের কমান্ডটি ভেতরে ঢোকার অন্য পথটি বন্ধ করে দেবে।

তারপর /etc/ssh/sshd_config সম্পাদনা করুন:

text
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
bash
sudo sshd -t && sudo systemctl reload ssh

sshd -t কোনো ঐচ্ছিক ভদ্রতা নয় — এটি কনফিগ যাচাই করে, আর দূরের মেশিনে ভাঙা sshd কনফিগ রিলোড করেই মানুষ সার্ভারে ঢোকার পথ হারায়।

আগে sudo সহ একটি সাধারণ ব্যবহারকারী বানান, যদি না থাকে:

bash
sudo adduser deploy
sudo usermod -aG sudo deploy

রুট লগইন বন্ধ, সঙ্গে কেবল কী — এই দুটি মিলে ব্রুট-ফোর্স আক্রমণের গোটা শ্রেণিটাই মুছে দেয়। প্রতিদিনের ওই হাজার হাজার চেষ্টার প্রতিটি এখন প্রথম ধাপেই ব্যর্থ হয়।

ধাপ ২ — ডিফল্টে সব বন্ধ করা ফায়ারওয়াল

নিয়ম হলো: সব বন্ধ করুন, তারপর যে পোর্টগুলো সত্যিই লাগে সেগুলো খুলুন। উল্টোটা নয়।

bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

চালু করার আগে SSH খুলে নিন। SSH নিয়ম ছাড়া ডিফল্ট-ডিনাই ফায়ারওয়াল চালু করলে সঙ্গে সঙ্গে সংযোগ কেটে যায়, আর তারপর সার্ভারে আর পৌঁছানো যায় না।

তারপর দেখুন আসলে কী কী শুনছে:

bash
sudo ss -tulpn | grep LISTEN

প্রতিটি লাইন এমন একটি সার্ভিস, যেখানে কেউ না কেউ পৌঁছাতে পারে। সাধারণত ধরা পড়ে ডেটাবেস — MySQL ও PostgreSQL 0.0.0.0 নয়, 127.0.0.1-এ বাঁধা থাকা উচিত। দুর্বল পাসওয়ার্ডসহ খোলা ডেটাবেস ছোট সার্ভার হারানোর দ্বিতীয় সবচেয়ে প্রচলিত কারণ, আর এতে কারও কিছু ভাঙারও দরকার হয় না।

SSH-কে পরিচিত কোনো আইপি পরিসরে সীমিত করতে পারলে করুন — এটিই সবচেয়ে শক্তিশালী একক নিয়ন্ত্রণ, আর এতে ধাপ ৪-এর সবকিছু অপ্রয়োজনীয় হয়ে যায়।

ধাপ ৩ — স্বয়ংক্রিয় নিরাপত্তা আপডেট

প্যাচ না করা সফটওয়্যারের কারণেই সার্ভার আক্রান্ত হয়, যদিও কেউ বিশেষভাবে আপনাকে আক্রমণ করেনি। একটি প্রকাশিত দুর্বলতা আর একটি স্ক্যানই যথেষ্ট।

bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

/etc/apt/apt.conf.d/50unattended-upgrades-এ নিশ্চিত করুন নিরাপত্তা উৎসটি চালু আছে। আর বসান:

text
Unattended-Upgrade::Automatic-Reboot "false";

যদি না আপনি সত্যিই অপ্রত্যাশিত রিবুট চান। তারপর অপেক্ষমাণ কার্নেল আপডেট নিজেই খেয়াল রাখুন — needrestart জানিয়ে দেবে কখন সত্যিই রিবুট দরকার।

স্বয়ংক্রিয়ভাবে কেবল নিরাপত্তা আপডেট; ফিচার আপডেট নিজের সময়মতো। সবকিছু স্বয়ংক্রিয় করলেই একটি ছোট ভার্সন পরিবর্তন রাত ৩টায় প্রোডাকশন বসিয়ে দেয়। এসবের কোনোটাই নিজের কাঁধে নিতে না চাইলে অথবা একটি ম্যানেজড ভিপিএস নিন আর প্যাচিংয়ের দায়িত্ব অন্যের কাঁধে দিন।

ধাপ ৪ — Fail2ban

কেবল কী দিয়ে SSH থাকলে ব্রুট ফোর্স সফল হতে পারে না — তবু লগে শব্দ আর CPU-তে খরচ থেকেই যায়। Fail2ban লগ দেখে বারবার চেষ্টা করা আইপিগুলোকে ফায়ারওয়ালে আটকে দেয়।

bash
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

jail.local সম্পাদনা করুন:

ini
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true

[recidive]
enabled  = true
bantime  = 1w
findtime = 1d

সবসময় jail.local সম্পাদনা করুন, কখনো jail.conf নয় — প্যাকেজ আপগ্রেডে দ্বিতীয়টি বদলে যায়।

recidive জেলটিই বেশিরভাগ গাইড বাদ দেয়, অথচ সবচেয়ে বেশি কাজ এটিই করে: এটি Fail2ban-এর নিজের লগ দেখে, আর যারা বারবার ফিরে আসে তাদের এক সপ্তাহের জন্য আটকে দেয়। কেবল SSH নয়, ইন্টারনেটমুখী প্রতিটি সার্ভিসের জন্য জেল চালু করুন — ওয়েব সার্ভার আর মেইলও গুরুত্বপূর্ণ।

bash
sudo fail2ban-client status sshd

ধাপ ৫ — ব্যাকআপ, যেটি আপনি সত্যিই ফিরিয়ে দেখেছেন

এটি হার্ডেনিং নয়, আর এই ধাপটিই ঠিক করে আপনার সবচেয়ে খারাপ দিনটি কতটা খারাপ হবে। ব্যাকআপ থাকলে র‍্যানসমওয়্যার বা ভুল rm থেকে বাঁচা যায়, না থাকলে যায় না।

তিনটি নিয়ম:

  1. মেশিনের বাইরে। যে সার্ভারের ব্যাকআপ, সেই সার্ভারে রাখা ব্যাকআপ তার সঙ্গেই মরে।
  2. সংস্করণসহ। ব্যাকআপ যদি বর্তমান অবস্থার হুবহু প্রতিচ্ছবি হয়, তাহলে ঘটনার এক ঘণ্টা পর সেটি এনক্রিপ্ট হয়ে যাওয়া অবস্থারও হুবহু প্রতিচ্ছবি হবে।
  3. পরীক্ষিত। পরীক্ষা না করা ব্যাকআপ একটি বিশ্বাস, ব্যাকআপ নয়।

অবজেক্ট স্টোরেজে সংস্করণসহ, ডিডুপ্লিকেটেড, এনক্রিপ্টেড ব্যাকআপের জন্য restic বা borg। যা-ই বাছুন, ক্যালেন্ডারে মনে করিয়ে দেওয়ার ব্যবস্থা রাখুন যাতে প্রতি তিন মাসে একবার একটি ব্যাকআপ আলাদা সার্ভারে ফিরিয়ে দেখেন। সমস্যা ব্যাকআপ না চলা নয় — সমস্যা হলো দুই বছর ধরে এমন এক বাকেটে ব্যাকআপ চলা, যেটি কেউ ডিক্রিপ্ট করতে পারে না।

ধাপ ৬ — যা চলছে তা কমান

ইনস্টল করা প্রতিটি সার্ভিস ভেতরে ঢোকার একটি পথ। ওয়েব সার্ভারে প্রতিটি সম্পর্কে জিজ্ঞেস করুন এটি কী কাজে, আর অপ্রয়োজনীয়গুলো সরিয়ে দিন: পাবলিকলি শুনতে থাকা মেইল ট্রান্সফার এজেন্ট, FTP ডেমন, ইন্টারনেটে খোলা DNS রিজলভার, দুই বছর আগের প্রজেক্টের পড়ে থাকা ডেটাবেস, কিছু প্যানেলের বসানো নমুনা অ্যাপ।

bash
sudo systemctl list-units --type=service --state=running

সবচেয়ে নিরাপদ সার্ভিস সেটিই, যেটি ইনস্টলই করা নেই।

ধাপ ৭ — ওয়েব সার্ভার ও টিএলএস

  • কেবল TLS ১.২ ও ১.৩। এর নিচের সবকিছু বাতিল ও আক্রমণযোগ্য।
  • HSTS, তবে https সব জায়গায় কাজ করছে নিশ্চিত হওয়ার পর — এটি ফেরানো কঠিন, তাই আগে নিশ্চিত হোন।
  • ভার্সন ব্যানার সরান। Apache-তে ServerTokens Prod, Nginx-এ server_tokens off। সামান্য, তবু দুর্বল কোনো নির্দিষ্ট ভার্সনের খোঁজ থেকে আপনাকে বাদ দেয়।
  • লগইন এন্ডপয়েন্টে রেট লিমিট বসান ওয়েব-সার্ভার স্তরে, কেবল অ্যাপ্লিকেশনে নয়।
  • নিরাপত্তা হেডার বসান: X-Content-Type-Options, X-Frame-Options, Referrer-Policy, আর অ্যাপ সইতে পারলে একটি Content-Security-Policy।

ধাপ ৮ — পারমিশন ও গোপন তথ্য

প্রায় প্রতিটি অডিটে যা ধরা পড়ে তা হলো ওয়েব সার্ভারের পড়ার মতো একটি .env ফাইল — বা আরও খারাপ, http দিয়ে পৌঁছানো যায় এমন একটি।

  • অ্যাপ্লিকেশন ফাইলের মালিক হোক একটি ডিপ্লয় ব্যবহারকারী, ওয়েব সার্ভার ব্যবহারকারী নয়। ওয়েব সার্ভারের পড়া দরকার; নিজের কোডে লেখার দরকার নেই।
  • গোপন ফাইল 600-এ, যে ব্যবহারকারী পড়ে তারই মালিকানায়।
  • বাইরে থেকে যাচাই করুন যে কনফিগ ফাইল পরিবেশিত হচ্ছে না:
bash
curl -sI https://yoursite.com/.env
curl -sI https://yoursite.com/.git/config

দুটোই ৪০৪ বা ৪০৩ হওয়া উচিত। উন্মুক্ত একটি .git ডিরেক্টরি আপনার পুরো সোর্স ইতিহাস ক্রেডেনশিয়ালসহ তুলে দেয়, আর এটি বিস্ময়করভাবে সাধারণ ঘটনা।

  • ভাগাভাগি করা লগইন নয়। প্রতি ব্যক্তির জন্য একটি অ্যাকাউন্ট, প্রতি ব্যক্তির নিজের কী। কেউ চলে গেলে আপনি একটি কী সরাবেন, সবার জানা একটি পাসওয়ার্ড বদলাবেন না।

ধাপ ৯ — কিছু বদলালে যেন টের পান

প্রতিরোধ একসময় ব্যর্থ হবেই। শনাক্তকরণই আক্রমণ আর তা ধরা পড়ার মধ্যেকার ফাঁক ছোট করে, যা সাধারণত মাসের হিসাবে মাপা হয়।

  • সার্ভারের বাইরে থেকে আপটাইম ও সার্টিফিকেট মেয়াদের মনিটরিং
  • লগ মেশিনের বাইরে পাঠান। আক্রমণকারীর প্রথম কাজই স্থানীয় লগ।
  • ওয়েব সার্ভারে ফাইল ইন্টিগ্রিটি মনিটরিং — AIDE বা Tripwire — যেখানে সাধারণ লক্ষণ হলো আপলোড ডিরেক্টরিতে নতুন PHP ফাইল দেখা দেওয়া।
  • ডিস্ক ভরে যাওয়ার সতর্কবার্তা। আকর্ষণহীন, অথচ আক্রমণকারীদের চেয়ে বেশি সার্ভার এটিই বসিয়ে দেয়।

১৫ মিনিটের সংস্করণ

নতুন সার্ভারে আর কিছু না করলেও এটুকু করুন:

bash
# ১. sudo সহ নন-রুট ব্যবহারকারী
sudo adduser deploy && sudo usermod -aG sudo deploy

# ২. নিজের কী পাঠান, তারপর দ্বিতীয় টার্মিনালে পরীক্ষা করুন
ssh-copy-id deploy@server

# ৩. কেবল কী, রুট নয়
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/'         /etc/ssh/sshd_config
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload ssh

# ৪. ডিফল্ট-ডিনাই ফায়ারওয়াল
sudo ufw default deny incoming && sudo ufw allow OpenSSH \
  && sudo ufw allow 80,443/tcp && sudo ufw enable

# ৫. স্বয়ংক্রিয় নিরাপত্তা আপডেট
sudo apt install -y unattended-upgrades fail2ban

# ৬. এখনো কী কী শুনছে?
sudo ss -tulpn | grep LISTEN

বাস্তব সুবিধার সিংহভাগ এটুকুতেই, আর সময় লাগে পনেরো মিনিট।

এটি যা ঢাকে না

সীমারেখাটা সৎভাবে বলা দরকার। এটি সার্ভার সুরক্ষিত করে। এতে কিছুই হয় না:

  • অ্যাপ্লিকেশনের দুর্বলতায়। পুরোনো একটি WordPress প্লাগইন কাজে লাগানো হয় ৪৪৩ পোর্ট দিয়ে, যেটি আপনি ইচ্ছে করেই খোলা রেখেছেন।
  • সাপ্লাই চেইনে। আক্রান্ত একটি ডিপেনডেন্সি আপনার অ্যাপ্লিকেশনের অনুমতি নিয়েই চলে।
  • চুরি যাওয়া ক্রেডেনশিয়ালে। ডেভেলপারের ল্যাপটপ থেকে নেওয়া কী বৈধ কী-ই।

সার্ভার হার্ডেনিং একটি স্তর। অ্যাপ্লিকেশন প্যাচ করে রাখা আরেকটি, আর সাধারণ ওয়েব সার্ভারে ভাঙা হয় আসলে ওই স্তরটিই। দুটোই রক্ষণাবেক্ষণ করা যদি আপনার সময়ের ভালো ব্যবহার না হয়, তাহলে অথবা একটি ম্যানেজড ভিপিএস নিন আর প্যাচিংয়ের দায়িত্ব অন্যের কাঁধে দিন।

সচরাচর জিজ্ঞাসা

SSH পোর্ট ২২ থেকে বদলানো উচিত? লগের শব্দ অনেকটা কমে, তবে দৃঢ়প্রতিজ্ঞ কাউকে ঠেকায় না — পোর্ট স্ক্যান সার্ভিস খুঁজে বের করবেই। শব্দ বিরক্তিকর লাগলে করুন, কিন্তু এটিকে নিরাপত্তা নিয়ন্ত্রণ ভাববেন না, আর কখনোই কেবল-কী প্রমাণীকরণের বদলে এটি করবেন না।

কেবল কী দিয়ে SSH থাকলেও কি Fail2ban দরকার? হ্যাঁ, দুই কারণে: অবিরাম চেষ্টার CPU আর লগের পরিমাণ কমে, আর এর SSH-বহির্ভূত জেলগুলো ওয়েব ও মেইল সার্ভিস রক্ষা করে, যেখানে ক্রেডেনশিয়াল এখনো অনুমান করা যায়।

কত ঘন ঘন প্যাচ করা উচিত? নিরাপত্তা আপডেট স্বয়ংক্রিয়ভাবে, প্রতিদিন। ফিচার ও কার্নেল আপডেট নিজের বেছে নেওয়া সময়ে, একটি রিবুট উইন্ডোসহ। needrestart দেখে রাখুন, যাতে জানেন কখন অপেক্ষমাণ কার্নেল আপডেটের জন্য সত্যিই রিবুট লাগবে।

শেয়ার্ড হোস্টিংয়ে কি এসব লাগে? না — হোস্টই করে, আর এর বেশিরভাগ আপনি করতেও পারবেন না। এটি ভিপিএস থেকে ওপরের জন্য। কোন স্তর দরকার সেটি আলাদা প্রশ্ন: দেখুন শেয়ার্ড বনাম ভিপিএস বনাম ডেডিকেটেড

ম্যানেজড সার্ভার কি সত্যিই বেশি নিরাপদ? বাস্তবে সাধারণত হ্যাঁ, কারণ তখন প্যাচ করাটা কারও ইচ্ছা নয়, কারও চাকরি হয়ে যায়। ছোট ব্যবসার সার্ভার আক্রান্ত হওয়ার সবচেয়ে প্রচলিত কারণ এমন একটি আনম্যানেজড ভিপিএস, যা ঠিকঠাক সেটআপ করা হয়েছিল আর তারপর কেউ আর ছোঁয়নি।

আক্রান্ত হয়েছি মনে হলে প্রথমে কী দেখব? রিবুট করবেন না — তাতে মেমোরির প্রমাণ মুছে যায়। লগইনের জন্য lastlastb দেখুন, অপ্রত্যাশিত লিসেনারের জন্য ss -tulpn, আর সম্প্রতি বদলানো ফাইল খুঁজুন (find /var/www -mtime -7)। তারপর জায়গায় বসে পরিষ্কার না করে জানা-ভালো একটি ব্যাকআপ থেকে নতুন করে গড়ুন। সবকিছু সরিয়েছেন — এটি আপনি প্রমাণ করতে পারবেন না।