FAQ

এটি Arcivéo Monitor ইনস্টল, কনফিগার ও রক্ষণাবেক্ষণের নির্দেশিকা। বিভাগগুলো সাজানো হয়েছে: সাধারণ পরিচিতি, প্যানেল স্থাপন, নিরাপত্তা টুল যুক্ত করা, অন্তর্নির্মিত মডিউল এবং ডায়াগনস্টিক্স। ডান দিকের বোতাম দিয়ে কমান্ড কপি করা যায়।

শুরু কোথা থেকে

01. প্যানেল ইনস্টলেশন — পদ্ধতি বেছে নিন

প্যানেল ইনস্টলেশন আলাদা ধাপে-ধাপে পৃষ্ঠায় দেওয়া আছে। পদ্ধতি বেছে নিন:

নিশ্চিত না হলে স্বয়ংক্রিয় পদ্ধতি নিন। এই নির্দেশিকা SSL, টুল, cron ও ডায়াগনস্টিকসের একক উৎস হিসেবে থাকছে — install-পৃষ্ঠাগুলো কিছু নকল না করেই এর বিভাগগুলোর লিঙ্ক দেয়।

পরিদর্শন

02. Arcivéo Monitor কী

Arcivéo Monitor — সার্ভার নিরাপত্তার ড্যাশবোর্ড। ইনস্টল করা টুল (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco প্রভৃতি) থেকে তথ্য সংগ্রহ করে এবং ড্যাশবোর্ড, অ্যাটাক ম্যাপ ও প্রতিটি টুলের বিস্তারিত পৃষ্ঠাসহ একটি একক ইন্টারফেসে সেগুলো দেখায়।

মনিটর কোনো সক্রিয় সুরক্ষা ব্যবস্থা নয় — এটি নিজে থেকে আক্রমণ ব্লক করে না। এর কাজ হলো ইতিমধ্যে চালু থাকা টুলগুলোর তথ্য একত্র করে সুবিধাজনকভাবে উপস্থাপন করা।

03. সার্ভারে মনিটর কীভাবে কাজ করে

মনিটর শুধু লোকালি কাজ করে — যে সার্ভার মনিটর করা হচ্ছে, সেটিতেই এটি ইনস্টল করতে হবে। কোনো SSH বা রিমোট API নেই।

সব কমান্ড (fail2ban-client, ufw status, ipset list ইত্যাদি) প্যানেল ওয়েব-সার্ভার ব্যবহারকারীর নামে চালায় (সাধারণত www-data, হোস্টিং প্যানেলে — সাইটের অ্যাকাউন্ট) এবং sudo-এর সীমিত অনুমতিসহ — শুধু নির্দিষ্ট ইউটিলিটির জন্য, সম্পূর্ণ root অ্যাক্সেস ছাড়াই। ফলাফল পার্স করে ব্রাউজারে দেখানো হয়।

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

04. নিরাপত্তা স্কোর কীভাবে গণনা করা হয়

স্কোর সর্বোচ্চ মান থেকে শুরু হয় এবং শনাক্ত হওয়া প্রতিটি সমস্যার জন্য কমে:

  • UFW সক্রিয় নয় — −30
  • Fail2ban চালু নেই (কোনো সক্রিয় jail নেই) — −25
  • কোনো WebAuthn কী নেই — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum লোড হয়নি — −10
  • ClamAV হুমকি খুঁজে পেয়েছে — −20
  • AIDE ফাইল পরিবর্তন — −15
  • SSL মেয়াদ শেষ — −30, <14 দিনে শেষ হচ্ছে — −15, <30 দিন — −5
  • CrowdSec ইনস্টল করা আছে, কিন্তু চালু নেই — −5
  • Suricata ইনস্টল করা আছে, কিন্তু চালু নেই — −5
  • ডেটাবেস/ক্যাশ (MySQL, PostgreSQL, Redis…) বাইরে থেকে অ্যাক্সেসযোগ্য — −10
  • SSH দিয়ে root লগইন অনুমোদিত (PermitRootLogin yes) — −20
  • security আপডেট ইনস্টলের অপেক্ষায় — −5

ফলাফল: 80+ = সুরক্ষিত, 60–79 = সতর্কতা, <60 = ঝুঁকিতে।

ClamAV, AIDE, CrowdSec ও Suricata-এর জন্য কর্তন কেবল তখনই প্রযোজ্য যদি টুলটি ইনস্টল করা থাকে। ইনিশিয়ালাইজ করা ডেটাবেস ছাড়া Lynis ও AIDE “কোনো ডেটা নেই” হিসেবে দেখানো হয় এবং স্কোর কমায় না। আজকের আক্রমণের সংখ্যা ড্যাশবোর্ডে দেখানো হয়, কিন্তু নিরাপত্তা স্কোরে প্রভাব ফেলে না।

সেটিংস ও লাইসেন্স

05. WebAuthn — দ্বি-স্তরীয় প্রমাণীকরণ

WebAuthn — হার্ডওয়্যার কি ব্যবহার করে পাসওয়ার্ড ছাড়াই প্রমাণীকরণের একটি স্ট্যান্ডার্ড। YubiKey, Touch ID, Face ID, Windows Hello, Passkey সমর্থন করে।

পাসওয়ার্ড দিয়ে লগইনের পর সিস্টেম নিবন্ধিত কি দিয়ে নিশ্চিতকরণ চায়। পাসওয়ার্ড ফাঁস হলেও ফিজিক্যাল কি বা বায়োমেট্রিক ছাড়া লগইন করা অসম্ভব।

সেট আপ করতে পাশের মেনু থেকে WebAuthn কি খুলুন এবং “কি নিবন্ধন করুন” চাপুন। একসাথে দুটি কি নিবন্ধন করুন: একমাত্র কি হারিয়ে গেলে বা নষ্ট হয়ে গেলে সেটি দিয়ে প্যানেলে লগইন করা সম্ভব হবে না।

WebAuthn শুধু HTTPS-এর মাধ্যমে কাজ করে। HTTP সংযোগে কি নিবন্ধন ও লগইন উপলব্ধ নয়।

06. নোটিফিকেশন: Telegram এবং Email

প্যানেল Telegram ও ইমেইলে নিরাপত্তা রিপোর্ট পাঠাতে পারে (বোতাম চেপে ও সময়সূচি অনুযায়ী)। “সেটিংস” বিভাগে কনফিগার করা যায়।

Telegram. প্রয়োজন বট টোকেনchat id:

  1. Telegram-এ @BotFather/newbot লিখুন → 123456:ABC... ধরনের একটি টোকেন পাবেন।
  2. আপনার নতুন বটকে যেকোনো একটি বার্তা পাঠান (যাতে সে আপনাকে উত্তর দিতে পারে)।
  3. আপনার chat id জেনে নিন: @userinfobot-কে লিখুন, অথবা https://api.telegram.org/bot<TOKEN>/getUpdates খুলে "chat":{"id":...} খুঁজুন।
  4. “সেটিংস” → Telegram-এ টোকেন ও chat id বসিয়ে “সেভ করে টেস্ট পাঠান” চাপুন।

Email. “সেটিংস” → Email-এ বেছে নেওয়ার দুটি উপায়:

  • SMTP — আপনার মেইলবক্সের হোস্ট, পোর্ট (465/SSL বা 587/TLS), লগইন ও পাসওয়ার্ড;
  • Resend — আধুনিক API: API-কী (re_...) এবং যাচাইকৃত প্রেরক ডোমেন উল্লেখ করুন।
“টেস্ট পাঠান” বোতাম সঙ্গে সঙ্গে চ্যানেল যাচাই করে। স্বয়ংক্রিয় রিপোর্টের সময়সূচি cron-এর মাধ্যমে (“সব cron-টাস্ক” বিভাগ): এটি পাঠানোর কাজ চালু করে, আর চ্যানেলগুলো সেটিংস থেকে নেওয়া হয়।

রিপোর্টের অবস্থা: “সতর্কতা” বা “ঠিক আছে”. শিরোনাম “সতর্কতা” হয় কেবল প্রকৃত সমস্যা বা অপেক্ষমাণ অ্যাকশন থাকলে: ClamAV হুমকি শনাক্ত করেছে, AIDE-তে ফাইল পরিবর্তন, Falco-র গুরুতর ইভেন্ট (গত ২৪ ঘণ্টায় Emergency/Alert/Critical), Monit-এ পড়ে যাওয়া সার্ভিস, রিবুট দরকার, SSL মেয়াদ শেষ হচ্ছে (≤১৪ দিন) বা security-আপডেট অপেক্ষমাণ। ব্যাকগ্রাউন্ড নয়েজ — বটদের SSH ব্রুট-ফোর্স, fail2ban-এ ব্যান হওয়া IP, Suricata অ্যালার্ট, Lynis সতর্কতা এবং ইতিমধ্যে ঠেকানো ModSecurity রিকোয়েস্ট — অবস্থা বাড়ায় না, তাই এসব সংখ্যা নিজে থেকে “সতর্কতা” বোঝায় না।

07. লাইসেন্স — প্রবেশ ও সক্রিয়করণ

বিস্তারিত মনিটরিং মডিউল (Lynis, UFW, ModSecurity, আক্রমণের মানচিত্র, AIDE, ClamAV প্রভৃতি) একটি বৈধ লাইসেন্স থাকলে চালু হয়। এটি ছাড়াও ড্যাশবোর্ড, সেটিংস ও অ্যাকাউন্ট কাজ করে, তবে মডিউলগুলো “লাইসেন্স প্রয়োজন” কার্ড দেখায়।

অ্যাকাউন্টে কেনার পর আপনার কাছে ARCIVEO-XXXX-XXXX-XXXX-XXXX রূপের একটি সক্রিয়করণ কোড থাকে। এটি আপনার প্যানেলের ডোমেনে “সক্রিয়” করতে হবে — এতে কোডটি একটি স্বাক্ষরিত লাইসেন্স ফাইলে ([license] ব্লক) পরিণত হয়, যা আপনি প্যানেলে বসিয়ে দেন।

কীভাবে সক্রিয় করবেন (৩ ধাপ):

  1. সক্রিয়করণ কোডটি নিন। অ্যাকাউন্ট my.arciveo.com → “লাইসেন্স” / “লাইসেন্স সক্রিয়করণ” বিভাগ — ARCIVEO-… কোডটি কপি করুন।
  2. নিজের ডোমেনে কোডটি সক্রিয় করুন। সেই অ্যাকাউন্টেই “লাইসেন্স সক্রিয়করণ” খুলুন, দিন: সক্রিয়করণ কোড, আপনার email এবং প্যানেলের ডোমেন (যে ঠিকানায় মনিটর খোলে, যেমন monitor.example.com)। সক্রিয় করুন বোতামে ক্লিক করুন — সিস্টেম সেই ডোমেনে বাঁধা একটি লাইসেন্স ফাইল তৈরি করবে এবং “কপি” বোতামসহ একটি ঘরে তা দেখাবে।
  3. প্যানেলে কী বসান। লাইসেন্সের পুরো টেক্সট কপি করুন → প্যানেলে “সেটিংস” → “লাইসেন্স” ব্লক খুলুন, বসিয়ে “সংরক্ষণ” চাপুন। মডিউলগুলো তৎক্ষণাৎ আনলক হবে।

প্যানেল কী-টি ক্রিপ্টোগ্রাফিকভাবে যাচাই করে: স্বাক্ষর, ডোমেন-বাঁধন ও মেয়াদ।

সক্রিয়করণের সময় ডোমেন প্যানেলের ঠিকানার সাথে হুবহু মিলতে হবে। এটি config.php-এর APP_URL কনস্ট্যান্ট থেকে নিন এবং শুধু হোস্টের নাম দিন — https:// ছাড়া এবং www প্রিফিক্স ছাড়া। সক্রিয়করণ একবারই: কোডটি প্রদত্ত ডোমেনের জন্য লাইসেন্সে পরিণত হয় এবং পুনরায় সক্রিয় হয় না — ডোমেনে ভুল হলে কী আপনার প্যানেলে চলবে না, আর কোডটিও খরচ হয়ে যাবে। তাই ডোমেন সাবধানে দিন।
মেয়াদ শেষ হলে বা ডোমেন বদলালে — প্যানেলের শীর্ষে একটি সতর্কতা দেখাবে। লাইসেন্স ডোমেনে চিরস্থায়ীভাবে বাঁধা এবং অন্য ডোমেনে স্থানান্তরযোগ্য নয়: নতুন মেয়াদ বা নতুন ডোমেনের জন্য নতুন কী লাগবে (অ্যাকাউন্টে কেনা হয় এবং একবারই সক্রিয় হয়)।

08. config.php ফাইল — প্যানেলের সব সেটিংস

প্যানেলের সব মূল প্যারামিটার একটিমাত্র config.php ফাইলে রুটে (public/ ফোল্ডারের পাশে) সাধারণ define() ধ্রুবক হিসেবে দেওয়া থাকে। ফাইলটি ইনস্টলের সময় তৈরি হয়; হাতে সম্পাদনার দরকার খুব কমই পড়ে — মূলত ডোমেন বদলানো, স্থানান্তর বা অন্য ডেটাবেসে সংযোগের সময়। যেকোনো সম্পাদনার পর PHP-FPM পুনরায় চালু করুন (নয়তো OPcache-এর কারণে পরিবর্তন প্রয়োগ হবে না)।

হাইলাইট করা জায়গায় নিজের মান বসান; বাকিটা যেমন আছে রেখে দিন:

// --- ডেটাবেস --- define('DB_HOST', 'localhost'); // যেমন আছে রাখুন define('DB_NAME', 'db_name'); // ডেটাবেস তৈরির সময় যা দিয়েছেন define('DB_USER', 'user'); // ডেটাবেস তৈরির সময় যা দিয়েছেন define('DB_PASS', 'db_password'); // ডেটাবেস তৈরির সময় যা দিয়েছেন define('DB_CHARSET', 'utf8mb4'); // যেমন আছে রাখুন // --- অ্যাপ্লিকেশন --- define('APP_URL', 'https://monitor.example.com'); // প্যানেলের ঠিকানা, শেষে স্ল্যাশ ছাড়া define('TIMEZONE', 'Asia/Dhaka'); // আপনার টাইম জোন // --- সেশনের সময় --- define('SESSION_LIFETIME', 28800); // পুনরায় লগইনের আগে নিষ্ক্রিয়তা, সেকেন্ড (28800 = 8 ঘণ্টা)

ডেটাবেস। MySQL/MariaDB-তে সংযোগের তথ্য:

  • DB_HOST — DBMS হোস্ট, প্রায় সবসময় localhost;
  • DB_NAME — প্যানেলের ডেটাবেসের নাম;
  • DB_USER — ডেটাবেস ব্যবহারকারী (শুধু নিজের ডেটাবেসে অ্যাক্সেস);
  • DB_PASS — এই ব্যবহারকারীর পাসওয়ার্ড;
  • DB_CHARSET — সংযোগের এনকোডিং, utf8mb4 রেখে দিন।

অ্যাপ্লিকেশন।

  • APP_URL — প্যানেলের পূর্ণ ঠিকানা (যেমন https://monitor.example.com)। যে ডোমেনে লাইসেন্স সক্রিয় করা হয়েছে তার সঙ্গে মিলতে হবে — নয়তো কী প্রত্যাখ্যাত হবে (দেখুন “লাইসেন্স” বিভাগ);
  • TIMEZONEPHP-এর টাইম জোন: শুধু প্যানেল কীভাবে তারিখ ও সময় দেখায় তার উপর প্রভাব ফেলে। cron কাজ চালানোর সময়ের উপর প্রভাব ফেলে না — সেখানে সিস্টেমের জোন কার্যকর থাকে (দেখুন “সব cron কাজ”)।

সেশনের সময়। SESSION_LIFETIME — সেশনের নিষ্ক্রিয়তার টাইমআউট সেকেন্ডে (চলমান: সক্রিয়তায় নবায়ন হয়)। ডিফল্ট 28800 = ৮ ঘণ্টা; এতটা সময় নিষ্ক্রিয় থাকার পর প্যানেল আবার লগইন করতে বলবে। যেমন, 3600 = ১ ঘণ্টা, 86400 = এক দিন।

ত্রুটি লগিং। ত্রুটি কখনও দর্শকদের দেখানো হয় না, বরং logs/php_errors.log-এ লেখা হয় — সেগুলো “অ্যাপ্লিকেশন লগ” পৃষ্ঠায় দেখা যায়। এই লাইনগুলো (display_errors=0, log_errors=1, error_log পথ) সাধারণত বদলানোর দরকার নেই — সেটিংস সরাসরি ফাইলেই দেওয়া আছে এবং php.ini-র উপর নির্ভর করে না।

config.php — গোপন ফাইল। এতে ডেটাবেসের পাসওয়ার্ড আছে। এটি থাকে প্যানেলের রুটে (public/-এর পাশে), আর এই প্যানেলের ওয়েব-রুট (DocumentRoot) — ঠিক প্যানেলের রুটই, public/ নয়। ফাইলটি নিজে থেকে “ফাঁস” হয় না: রুটের .htaccess-এ এর জন্য স্পষ্ট নিষেধ (Require all denied) আছে — সার্ভার 403 ফেরত দেয়। এই নিয়ম ছাড়াও সোর্স ফাঁস হতো না: এটি PHP — সার্ভার এটি চালায়, টেক্সট হিসেবে দেয় না। যেকোনো ক্ষেত্রে: এটি পাবলিক রিপোজিটরিতে রাখবেন না এবং প্রকৃত পাসওয়ার্ডসহ সাপোর্টে পাঠাবেন না। ফাইলের অনুমতি — 640
স্থানান্তর বা অ্যাক্সেস পুনরুদ্ধারের সময় এই ফাইলই তথ্যের মূল উৎস: ডেটাবেসের নাম, ব্যবহারকারী ও পাসওয়ার্ড এখান থেকেই নেওয়া হয় (দেখুন “প্যানেল আপডেট ও স্থানান্তর” এবং “অ্যাক্সেস পুনরুদ্ধার” বিভাগ)।

নিরাপত্তা টুল

09. UFW ফায়ারওয়াল

UFW (Uncomplicated Firewall) — nftables/iptables-এর একটি সহজ ইন্টারফেস। স্পষ্টভাবে অনুমোদিত পোর্ট ছাড়া সব ইনকামিং পোর্ট বন্ধ করে দেয়। “UFW ফায়ারওয়াল” পৃষ্ঠাটি স্ট্যাটাস ও নিয়মগুলো দেখায়।

sudo apt install ufw # SSH অনুমোদন করুন (চালু করার আগে অবশ্যই!) এবং ওয়েব sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # বাইরে থেকে DB বন্ধ করুন (কেবল লোকাল অ্যাক্সেস) sudo ufw deny 3306 # চালু করুন ও যাচাই করুন sudo ufw enable sudo ufw status verbose
ufw enable-এর আগে অবশ্যই SSH অনুমোদন করুন (ufw allow OpenSSH), নাহলে সার্ভারে অ্যাক্সেস হারাবেন।
ড্যাশবোর্ডের “বাহ্যিক এক্সপোজার” UFW বিবেচনা করে: deny নিয়মে বন্ধ করা পোর্ট বাইরে থেকে অ্যাক্সেসযোগ্য হিসেবে গণ্য হয় না।
Skipping adding existing rule — এটি কোনো ত্রুটি নয়। UFW এভাবে জানায় যে ঠিক এমন একটি নিয়ম ইতিমধ্যেই আছে এবং তা পুনরায় যোগ করে না। স্বয়ংক্রিয় কনফিগারেশন আবার চালালে (এটি ইডেমপোটেন্ট) এটি একটি স্বাভাবিক বার্তা — কিছু করার দরকার নেই।

10. Fail2ban ইনস্টল করা

ব্যর্থ লগইন চেষ্টার সংখ্যা সীমা ছাড়ালে স্বয়ংক্রিয়ভাবে IP ব্লক করে। SSH, nginx, Apache ও অন্যান্য সার্ভিসের লগ বিশ্লেষণ করে।

sudo apt install fail2ban sudo systemctl enable --now fail2ban # স্ট্যাটাস দেখুন: sudo fail2ban-client status
কার্যকর কনফিগারেশন (কয়েক ডজন jail ও ipsum থেকে অটোব্যানসহ jail.local) — পরবর্তী বিভাগে।

11. Fail2ban + ipsum-এর কার্যকর কনফিগারেশন

মৌলিক ইনস্টলেশন উপরে দেওয়া আছে। এখানে রয়েছে কার্যকর কনফিগারেশন, যা কয়েক ডজন সক্রিয় jail এবং হাজার হাজার ব্লক তৈরি করে: সাধারণ সেটিংস, মূল jail এবং ipsum তালিকা থেকে ক্ষতিকর IP-র স্বয়ংক্রিয় ব্যান।

/etc/fail2ban/jail.local ফাইল — সাধারণ সেটিংস ও সবচেয়ে গুরুত্বপূর্ণ jail:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # প্রগতিশীল ব্যান: প্রতিটি পুনরাবৃত্তি — দীর্ঘতর bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # SSH ব্রুটফোর্সের জন্য স্থায়ী ব্যান findtime = 3600 # পুনরাবৃত্তিকারী: যারা একাধিক ব্যান খেয়েছে — চিরতরে ব্যান [recidive] enabled = true logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = -1 findtime = 86400 maxretry = 2 [http-get-dos] enabled = true maxretry = 100 findtime = 300 bantime = 1w # ওয়েব-সার্ভিস (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … এবং সার্ভিসভিত্তিক বাকি jail (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
ignoreip-এ অবশ্যই আপনার নিজের IP ও বিশ্বস্ত নেটওয়ার্ক লিখুন, নইলে নিজেকেই ব্যান করে ফেলতে পারেন। সম্পাদনার পর: sudo fail2ban-client reload

ipsum ব্লক-লিস্টের স্বয়ংক্রিয় লোডিং — root-cron-এ (sudo crontab -e): level 1 (১ লক্ষাধিক IP) ipsum সেটে লোড হয়, যা ফায়ারওয়ালে কেটে দেওয়া হয় (বিস্তারিত — “IPset ব্লক-লিস্ট” অংশে):

# 04:00 — ipset ipsum আপডেট (level 1, সর্বোচ্চ কভারেজ): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
সেটের নাম অবশ্যই ipsum হতে হবে — ঠিক এটিই ড্যাশবোর্ড পড়ে (“IPset ipsum” কার্ড)। লেভেল: levels/1.txt — সর্বোচ্চ কভারেজ, levels/3.txt — আরও নির্ভুল (৩+ উৎস)।

“নিরাপত্তা মনিটর” কেন দুটি জোনে বিভক্ত। সুরক্ষা দুটি স্তরে কাজ করে, আর ড্যাশবোর্ড এদের মেশায় না:

  • প্রকৃত আক্রমণ (প্রতিক্রিয়ামূলক) — fail2ban যা ধরেছে তার সবকিছু: হ্যাকিংয়ের জীবন্ত চেষ্টা (sshd, apache-*, nginx-* ইত্যাদি jail) এবং দুর্দান্ত পুনরাবৃত্তিকারী (recidive jail — যারা ইতিমধ্যে কয়েকবার ব্যান হয়েছে)। এগুলো এমন IP যারা সত্যিই আপনার কাছে ঢোকার চেষ্টা করেছিল — এরা আক্রমণ মানচিত্র ও “টাইমলাইনে” থাকে।
  • প্রতিরোধমূলক ব্লক (সক্রিয়) — পরিচিত ক্ষতিকর IP-র সর্বজনীন ব্লক-লিস্ট ipset ipsum, যা ফায়ারওয়ালে DROP নিয়ম দিয়ে কেটে দেওয়া হয়। এই ঠিকানাগুলোর বেশিরভাগই আপনার সার্ভার স্পর্শও করেনি — এদের আগেভাগে কেটে দেওয়া হয়; “IPset ipsum” কাউন্টার দেখায় কতগুলো প্রতিরোধমূলকভাবে কাটা হয়েছে।

পার্থক্যটা সহজ: প্রতিক্রিয়ামূলক — “এরা আক্রমণ করেছে এবং ব্যান খেয়েছে”, প্রতিরোধমূলক — “এদের চেষ্টা করার আগেই ব্লক করা হয়েছে”। আগে recidive-এ কৃত্রিমভাবে ipsum list-3 ঢোকানো হতো (এখান থেকেই পুরনো বিভাজন “তালিকাভিত্তিক recidive”); এখন recidive-এ কেবল প্রকৃত পুনরাবৃত্তিকারীরা, আর প্রতিরোধমূলক অংশ পুরোপুরি ফায়ারওয়ালে।

12. IPset ব্লক-লিস্ট (ipsum)

ipsum — ক্ষতিকর IP-এর একটি পাবলিক তালিকা, প্রতিদিন আপডেট হয়। মনিটর ড্যাশবোর্ড ও অ্যাটাক ম্যাপে লোড হওয়া ঠিকানার সংখ্যা দেখায় এবং তা নিরাপত্তা স্কোরে হিসাব করে (সেট লোড না থাকলে −10)।

fail2ban ছাড়া সবচেয়ে সরল বিকল্প — iptables দিয়ে ব্লক করে এমন একটি আলাদা ipsum সেট:

# সেট তৈরি করুন (একবার): sudo ipset create ipsum hash:ip # আপডেট স্ক্রিপ্ট /usr/local/bin/update-ipsum.sh: #!/bin/bash ipset flush ipsum for ip in $(curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt); do ipset add ipsum "$ip" 2>/dev/null done iptables -C INPUT -m set --match-set ipsum src -j DROP 2>/dev/null \ || iptables -I INPUT -m set --match-set ipsum src -j DROP # Cron (sudo crontab -e, প্রতিদিন 4:00-এ): 0 4 * * * /usr/local/bin/update-ipsum.sh
fail2ban-recidive সহ উন্নত বিকল্প — “Fail2ban + ipsum-এর কার্যকরী কনফিগারেশন” অংশে।
ipset মেমরিতে থাকে এবং রিবুটে হারিয়ে যায়। কেবল একটি দৈনিক ক্রন থাকলে রিবুটের পর থেকে পরের রান পর্যন্ত সেট খালি থাকবে (ড্যাশবোর্ড 0 দেখাবে)। স্টার্টআপেও সেট লোড করুন — লোডিং একটি স্ক্রিপ্টে সরিয়ে @reboot-এ যুক্ত করুন। পাশাপাশি create … -exist কমান্ড maxelem 300000 সীমা নির্ধারণ করে (ডিফল্ট 65536 — level 1 আঁটে না, “Hash is full” দেখাবে):
# /usr/local/bin/load-ipsum.sh #!/bin/bash curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt \ | grep -v '^#' | sed 's/^/add ipsum /' \ | (echo "create ipsum hash:ip hashsize 131072 maxelem 300000 -exist"; echo "flush ipsum"; cat) \ | ipset restore -exist # sudo crontab -e — প্রতিদিন 04:00-এ এবং প্রতিবার স্টার্টে: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
অটোইনস্টলে কীভাবে কাজ করে। স্ক্রিপ্ট পূর্ণ level 1 তালিকা (১ লক্ষাধিক IP) ipsum সেটে লোড করে, এবং ফায়ারওয়াল যদি ইনস্টলার পরিচালনা করে (নতুন VPS — “পূর্ণ”/“লাইট” প্রোফাইল), তবে DROP নিয়মে সেটটি UFW-তে সংযুক্ত করে — এই IP থেকে ট্রাফিক সত্যিই ব্লক হয়। নিয়মটি ESTABLISHED,RELATED-এর পরে থাকে, তাই বর্তমান সংযোগগুলো (আপনার SSH সহ) বিচ্ছিন্ন হয় না — শুধু তালিকার নতুন সংযোগ কাটা পড়ে। সেটটি ipsum-load.service সার্ভিস লোড হওয়ার সময় ফায়ারওয়ালের আগে পুনরুদ্ধার হয় (নইলে UFW উঠত না), এবং 04:00-এর ক্রনে আপডেট হয়। ইতিমধ্যে কনফিগার করা সার্ভারে (প্যানেল, নিজের ফায়ারওয়াল) ইনস্টলার ফায়ারওয়ালে হাত দেয় না — সেখানে ipsum ড্যাশবোর্ড ও অ্যাটাক ম্যাপের তালিকা হিসেবেই থাকে, আর DROP নিয়ম চাইলে ম্যানুয়ালি যোগ করা যায় (iptables … --match-set ipsum … -j DROP সহ সরল বিকল্প — উপরে)। অটোইনস্টলে ম্যানুয়ালি কিছু করার দরকার নেই।

13. CrowdSec ইনস্টলেশন

যৌথ threat intelligence সহ Fail2ban-এর আধুনিক বিকল্প: কমিউনিটির ব্লক এবং নিজস্ব নিয়ম। ফায়ারওয়ালে ব্লক প্রয়োগ করতে আলাদা bouncer প্রয়োজন।

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash sudo apt install crowdsec sudo systemctl enable --now crowdsec # iptables/nftables-এর জন্য Bouncer: sudo apt install crowdsec-firewall-bouncer-iptables # স্ট্যাটাস যাচাই করুন: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
প্যানেলে “চালু নেই” স্ট্যাটাস = সার্ভিস ইনস্টল করা আছে, কিন্তু সার্ভিসটি সক্রিয় নয় (মনিটর এটি systemctl is-active crowdsec দিয়ে যাচাই করে)। চালু করুন: sudo systemctl enable --now crowdsec; ক্র্যাশ করলে দেখুন sudo journalctl -u crowdsec -n 30। “চালু নেই” স্ট্যাটাসের যেকোনো সার্ভিসের (Suricata, Falco, Monit, MySQL) জন্য একই নিয়ম।
ড্যাশবোর্ডে “0 সিনারিও” বা “0 bouncers”। CrowdSec ডিফল্টভাবে প্রায় খালি আসে — কালেকশন ছাড়া এটি কিছুই শনাক্ত করে না, আর নিবন্ধিত bouncer ছাড়া ফায়ারওয়ালে ব্লক প্রয়োগ হয় না। মৌলিক কালেকশন ইনস্টল করুন এবং নিশ্চিত করুন যে bouncer তালিকায় আছে:
# মৌলিক কালেকশন (Linux + SSH + ওয়েব সার্ভার): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer তালিকায় থাকতে হবে এবং সক্রিয় সংযোগ স্ট্যাটাসসহ: sudo cscli bouncers list
bouncer-এর লগে stream halted / ব্লক প্রয়োগ হচ্ছে না। এটি একটি অনাথ api-কী: bouncer cscli bouncers list থেকে মুছে গেছে, কিন্তু তার পুরনো কী /etc/crowdsec/bouncers/*.yaml-এ রয়ে গেছে। bouncer পুনরায় নিবন্ধন করুন এবং নতুন কী লিখুন:
sudo cscli bouncers add fw-bouncer # নতুন api_key দেখাবে # এই কী লিখুন api_key:-এ /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml ফাইলে sudo systemctl restart crowdsec-firewall-bouncer
স্বয়ংক্রিয় ইনস্টলেশন (“সম্পূর্ণ সুরক্ষা” প্রোফাইল) নিজেই কালেকশন ইনস্টল করে এবং firewall-bouncer নিবন্ধন করে — ম্যানুয়াল ইনস্টলেশনের সময় বা CrowdSec-এ ম্যানুয়াল হস্তক্ষেপের পরেই কেবল এটি হাতে করতে হয়।

14. AIDE ইনস্টলেশন

AIDE (Advanced Intrusion Detection Environment) ফাইল সিস্টেমের একটি স্ন্যাপশট তৈরি করে এবং প্রতিটি পরীক্ষার সময় /etc, /bin, /usr-এর পরিবর্তনগুলো জানায়। ইনস্টলেশনের পরে ডেটাবেস ইনিশিয়ালাইজ (aideinit) করা অবশ্যই প্রয়োজন।

sudo apt install aide # ডেটাবেস ইনিশিয়ালাইজেশন (৫–১৫ মিনিট): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: /var/lib/aide ডিরেক্টরি 700 মোডে তৈরি হয় (মালিক _aide), # এবং প্যানেল (www-data) ডেটাবেস দেখতে পায় না → “ইনিশিয়ালাইজ করা হয়নি” দেখায়। # ডিরেক্টরিটি পাসের জন্য খুলুন (ডেটাবেস ফাইলগুলো 600 থাকে): sudo chmod 755 /var/lib/aide # মনিটর যে লগ পড়ে সেখানে লেখা সহ প্রথম পরীক্ষা। # Ubuntu/Debian-এ aide-এর জন্য স্পষ্ট --config প্রয়োজন (নইলে “missing configuration”; # নতুন সংস্করণে aide.wrapper বাইনারি দেওয়া হয় না): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
aideinit চলাকালীন টার্মিনাল ৫–১৫ মিনিট Running aide --init... লাইনে থেমে থাকে — এটি স্বাভাবিক (পুরো ফাইল সিস্টেম হ্যাশিং, ডিস্কে চাপ)। Ctrl+C দিয়ে থামাবেন না। যদি প্রসেসটি “ঝুলে” থাকে কিন্তু কিছু না লেখে — সম্ভবত এটি একটি লুকানো প্রশ্নের Overwrite existing aide.db.new [Yn]? উত্তরের অপেক্ষায় আছে (Y চাপুন)। অন্য একটি সেশন থেকে সক্রিয়তা যাচাই করুন: pgrep -af aide
aideinit ত্রুটি: “21_aide_spamassassin … printf: invalid number” (return code 20) — Ubuntu 22.04-এ AIDE কনফিগ-স্নিপেটের একটি পরিচিত বাগ। ডেটাবেস তৈরি হয় না। ভাঙা স্নিপেটটি সরিয়ে আবার চেষ্টা করুন:
sudo mv /etc/aide/aide.conf.d/21_aide_spamassassin /etc/aide/21_aide_spamassassin.disabled sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
ড্যাশবোর্ডে স্ট্যাটাস। “ইনিশিয়ালাইজ করা হয়নি” = প্যানেল ডেটাবেস ফাইল দেখতে পায় না: হয় aideinit চালানো হয়নি, নয়তো (Ubuntu 24.04) /var/lib/aide ডিরেক্টরি 700 মোডে তৈরি হয়েছে ও www-data-এর কাছে অগম্য — sudo chmod 755 /var/lib/aide দিয়ে সমাধান হয় (উপরের ব্লক দেখুন)। “কোনো পরীক্ষা হয়নি” = ডেটাবেস আছে, কিন্তু এখনও পরীক্ষা চালানো হয়নি — এটি কোনো ত্রুটি নয়। মনিটর ফলাফল /var/log/aide/aide.log থেকে পড়ে।
নিয়মিত পরীক্ষা → প্যানেলের জন্য লগ। নতুন Ubuntu/Debian-এ স্ট্যান্ডার্ড /etc/cron.daily/aide হয়তো প্রয়োজনীয় ফরম্যাটে /var/log/aide/aide.log নাও লিখতে পারে (এবং তাতে aide.wrapper-ও আর নেই)। স্পষ্ট --config সহ নিজস্ব ক্রন যোগ করা বেশি নির্ভরযোগ্য — এটি root থেকে 644 মোডে লগ লেখে, আর মনিটর অতিরিক্ত গ্রুপ ছাড়াই তা পড়ে:
# sudo crontab -e — প্রতিদিন 02:00-এ পরীক্ষা: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # সময়সূচির অপেক্ষা না করে এখনই চালান: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
স্বয়ংক্রিয় ইনস্টলেশন এই সবই করে ফেলে: chmod 755 /var/lib/aide এবং 02:00-এ পরীক্ষার ক্রন — হাতে কিছুই করার দরকার নেই।
প্রথম ইনিশিয়ালাইজেশন একটি পরিষ্কার সার্ভারে করুন — ওয়েব অ্যাপ্লিকেশন ইনস্টলের আগে। বৈধ পরিবর্তনের পরে ডেটাবেস আবার তৈরি করুন: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

15. ClamAV ইনস্টলেশন

Linux-এর জন্য অ্যান্টিভাইরাস স্ক্যানার। PHP-শেল ও ক্ষতিকর কোড আছে কিনা /var/www যাচাই করতে বিশেষভাবে কার্যকর।

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # সিগনেচার ডেটাবেস আপডেট করুন: sudo freshclam # ফোল্ডার নিজে হাতে স্ক্যান করুন: sudo clamscan -r /var/www --infected
enable --now-এর পরেও clamd ডেমন “নিষ্ক্রিয়” দেখাচ্ছে? তিনটি সাধারণ কারণ:

1. কনফিগে Example লাইনটি রয়ে গেছে — এটি থাকা অবস্থায় clamd চালু হতে অস্বীকার করে:

sudo sed -i '/^Example/d' /etc/clamav/clamd.conf sudo systemctl restart clamav-daemon

2. সিগনেচার ডেটাবেস ডাউনলোড হয়নি — এটি ছাড়া clamd চালু হয় না:

sudo systemctl stop clamav-freshclam sudo freshclam sudo systemctl start clamav-freshclam sudo systemctl restart clamav-daemon

3. কেবল লোড হচ্ছে — clamd ~৮০ লক্ষ সিগনেচার মেমরিতে লোড করতে ৩০–৬০ সেকেন্ড নেয়। অপেক্ষা করে যাচাই করুন: systemctl is-active clamav-daemon (activating স্ট্যাটাস → এখনও লোড হচ্ছে)।

ডায়াগনস্টিক্স: sudo journalctl -u clamav-daemon -n 30 --no-pager
ড্যাশবোর্ডে “ফাইল যাচাই: 0” / “শেষ স্ক্যান: —”? clamd ডেমন শুধু সিগনেচার মেমরিতে ধরে রাখে, নিজে থেকে সময়সূচি অনুযায়ী কিছু স্ক্যান করে না। প্যানেল নির্ধারিত স্ক্যানের ফলাফল দেখায়, তাই এমন একটি ক্রন দরকার যা স্ক্যান করে ও লগ লেখে। স্বয়ংক্রিয় ইনস্টলেশন /usr/local/bin/clamav-scan.sh র‍্যাপার এবং 01:30-এ একটি ক্রন বসায় — প্রথম রানের পর “ফাইল যাচাই” ও “শেষ স্ক্যান” পূরণ হবে। সময়সূচির অপেক্ষা না করে এখনই চালাতে: sudo /usr/local/bin/clamav-scan.sh

16. Linux Malware Detect (maldet) ইনস্টল করা

Linux Malware Detect (LMD) — ওয়েব হুমকির জন্য ম্যালওয়্যার স্ক্যানার: PHP-শেল, ওয়েব-ব্যাকডোর, লোডার। এটি ClamAV ইঞ্জিন ব্যবহার করে এবং নিজস্ব সিগনেচার দিয়ে তা পরিপূরক করে।

wget https://www.rfxn.com/downloads/maldetect-current.tar.gz tar -xzf maldetect-current.tar.gz dir=$(ls -d maldetect-*/ | head -1) && cd "$dir" && sudo bash install.sh && cd ~ rm -rf maldetect-* maldetect-current.tar.gz # সিগনেচার আপডেট করুন: sudo maldet -u # /var/www স্ক্যান করুন: sudo maldet -a /var/www
LMD এবং ClamAV জুটি হিসেবে ভালো কাজ করে। সর্বশেষ রিপোর্ট: maldet --report
ইনস্টলের সময় update-rc.d: error: unable to read /etc/init.d/maldet লাইনটি দেখা যেতে পারে — এটি ক্ষতিকর নয়। maldet init.d ব্যবহার করে না, সিগনেচার আপডেট ও স্ক্যান /etc/cron.daily/maldet এর মাধ্যমে চলে। নিচে installation completed দেখা গেলে — সবকিছু ইনস্টল হয়ে গেছে।
ইনস্টল থাকা সত্ত্বেও পেজে LMD-এর জন্য “ইনস্টল করা নেই” দেখাচ্ছে? maldet apt দিয়ে নয়, বরং /usr/local/maldetect-এ ইনস্টল হয়, এবং open_basedir চালু থাকলে এর উপস্থিতি shell-এর মাধ্যমে যাচাই করা হয় — দেখুন “পেজ ফাঁকা, যদিও সার্ভারে ডেটা আছে” অংশটি।

17. Suricata ইনস্টল করা

নেটওয়ার্ক অনুপ্রবেশ শনাক্তকরণ সিস্টেম: প্যাকেট স্তরে ট্রাফিক বিশ্লেষণ করে এবং হাজার হাজার আক্রমণের সিগনেচার চেনে। ModSecurity-কে পরিপূরক করে (সেটি HTTP স্তরে কাজ করে, Suricata — TCP/IP স্তরে)।

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # সর্বশেষ নিয়ম ডাউনলোড করুন: sudo suricata-update sudo systemctl enable --now suricata
Suricata “সক্রিয়”, কিন্তু ড্যাশবোর্ড অ্যালার্ট দেখায় না / ইভেন্ট সংখ্যা 0? Suricata /var/log/suricata/eve.json ফাইলটি root হিসেবে লেখে এবং ডিরেক্টরিতে 750 মোড থাকায় ওয়েব-সার্ভার (www-data) সেটি পড়তে পারে না। ডিরেক্টরিটি পাস-থ্রুয়ের জন্য খুলুন — ভেতরের ফাইলগুলো সুরক্ষিত থাকে:
sudo chmod o+rx /var/log/suricata
স্বয়ংক্রিয় ইনস্টল এটি নিজেই করে — হাতে করার প্রয়োজন নেই।

18. Falco ইনস্টলেশন

eBPF/kernel module-এর মাধ্যমে সিস্টেম কল ইন্টারসেপ্ট করে এবং রিয়েল-টাইমে অস্বাভাবিকতা শনাক্ত করে: nginx থেকে shell, ওয়েব প্রসেস দিয়ে /etc/passwd পড়া, /bin-এ লেখা ইত্যাদি।

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc > /tmp/falco.asc gpg --dearmor < /tmp/falco.asc | sudo tee /usr/share/keyrings/falco-archive-keyring.gpg > /dev/null sudo chmod 644 /usr/share/keyrings/falco-archive-keyring.gpg && rm /tmp/falco.asc echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" \ | sudo tee /etc/apt/sources.list.d/falcosecurity.list sudo apt update && sudo apt install falco sudo systemctl enable --now falco
মনিটর Falco-র ইভেন্ট journalctl -u falco দিয়ে পড়ে (sudo ছাড়া — systemd-journal গ্রুপের মাধ্যমে)। www-data এই গ্রুপে আছে কিনা নিশ্চিত করুন — দেখুন ম্যানুয়াল ইনস্টলেশন পৃষ্ঠায় “sudo সেটআপ” (পয়েন্ট ২)।
“২৪ ঘণ্টায় ০ ইভেন্ট” — এটি স্বাভাবিক, ত্রুটি নয়। Falco event-driven: সব ঠিক থাকলে এটি নীরব থাকে, আর কেবল অস্বাভাবিকতায় (ওয়েব প্রসেস থেকে shell, /etc/passwd পড়া, সিস্টেম ডিরেক্টরিতে লেখা) ইভেন্ট লেখে। শান্ত সার্ভারে দিনে শূন্য ক্রিটিক্যাল — একটি সুস্থ অবস্থা।
ড্যাশবোর্ডের জন্য ফাইল-আউটপুট বেশি নির্ভরযোগ্য। journalctl দিয়ে পড়তে জার্নালে অনুমতি লাগে; ড্যাশবোর্ড যাতে স্থিরভাবে ইভেন্ট দেখে, তার জন্য অটো-ইনস্টল Falco-তে file_output/var/log/falco/falco.log চালু করে এবং সার্ভিসে UMask=0022 সেট করে (লগ ওয়েব-সার্ভার পড়তে পারে)। নতুন ইনস্টলেশনে এটি হাতে কনফিগার করার দরকার নেই।

19. ModSecurity (WAF) ইনস্টল করা

ModSecurity — Apache বা Nginx-এর জন্য ওয়েব ফায়ারওয়াল (WAF)। অ্যাপ্লিকেশন স্তরের আক্রমণ ব্লক করে: SQL ইনজেকশন, XSS, পাথ ট্রাভার্সাল, স্ক্যানার।

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # OWASP Core Rule Set রুল সেট: sudo apt install modsecurity-crs # আবশ্যক: এই ফাইল ছাড়া রুল ইঞ্জিন বন্ধ থাকে sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf sudo apache2ctl configtest && sudo systemctl reload apache2 # যাচাই: 403 ফেরত আসা উচিত curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
শুধু প্যাকেজ ইনস্টল করলেই কিছু সুরক্ষিত হয় না। Apache IncludeOptional /etc/modsecurity/*.conf লাইন দিয়ে কনফিগ যুক্ত করে, কিন্তু প্যাকেজ শুধু modsecurity.conf-recommended রাখে — যা *.conf মাস্কের আওতায় পড়ে না। এটি modsecurity.conf-এ কপি না করলে SecRuleEngine Off থেকে যায়: মডিউল লোড হয়, CRS রুল লোড হয়, কিন্তু ট্রাফিক পরীক্ষা হয় না এবং অডিট লগ তৈরি হয় না। মধ্যবর্তী মোড DetectionOnly শুধু লগে ইভেন্ট লেখে, অনুরোধ ব্লক করে না — প্যানেল একে হলুদ রঙে দেখায়।

অডিট লগে প্যানেলের অ্যাক্সেস। /var/log/apache2/modsec_audit.log লগটি root-এর মালিকানাধীন (অনুমতি 640), ওয়েব-ব্যবহারকারী এটি পড়তে পারে না। প্যানেল একটি র‍্যাপার দিয়ে ডেটা নেয় — এটি তৈরি করুন:

sudo tee /usr/local/bin/monitor-modsec >/dev/null <<'EOF' #!/bin/sh echo "ENGINE=$(grep -hE '^SecRuleEngine[[:space:]]+' /etc/modsecurity/*.conf 2>/dev/null | tail -1 | awk '{print $2}')" echo "---LOG---" tail -n 3000 /var/log/apache2/modsec_audit.log 2>/dev/null echo "---RULES---" for f in /etc/modsecurity/crs/rules/*.conf /usr/share/modsecurity-crs/rules/*.conf /etc/modsecurity/custom-rules.conf; do [ -f "$f" ] && { echo "===FILE:$(basename "$f")==="; cat "$f"; } done EOF sudo chown root:root /usr/local/bin/monitor-modsec sudo chmod 755 /usr/local/bin/monitor-modsec # /etc/sudoers.d/monitor-এ (ব্যবহারকারী = যার অধীনে PHP-FPM চলে): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
র‍্যাপার ইন্ডেন্ট ছাড়া সর্বশেষ SecRuleEngine নির্দেশনা নেয়: ইন্ডেন্টযুক্ত লাইনগুলো <LocationMatch>/<Directory> ব্লকের ভেতরে থাকে (যেমন, phpMyAdmin-এর জন্য WAF বন্ধ করা) এবং গ্লোবাল মোড নির্ধারণ করে না।
sudoers-এর ব্যবহারকারী FPM পুলের ব্যবহারকারীর সাথে মিলতে হবে: সাধারণ Apache/Debian-এ এটি www-data, HestiaCP-তে সাইটের পুল সাইটের মালিকের অধীনে চলে (যেমন, admin) — grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf দিয়ে যাচাই করুন।
সাইটটি যদি Nginx প্রক্সির পেছনে থাকে (HestiaCP), Apache প্রক্সিকেই ক্লায়েন্ট হিসেবে দেখে — প্যানেল X-Forwarded-For হেডার থেকে আক্রমণকারীর প্রকৃত IP নেয়। পরিসংখ্যানে শুধু সেই লেনদেনগুলো আসে যেখানে রুল সক্রিয় হয়েছে: SecAuditLogRelevantStatus নির্দেশনা যেকোনো 4xx/5xx রেসপন্স অডিট লগে লেখে, তাই সেখানে সাধারণ 403/500-ও চলে আসে — প্যানেল এগুলোকে WAF ইভেন্ট হিসেবে গণ্য করে না।
---RULES--- ব্লকটি “সব সক্রিয় রুল” বিভাগের জন্য দরকার — প্যানেল শুধু সক্রিয় হওয়া রুল নয়, লোড করা সমস্ত CRS + কাস্টম রুল দেখায়। for f in … লুপের তিনটি পাথ — CRS রুল ও স্থানীয় সংযোজনের জন্য সাধারণ অবস্থান; আপনার বিন্যাস ভিন্ন হলে (প্যাকেজ নিজের ডিরেক্টরিতে ফাইল রাখে, বা কাস্টম রুল /etc/modsecurity/custom-rules.conf-এ নেই), sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null কমান্ড দিয়ে প্রকৃত পাথ খুঁজে বের করে তালিকায় বসান। র‍্যাপার পুরনো হলে (এই সেকশন ছাড়া) — বিভাগটি শুধু “অনুপলব্ধ” সতর্কতা দেখাবে, বাকি পৃষ্ঠা আগের মতোই কাজ করবে।

20. Auditd ইনস্টলেশন

Auditd (Linux Audit Daemon) কার্নেল স্তরে সিস্টেম কল রেকর্ড করে: লগইন ও লগআউট, sudo কমান্ড, ব্যর্থ প্রমাণীকরণ প্রচেষ্টা, ফাইল পরিবর্তন। মনিটর আজকের লগইন, ব্যর্থ প্রচেষ্টা এবং sudo কমান্ড দেখায়।

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # স্ট্যাটাস ও ইভেন্ট যাচাই করুন: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
মনিটর ausearch (/usr/sbin/ausearch) এর মাধ্যমে এবং প্রয়োজনে /var/log/audit/audit.log থেকে tail কমান্ড দিয়ে ইভেন্ট পড়ে। উভয়ই sudoers-এ থাকতে হবে।

21. Monit ইনস্টল করা

সার্ভিসগুলো (nginx, php-fpm, mysql ইত্যাদি) পর্যবেক্ষণ করে এবং বন্ধ হয়ে গেলে পুনরায় চালু করে। ইমেইলে অ্যালার্ট পাঠাতে পারে।

sudo apt install monit sudo systemctl enable --now monit # কনফিগ: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
মনিটর monit status এর মাধ্যমে সার্ভিসের তালিকা পায়। /etc/monit/monitrc ফাইলে HTTP ইন্টারফেস চালু থাকতে হবে (allow localhost সহ set httpd ব্লক), নাহলে monit status ত্রুটি ফেরত দেবে।
ড্যাশবোর্ডে “০টি সার্ভিস পর্যবেক্ষণাধীন”? দুটি কারণ। (১) HTTP ইন্টারফেস বন্ধ — monitrc-এ set httpd লাইনটি কমেন্ট করা আছে (ডিফল্টভাবে # set httpd port 2812 … হিসেবে থাকে)। ব্লকটি আনকমেন্ট করুন এবং localhost অনুমোদন করুন। (২) শুধু httpd চালু থাকলে তা কিছুই পর্যবেক্ষণ করে না — Monit কেবল check-স্ট্যানজায় বর্ণিত জিনিসই গণনা করে; সেগুলো ছাড়া ইন্টারফেস চালু থাকলেও তালিকা খালি থাকে। ন্যূনতম কার্যকর কনফিগ:
# /etc/monit/conf.d/00-httpd — localhost এর জন্য HTTP ইন্টারফেস: set httpd port 2812 use address localhost allow localhost # check-স্ট্যানজার উদাহরণ (কী পর্যবেক্ষণ করতে হবে): check process sshd with pidfile /run/sshd.pid start program = "/usr/bin/systemctl start ssh" stop program = "/usr/bin/systemctl stop ssh" check filesystem rootfs with path / if space usage > 90% then alert
sudo monit -t # সিনট্যাক্স যাচাই করুন (Control file syntax OK) sudo systemctl reload monit sudo monit status
অটো-ইনস্টল ২৮১২ পোর্টে httpd এবং একগুচ্ছ চেকসহ প্রস্তুত conf.d রেখে দেয় — নতুন ইনস্টলেশনে হাতে কনফিগার করার দরকার নেই।
সার্ভিস “ত্রুটিসহ” স্ট্যাটাসে? মনিটর কেবল অবস্থা দেখায় এবং ইচ্ছাকৃতভাবে ওয়েব-প্যানেল থেকে সার্ভিস পুনরায় চালু করে না (এটি নিরাপত্তা প্যানেলে রিমোট root-কমান্ড চালানোর সমতুল্য হতো)। ডায়াগনস্টিকস ও পুনরায় চালু করা — SSH দিয়ে Monit-এর মাধ্যমে:
sudo monit status <service> # ত্রুটির কারণ sudo monit restart <service> # Monit দিয়ে পুনরায় চালু # Monit যদি সার্ভিস চালু না করে — তার নিজস্ব ইউনিট দেখুন: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

22. PSAD ইনস্টল করা (পোর্ট স্ক্যান শনাক্তকরণ)

PSAD iptables লগ বিশ্লেষণ করে পোর্ট স্ক্যানিং ও নেটওয়ার্ক আক্রমণ শনাক্ত করে এবং প্রতিটি উৎসকে হুমকির মাত্রা (১–৫) নির্ধারণ করে। এটি fail2ban ও Suricata-কে সম্পূর্ণ করে।

sudo apt install psad # PSAD iptables লগ পড়ে — লগিং চালু করা দরকার (UFW নিজেই তা করে)। # শুধু iptables-এর জন্য INPUT/FORWARD চেইনে LOG নিয়ম যোগ করুন। sudo psad --sig-update sudo systemctl enable --now psad
মনিটর psad --Status দিয়ে ডেটা পড়ে (sudoers-এ থাকা দরকার)। iptables লগিং ছাড়া পৃষ্ঠাটি ফাঁকা থাকবে — কোনো স্ক্যান না হওয়া পর্যন্ত এটি স্বাভাবিক।

23. AppArmor / SELinux (অ্যাক্সেস নিয়ন্ত্রণ)

Mandatory Access Control নিয়ন্ত্রণ করে কোনও প্রোগ্রাম কোন কোন ফাইল ও রিসোর্সে অ্যাক্সেস করতে পারবে, এমনকি প্রোগ্রামটি হ্যাক হলেও। Ubuntu/Debian-এ ডিফল্টভাবে AppArmor ব্যবহৃত হয় (সাধারণত ইতিমধ্যে ইনস্টল করা ও সক্রিয়)।

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # প্রোফাইল যাচাই করুন
মনিটর aa-status-এর মাধ্যমে স্ট্যাটাস পড়ে (sudoers-এ প্রয়োজন)। enforce/complain মোডে প্রোফাইলের সংখ্যা এবং প্রোফাইলবিহীন প্রসেস দেখায়।

“লোড হওয়া প্রোফাইল” enforce + complain-এর চেয়ে বেশি হওয়া স্বাভাবিক। AppArmor 4.x (Ubuntu 24.04 ও তার নতুন সংস্করণ)-এ unconfined মোড এসেছে: প্রোফাইল কার্নেলে লোড হয়েছে, কিন্তু কিছুই সীমাবদ্ধ করে না। user namespaces ব্যবহারকারী প্রোগ্রামের (ব্রাউজার, torrent-ক্লায়েন্ট প্রভৃতি) জন্য Ubuntu এমন কয়েক ডজন প্রোফাইল এভাবে চিহ্নিত করে। এমন প্রোফাইল থাকলে “লোড হওয়া প্রোফাইল” কার্ডটি অ্যাম্বার রঙের হয়ে তাদের সংখ্যা দেখায় — যেমন ১২০টি লোড ও ২৬টি enforce থাকলে unconfined: 90। বাস্তবে কেবল enforce মোডের প্রোফাইলই সুরক্ষা দেয়; Ubuntu 22.04 (AppArmor 3.x)-এ এই মোড নেই আর সংখ্যাগুলো সবসময় মিলে যায়।

sudo aa-status | grep -E "profiles are" # মোড অনুসারে বিভাজন sudo aa-enforce /etc/apparmor.d/profile-name # প্রোফাইলটি enforce মোডে আনুন
Ubuntu যে প্রোফাইলগুলো ইচ্ছাকৃতভাবে unconfined রেখেছে সেগুলো enforce মোডে আনা কেবল বুঝেশুনেই উচিত: এগুলো ভুলবশত বন্ধ নয়, বরং এভাবে না করলে প্রোগ্রামগুলোর কাজই ভেঙে পড়ে। complain মোডের প্রোফাইল ভিন্ন ব্যাপার: সেখানে নিয়মগুলো ইতিমধ্যে লেখা আছে, কেবল প্রয়োগ হয় না।

24. debsums ইনস্টল করা (প্যাকেজের অখণ্ডতা)

debsums যাচাই করে যে ইনস্টল করা প্যাকেজের ফাইলগুলো রিপোজিটরির চেকসামের সাথে মেলে কিনা — বদলে ফেলা সিস্টেম বাইনারি শনাক্ত করে (AIDE-এর পরিপূরক)। পূর্ণ যাচাইয়ে ১–২ মিনিট লাগে, তাই এটি cron দিয়ে চলে, আর প্যানেল ফলাফল data/debsums/debsums.log থেকে পড়ে নিজেই বিভাগে সাজিয়ে নেয় (শুধু বাইনারি ও লাইব্রেরিই গুরুত্বপূর্ণ)।

কাজটি root-cron-এ যোগ হয় (sudo crontab -e)। প্রস্তুত র‍্যাপার debsums-scan.sh রাখা হয় /usr/local/bin/-এ (chmod +x; cron-কাজের সারসংক্ষেপ দেখুন) এবং নিজেই প্যানেলের data/debsums/-এ রিপোর্ট লেখে।

sudo apt install debsums # Cron-লাইন (প্রতিদিন 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

র‍্যাপার debsums-scan.sh নিজেই প্যানেলের data/ খুঁজে নেয় — পথ লেখার দরকার নেই।

সার্ভারে /etc/ (কনফিগ) ও /usr/share/ (রিসোর্স)-এর পরিবর্তন সাধারণত স্বাভাবিক — প্যানেল সেগুলো আলাদা রঙে চিহ্নিত করে। বাইনারি ও লাইব্রেরির পরিবর্তনই উদ্বেগজনক (/bin, /sbin, /usr/lib ইত্যাদি) — “বাইনারি / লাইব্রেরি” কার্ডটি ঠিক সেগুলোই দেখায়।

25. Lynis রিপোর্ট কনফিগার করা

Lynis ম্যানুয়ালি বা cron দিয়ে চালানো হয়। রিপোর্টটি প্রকল্পের data/lynis/ ফোল্ডারে সংরক্ষিত হতে হবে — মনিটর lynis-report.dat ফাইলটি পড়ে।

# একবার চালানো (আপনার প্যানেলের রুট পাথ বসান): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # দৈনিক অডিট — cron লাইন (তৈরি র‍্যাপার lynis-scan.sh আছে /usr/local/bin/-এ, সারসংক্ষেপ দেখুন): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
প্রথমবার চালানোর পর “Lynis অডিট” পৃষ্ঠায় সঙ্গে সঙ্গেই hardening index, সতর্কতা ও সুপারিশ দেখা যাবে।
Lynis পৃষ্ঠায় “অডিট চালান” বোতাম। এটি প্যানেল থেকে সরাসরি ব্যাকগ্রাউন্ডে lynis-scan.sh চালায় (cron-এর অপেক্ষা না করে): “স্ক্যান করা হচ্ছে…” দেখায় এবং শেষ হলে নিজেই রিপোর্ট আপডেট করে। এর জন্য ওয়েব-ব্যবহারকারীর স্ক্রিপ্ট চালানোর একটি sudoers লাইন দরকার — ইনস্টলার এটি /etc/sudoers.d/monitor-এ স্বয়ংক্রিয়ভাবে যোগ করে। প্যানেলটি ম্যানুয়ালি/আগে বসানো হলে, ফাইলে ইতিমধ্যে উল্লিখিত সেই একই ব্যবহারকারী দিয়ে এটি যোগ করুন:
u=$(sudo awk '/NOPASSWD/ && !/lynis-scan/ {print $1; exit}' /etc/sudoers.d/monitor) [ -n "$u" ] && echo "$u ALL=(ALL) NOPASSWD: /usr/local/bin/lynis-scan.sh" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c && sudo chmod 440 /etc/sudoers.d/monitor

26. Logwatch রিপোর্ট কনফিগার করা

Logwatch-কে প্রতিদিনের রিপোর্ট প্রকল্পের data/logwatch/ ফোল্ডারে .txt ফরম্যাটে সংরক্ষণ করতে হবে। মনিটর সর্বশেষ রিপোর্ট ও আর্কাইভ দেখায়।

# প্রতিদিন (6:00) — cron লাইন (/usr/local/bin/-এ তৈরি র‍্যাপার logwatch_daily.sh, সারসংক্ষেপ দেখুন): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

প্যানেল মডিউল

27. নেটওয়ার্ক মনিটর (অন্তর্নির্মিত)

নেটওয়ার্ক মনিটরে ইনস্টলেশন লাগে না — এটি ড্যাশবোর্ডের একটি অন্তর্নির্মিত পৃষ্ঠা। এটি স্থানীয় উৎস থেকে সার্ভারের নেটওয়ার্ক অবস্থা দেখায়:

  • ইন্টারফেস ও ট্রাফিক — /proc/net/dev থেকে;
  • লিঙ্কের অবস্থা (UP/DOWN) ও IP — ip দিয়ে;
  • সংযোগ ও শোনা পোর্ট — ss দিয়ে;
  • ২৪ ঘণ্টায় কার্নেলের নেটওয়ার্ক ইভেন্ট — journalctl -k দিয়ে।

প্রথম তিনটি উৎস sudo ছাড়াই কাজ করে, তাই ইন্টারফেস, ট্রাফিক, সংযোগ ও পোর্ট সঙ্গে সঙ্গেই দেখা যায়। “কার্নেল ইভেন্ট” ব্লকটি journalctl -k ব্যবহার করে — এটি systemd-journal গ্রুপের মাধ্যমে পড়া হয় (“sudo কনফিগারেশন”, ধাপ ২), sudo লাগে না। ওয়েব-ব্যবহারকারীর কাছে সবকিছু অ্যাক্সেসযোগ্য কিনা যাচাই করুন:

# www-data হিসেবে যাচাই (এর অধীনেই PHP চলে): sudo -u www-data bash -c 'cat /proc/net/dev' sudo -u www-data bash -c 'ip -o link show' sudo -u www-data bash -c 'ss -s' sudo -u www-data journalctl -k --no-pager -n 5
“কার্নেলের নেটওয়ার্ক ইভেন্ট” ব্লকটি কার্নেল নেটওয়ার্ক স্ট্যাকের ইভেন্ট দেখায় (লিঙ্ক up/down পরিবর্তন, ক্যারিয়ার ত্রুটি, “network unreachable”)। ফায়ারওয়ালের UFW BLOCK এন্ট্রি এখানে আসে না — সেগুলি “UFW ফায়ারওয়াল” ও “অ্যাটাক ম্যাপ” পৃষ্ঠায় থাকে। সবুজ টিকসহ খালি ব্লক = গত ২৪ ঘণ্টায় কোনো নেটওয়ার্ক সমস্যা হয়নি।

28. ডিস্ক ও SMART

বিল্ট-ইন পৃষ্ঠাটি তিনটি জিনিস দেখায়:

  • ফাইল সিস্টেম — পার্টিশনের ব্যবহার (df); ≥৯০% হলে বার লাল হয়ে যায়;
  • স্টোরেজ ডিভাইস — ডিস্কের তালিকা (lsblk), শুধু বাস্তবগুলো (loop/snap লুকানো);
  • স্বাস্থ্য (SMART) — ডিস্কের স্ট্যাটাস ও অ্যাট্রিবিউট (smartctl)।

জায়গা ও ডিভাইসের তালিকা কোনো সেটিংস ছাড়াই সঙ্গে সঙ্গে কাজ করে। SMART-এর জন্য smartmontools প্যাকেজটি দরকার। ওয়েব-প্রসেসের ডিস্ক ডিভাইসে সরাসরি অ্যাক্সেস নেই, তাই SMART cron দিয়ে data/disk/smart.txt ফাইলে সংগ্রহ করা হয়, আর ড্যাশবোর্ড সেটি পড়ে।

টাস্কটি root-cron-এ থাকে (sudo crontab -e)। প্রস্তুত র‍্যাপার smart-scan.sh /usr/local/bin/-এ রাখা হয় (chmod +x; cron-টাস্কের সারসংক্ষেপ দেখুন) এবং নিজেই ড্যাশবোর্ডের data/disk/-এ লেখে।

sudo apt install smartmontools # Cron-লাইন (প্রতি ৩০ মিনিটে): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

র‍্যাপার smart-scan.sh নিজেই ড্যাশবোর্ডের data/ খুঁজে নেয় — পাথ লেখার দরকার নেই। ভেতরে lsblk -e7,11 loop/cdrom বাদ দেয়।

ভার্চুয়াল ডিস্কে (QEMU/KVM ও অনুরূপ) সাধারণত কেবল সাধারণ স্ট্যাটাস “স্বাস্থ্য: OK” পাওয়া যায়, আর তাপমাত্রা, কর্মঘণ্টা ও রিঅ্যালোকেটেড সেক্টর খালি থাকতে পারে — এটা স্বাভাবিক। ফিজিক্যাল সার্ভারে সব অ্যাট্রিবিউট দেখা যায়।

29. পারফরম্যান্স (CPU/RAM/নেটওয়ার্ক/ডিস্ক)

এই পৃষ্ঠাটি গত ২৪ ঘণ্টার সার্ভার লোডের ইতিহাস দেখায় — Load Average, CPU ব্যস্ততা ও I/O অপেক্ষা, RAM/Swap, নেটওয়ার্ক ট্রাফিক (গ্রহণ/প্রেরণ), ডিস্ক I/O (পঠন/লিখন), ডিস্ক ও inodes পূরণ, খোলা ফাইল ডেসক্রিপ্টর ও MySQL সংযোগ, এবং বর্তমান TCP সংযোগ ও প্রসেসের সংখ্যা।

ডেটা সংগ্রহ করে cron/collect_metrics.php — প্রতি ৫ মিনিটে কাউন্টারের একটি “র” স্ন্যাপশট (/proc/loadavg, /proc/meminfo, /proc/stat, /proc/net/dev, /proc/diskstats, df/df -i, /proc/sys/fs/file-nr, SHOW GLOBAL STATUS LIKE 'Threads_connected') DB টেবিল system_metrics-এ লেখে; শতাংশ ও গতি পৃষ্ঠাটি নিজেই পাশাপাশি দুটি স্ন্যাপশটের পার্থক্য থেকে হিসাব করে (ডিস্ক/inodes/ডেসক্রিপ্টর পূরণ ও MySQL সংযোগ — তাৎক্ষণিক মান, পুনর্গণনা ছাড়াই)। Sudo লাগে না — উৎসগুলো root অধিকার ছাড়াই পড়া হয়। ২৪ ঘণ্টার চেয়ে পুরনো পয়েন্ট প্রতিটি লেখার সময় স্বয়ংক্রিয়ভাবে মুছে যায়।

# Cron-লাইন (প্রতি ৫ মিনিটে): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

র‍্যাপার collect-metrics-all.sh (cron-কাজের সারসংক্ষেপ দেখুন) নিজেই সার্ভারে ইনস্টল করা সমস্ত প্যানেল ইনস্ট্যান্স খুঁজে বের করে এবং প্রতিটির cron/collect_metrics.php সাইটের মালিকের নামে চালায়।

কালেক্টর অন্তত দুবার না চলা পর্যন্ত (ইনস্টলের পর প্রথম ~১০ মিনিট), পৃষ্ঠাটি “ডেটা সংগ্রহ করা হচ্ছে” দেখায় — গতি ও শতাংশ হিসাব করতে গ্রাফের অন্তত পাশাপাশি এক জোড়া পয়েন্ট দরকার।

লোড সংক্রান্ত সতর্কতা (“সেটিংস” → “লোড সংক্রান্ত সতর্কতা” বিভাগ) — CPU/RAM/ডিস্ক/inodes-এর সীমা ছাড়িয়ে গেলে প্যানেল Telegram/Email-এ বিজ্ঞপ্তি পাঠায় (দৈনিক রিপোর্টের মতোই একই চ্যানেল — অ্যালার্টের জন্য আলাদাভাবে চালু করার দরকার নেই), এবং মেট্রিক স্বাভাবিকে ফিরলে আরও একটি। সীমা ধরে রাখার সময় বারবার স্প্যাম করে না: পরের বিজ্ঞপ্তি কেবল “স্বাভাবিক হলো → আবার ছাড়িয়ে গেল” চক্রের পরেই আসবে।

সীমাগুলো প্রতিবার চালানোর সময় (প্রতি ৫ মিনিটে) একই collect_metrics.php পরীক্ষা করে — আলাদা cron লাগে না। “ইতিমধ্যে বিজ্ঞপ্তি পাঠানো হয়েছে / এখনও নয়” অবস্থা data/alerts_state.json-এ সংরক্ষিত থাকে, আর সীমা প্যানেলের সেটিংসে।

30. আক্রমণের মানচিত্র (GeoIP)

“আক্রমণের মানচিত্র” পৃষ্ঠাটি geoiplookup কমান্ড দিয়ে IP থেকে দেশ শনাক্ত করে। GeoIP প্যাকেজ ছাড়া দেশ শনাক্ত হবে না এবং মানচিত্রে বিন্দু দেখা যাবে না:

sudo apt install geoip-bin geoip-database # যাচাই: geoiplookup 8.8.8.8
Sudo প্রয়োজন নেই — /usr/share/GeoIP/GeoIP.dat ডেটাবেস সবাই পড়তে পারে, ফলাফল tmp/geoip_cache.json-এ ক্যাশ হয়। মানচিত্রটি নিজে (Leaflet + OpenStreetMap টাইল) ব্রাউজারে লোড হয় — যে কম্পিউটারে ড্যাশবোর্ড খোলা, সেখানে ইন্টারনেট প্রয়োজন।

31. বাহ্যিক এক্সপোজার, আপডেট এবং স্বয়ংক্রিয় আপডেট

ড্যাশবোর্ডের দুটি অন্তর্নির্মিত কার্ড, যা কোনো টুলের “চালু/বন্ধ” নয়, বরং সার্ভারের প্রকৃত সুরক্ষা দেখায়। এগুলোর ইনস্টল লাগে না, sudo ছাড়াই স্থানীয়ভাবে পড়া যায়।

বাহ্যিক এক্সপোজার — কতগুলো সার্ভিস সব ইন্টারফেস (0.0.0.0/[::]) শোনে এবং বাইরে থেকে অ্যাক্সেসযোগ্য। বাইরের দিকে যদি DBMS বা ক্যাশ (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) উন্মুক্ত থাকে তবে লাল রঙে দেখায় — এটি সরাসরি ফাঁক (নিরাপত্তা স্কোরে −10)। উৎস: ss -tuln

কার্ডটি লাল হলে — DBMS বাইরের জগৎ থেকে বন্ধ করুন: 127.0.0.1-এ বাঁধুন (MySQL/PostgreSQL কনফিগে bind-address, Redis-এ bind 127.0.0.1) অথবা UFW-তে পোর্ট বন্ধ করুন।
“খোলা পোর্ট” ≠ “বাইরে থেকে অ্যাক্সেসযোগ্য”। 127.0.0.1 (loopback) শোনে এমন সার্ভিস কেবল সার্ভারটিরই কাছে দৃশ্যমান — পোর্ট “খোলা” থাকলেও বাইরে থেকে সেখানে পৌঁছানো যায় না। তাই loopback-এ বাঁধা 25 পোর্টের Postfix নিরাপদ: স্বয়ংক্রিয় সেটআপ inet_interfaces = loopback-only নির্ধারণ করে (সাথে নিরপেক্ষ smtpd_banner — সংস্করণ প্রকাশ সম্পর্কে Lynis-এর MAIL-8818 মন্তব্য বন্ধ করে)। “বাহ্যিক এক্সপোজার” কার্ড বাইরের দিকে কেবল সেগুলোই গণনা করে যেগুলো 0.0.0.0/[::] শোনে; loopback-সার্ভিস সেখানে ধরা পড়ে না।
Lynis MAIL-8818 ম্যানুয়ালি (মেইল নিজে সেটআপ করলে): /etc/postfix/main.cf-তে smtpd_banner = $myhostname ESMTP (সংস্করণ ও OS ছাড়া) এবং inet_interfaces = loopback-only নির্ধারণ করুন, তারপর sudo systemctl restart postfix

নিরাপত্তা আপডেট — কতগুলো security-প্যাচ ইনস্টলের অপেক্ষায় এবং কার্নেল আপডেটের পর রিবুট দরকার কিনা (প্যাচ থাকলে নিরাপত্তা স্কোরে −5)। উৎস: /usr/lib/update-notifier/apt-check, ফাইল /var/run/reboot-required। বিস্তারিত তালিকা — “নিরাপত্তা আপডেট” পৃষ্ঠায়।

# আপডেট ইনস্টল করুন: sudo apt update && sudo apt upgrade # বাইরের দিকে কী শোনে তা পরীক্ষা করুন: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
আপডেট কার্ড Ubuntu/Debian-এ কাজ করে (update-notifier-common)। apt-check না থাকলে — মনিটর apt-get -s upgrade দিয়ে প্যাচ গণনা করে।

স্বয়ংক্রিয় নিরাপত্তা আপডেট (unattended-upgrades) — “নিরাপত্তা আপডেট” পৃষ্ঠায় একটি আলাদা কার্ড দেখায় যে security-প্যাচের স্বয়ংক্রিয় ইনস্টল চালু আছে কিনা এবং সর্বশেষ কখন তা চলেছে। sudo লাগে না — স্ট্যাটাস apt-config dump দিয়ে পড়া হয়।

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # চালু করুন # কী চালু আছে তা পরীক্ষা করুন: apt-config dump | grep Unattended-Upgrade

রক্ষণাবেক্ষণ

32. ব্যাকআপ

ব্যাকআপই প্রধান বিমা: ডেটা হারানো যেকোনো হ্যাকের চেয়ে ভয়ংকর। দুটি জিনিস দরকার — সার্ভার/সাইটের ব্যাকআপ এবং আলাদাভাবে প্যানেলের ডেটাবেসের ব্যাকআপ (সেখানে ব্যবহারকারী, WebAuthn কী, সেটিংস, লাইসেন্স থাকে)।

বিকল্প A — HestiaCP: ব্যবহারকারীর Backup ট্যাব → ব্যাকআপ তৈরির বোতাম (বা সার্ভার সেটিংসে সময়সূচী অনুযায়ী)। ব্যাকআপে সাইট ও তাদের ডেটাবেস অন্তর্ভুক্ত থাকে।

বিকল্প B — ম্যানুয়ালি (cron): ডেটাবেস ডাম্প + প্যানেলের data/ ডিরেক্টরির আর্কাইভ:

# root-cron (sudo crontab -e) — প্রতিদিন 2:30-এ ব্যাকআপ (নিজের নাম/পাথ বসান): 30 2 * * * mysqldump -u root MY_DB | gzip > /var/backups/monitor-db-$(date +\%F).sql.gz 40 2 * * * tar czf /var/backups/monitor-data-$(date +\%F).tar.gz -C /path/to/monitor data # ১৪ দিনের বেশি পুরনো আর্কাইভ মুছে ফেলুন: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
একই সার্ভারে ব্যাকআপ ভুলত্রুটি থেকে বাঁচায়, কিন্তু সার্ভার হারানো থেকে নয়। আর্কাইভগুলো বাহ্যিক স্টোরেজে কপি করুন (অন্য সার্ভার, S3, rclone দিয়ে ক্লাউডে)। পুনরুদ্ধার সত্যিই কাজ করছে কিনা যাচাই করুন।

33. প্যানেল আপডেট ও স্থানান্তর

নতুন সংস্করণে আপডেট। প্রথমে ব্যাকআপ নিন। এরপর নিজের ডেটা রেখে কোড ফাইলগুলো পুনরায় আপলোড করুন:

  • ওভাররাইট করুন (কোড): public/, includes/, assets/, cron/, database/, এবং রুট-এর .htaccess (ফ্রন্ট-কন্ট্রোলার — রাউটিং পুরনো সংস্করণের রাখা যাবে না), manifest.json, sw.js;
  • যা ছোঁবেন না: config.php (ডেটাবেস তথ্য), data/ (রিপোর্ট), logs/, tmp/ (সেশন ও ক্যাশ)।
# আপলোডের পর — PHP ক্যাশ রিসেট করুন (opcache চালু থাকলে): sudo systemctl reload php*-fpm
FileZilla দেখাচ্ছে SSH_FX_PERMISSION_DENIEDPermission denied প্যানেলের ফাইলগুলো www-data-এর মালিকানাধীন (ইনস্টলেশনের সময় এভাবেই সেট করা হয়েছিল), আর SFTP ক্লায়েন্ট সংযোগ করে আপনার নিজের ব্যবহারকারী দিয়ে, যার লেখার অনুমতি নেই। “চালু হোক” ভেবে পুরো প্যানেল www-data-কে দিয়ে দেওয়াই ঠিক এই ত্রুটির কারণ; নিচে তিনটি পদ্ধতি, যেকোনোটিই সমস্যা সমাধান করে।
# বিকল্প A (প্রস্তাবিত) — মালিকানা ভাগ করুন: কোড আপনার, কাজের ফোল্ডার ওয়েব সার্ভারের। # ওয়েব সার্ভার প্যানেলের কোডে লেখার অনুমতি একেবারেই পায় না: sudo chown -R deploy:www-data /path/to/monitor sudo chown -R www-data:www-data /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo find /path/to/monitor -type d -exec chmod 755 {} \; sudo find /path/to/monitor -type f -exec chmod 644 {} \; sudo chmod 750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo chmod 640 /path/to/monitor/config.php # বিকল্প B — বর্তমান মালিকানার উপরে ACL (কিছুই স্থানান্তর করি না): sudo apt install -y acl sudo setfacl -R -m u:deploy:rwX /path/to/monitor sudo setfacl -R -d -m u:deploy:rwX /path/to/monitor # বিকল্প C — www-data গ্রুপের মাধ্যমে। সহজ, তবে প্যানেলের ফাইলে লেখার অনুমতি # ওয়েব সার্ভারও পায় (PHP-তে দুর্বলতা থাকলে কোড বদলে দেওয়া সম্ভব): sudo usermod -aG www-data deploy sudo find /path/to/monitor -type d -exec chmod 2775 {} \; sudo find /path/to/monitor -type f -exec chmod 664 {} \; sudo chmod 640 /path/to/monitor/config.php sudo chmod 2750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs
বিকল্প A কেন নিরাপদ। প্যানেল কেবল তিনটি ডিরেক্টরিতে লেখে — data/ (রিপোর্ট), tmp/ (সেশন ও ক্যাশ), logs/; সেগুলো www-data-এর অধীনেই থাকে। বাকিটা কোড, আর ওয়েব সার্ভারের কেবল পড়ার প্রয়োজন, যা 644 অনুমতিসহ www-data গ্রুপ দিয়ে থাকে। বাড়তি সুবিধা: PHP-তে দুর্বলতা থাকলেও প্যানেলের ফাইল আর বদলানো যায় না। হোস্টিং প্যানেলে (HestiaCP ও সমজাতীয়) বিকল্প A প্রয়োজন নেই: সেখানে সাইটের ফাইল এমনিতেই সেই অ্যাকাউন্টের মালিকানাধীন যা দিয়ে আপনি SFTP-তে ঢোকেন, আর ওয়েব সার্ভার সেগুলো গ্রুপ দিয়ে পড়ে।
বিকল্প B-এর ফাঁদ: ফাইলের উপর পরবর্তী যেকোনো chmod ACL-মাস্ক রিসেট করে দেয়, আর অ্যাক্সেস নীরবে হারিয়ে যায়। যদি “অনুমতি গোছানোর” পরে আপলোড আবার Permission denied-এ আটকে যায় — setfacl দুটি কমান্ডই আবার চালান।
বিকল্প C-এর 2 বিটটিই setgid: SFTP-তে আপলোড করা ফাইল www-data গ্রুপে থেকে যায়, নইলে প্যানেল সেগুলো পুনরায় লিখতে পারবে না। বিকল্প C-এর পরে FileZilla-তে আবার সংযোগ করুন — নতুন গ্রুপ কেবল নতুন লগইনেই কার্যকর হয়। যাচাই: id deploy (www-data গ্রুপ দেখা যেতে হবে) এবং ls -ld /path/to/monitor (drwxrwsr-xs অক্ষরের মানে setgid সেট করা আছে)।

অন্য সার্ভারে স্থানান্তর:

  1. নতুন সার্ভারে সাইট + HTTPS চালু করুন (দেখুন ম্যানুয়াল ইনস্টলেশন পৃষ্ঠা)।
  2. প্যানেলের সব ফাইল config.php, data/ সহ কপি করুন।
  3. ডেটাবেস স্থানান্তর করুন: পুরনোতে mysqldump → নতুনে ইমপোর্ট; config.php-এ ডেটাবেস তথ্য সংশোধন করুন।
  4. নতুন সার্ভারে পুনরায় সেট করুন: sudoers, adm গ্রুপে সদস্যপদ, cron-কাজ।
  5. লাইসেন্স ডোমেনের সাথে বাঁধা — ডোমেন একই থাকলে কী কাজ করতে থাকবে।

34. অ্যাক্সেস পুনরুদ্ধার (হারানো কী, পাসওয়ার্ড, IP-ব্লক)

যদি লগ-ইন করতে না পারেন — সবকিছু সার্ভার থেকে সরাসরি ডেটাবেসে ঠিক করা যায়। ডেটাবেস খুলুন (নাম — config.php থেকে):

sudo mysql MY_DB

WebAuthn কী হারিয়েছেন (দ্বিতীয় ফ্যাক্টর পার হচ্ছে না) — 2FA বন্ধ করুন, পাসওয়ার্ড দিয়ে লগ-ইন করুন, নতুন কী নিবন্ধন করুন:

UPDATE users SET webauthn_enabled = 0;

পাসওয়ার্ড ভুলে গেছেন — নতুন হ্যাশ সেট করুন (সার্ভারে তৈরি করে বসিয়ে দিন):

# নতুন পাসওয়ার্ডের হ্যাশ তৈরি করুন: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # ডেটাবেসে (পাওয়া হ্যাশটি বসান): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

IP-ফিল্টারে নিজেকে ব্লক করে ফেলেছেন — সীমাবদ্ধতা বন্ধ করুন:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
ডেটাবেসে অ্যাক্সেস সবসময় থাকে: সার্ভারে sudo mysql, অথবা phpMyAdmin / হোস্টিং প্যানেলের ডেটাবেস বিভাগ। পুনরুদ্ধারের পর WebAuthn ও IP-ফিল্টার আবার চালু করুন।

35. সব cron-জব একসঙ্গে এক জায়গায়

জবগুলোর সারসংক্ষেপ থাকে সার্ভারের root-cron-এ (যোগ করা হয় sudo crontab -e দিয়ে)। আপনি যেসব টুল ব্যবহার করেন কেবল সেগুলোর লাইন রেখে দিন; পাথগুলো নিজের সার্ভার অনুযায়ী ঠিক করে নিন।

# মনিটরের সার্ভার cron (root) — যোগ করুন: sudo crontab -e দিয়ে # 01:30 — বিপজ্জনক পাথে (web, home, temp) ClamAV স্ক্যান → “ফাইল যাচাই হয়েছে” ও “সর্বশেষ স্ক্যান” কার্ড 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — AIDE দিয়ে ফাইলের ইনটিগ্রিটি যাচাই (স্পষ্ট --config লাগে) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # চালু হওয়ার সময় — /var/lib/aide-এর পারমিশন পুনরুদ্ধার করুন (প্যাকেজ tmpfiles-ফাইল # aide-common.conf সেগুলো 0700-এ রিসেট করে, ফলে প্যানেল ডেটাবেস আর দেখতে পায় না) @reboot chmod 755 /var/lib/aide # 03:00 — Lynis সিকিউরিটি অডিট 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — ipsum ব্লক-লিস্ট আপডেট (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # চালু হওয়ার সময় ipsum সেট তোলে ipsum-load.service (ফায়ারওয়ালের আগে, নইলে # UFW before.rules-এ সেটটি দেখতে পাবে না) — এটা cron নয়। এখানে কেবল উপরের প্রতিদিনের রিফ্রেশ। # 06:00 — Logwatch রিপোর্ট 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # প্রতি 30 মিনিটে — SMART ডিস্ক যাচাই */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — debsums প্যাকেজ ইনটিগ্রিটি 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — Email ও Telegram-এ নির্ধারিত রিপোর্ট 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # প্রতি ঘণ্টায় — প্যাকেজ তালিকা রিফ্রেশ (“নিরাপত্তা আপডেট” কার্ডের জন্য) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # প্রতি 5 মিনিটে — “পারফরম্যান্স” পেজের জন্য রিসোর্সের স্ন্যাপশট (CPU/RAM/নেটওয়ার্ক/ডিস্ক) */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1
প্রতিটির বিস্তারিত সংশ্লিষ্ট অংশে দেওয়া আছে। ব্যাকআপ-জব (আগের অংশ) এই একই cron-এ যোগ হয়। সম্পাদনার পরে যাচাই করুন: sudo crontab -l এবং cron-সার্ভিস সক্রিয় কিনা।
cron-এর সময় = সার্ভারের টাইমজোন, config.php-এর TIMEZONE নয়। TIMEZONE কনস্ট্যান্ট শুধু PHP-তে প্রভাব ফেলে (প্যানেল কীভাবে তারিখ দেখায়), কিন্তু cron-ডিমন জবগুলো চালায় OS-এর সিস্টেম সময় অনুযায়ী। সার্ভারের টাইমজোন আপনার সঙ্গে না মিললে “08:00”-এর রিপোর্ট ভুল সময়ে আসবে। উদাহরণ: সার্ভার অন্য টাইমজোনে (Asia/Karachi, UTC+5), আর আপনি ঢাকায় (UTC+6) → “08:00”-এর রিপোর্ট আপনার সময়ে 09:00-এ আসবে। যাচাই করুন এবং প্রয়োজনে সিস্টেমের টাইমজোন নিজের মতো ঠিক করে নিন:
# সার্ভারের বর্তমান টাইমজোন যাচাই করুন: timedatectl # নিজের টাইমজোন সেট করুন (উদাহরণ) এবং cron রিস্টার্ট করুন: sudo timedatectl set-timezone Asia/Dhaka sudo systemctl restart cron
এরপর 0 8 * * * লাইনটি স্থানীয় সময় অনুযায়ী 08:00-এ চলবে। নইলে cron নিজেই সরাতে হতো, কিন্তু শীত/গ্রীষ্মকালীন সময়ে পরিবর্তনের সময় ব্যবধান আবার এলোমেলো হয়ে যাবে — তাই সিস্টেমের টাইমজোন সেট করাই সঠিক।
রেডিমেড র‍্যাপার-স্ক্রিপ্ট। এগুলোর কার্যকর কপি ও crontab-এর নমুনা (crontab.txt) প্রজেক্টের পাশে system/ ফোল্ডারে থাকে, public_html-এর বাইরে। এটি সাইটের অংশ নয় — ওয়েব-রুটে এগুলো আপলোড করার দরকার নেই; সার্ভারে সিস্টেম-পাথে রাখুন (উপরের crontab-এর মতো):
  • lynis-scan.sh/usr/local/bin/ (chmod +x) — lynis audit system চালায়, স্ক্যানের সময় /tmp/lynis-running ফ্ল্যাগ বসায় এবং lynis-report.dat প্যানেলের data/lynis/-এ কপি করে;
  • logwatch_daily.sh/usr/local/bin/ (chmod +x) — প্রতিদিনের Logwatch রিপোর্ট (sshd, fail2ban, sudo, postfix) data/logwatch/-এ তৈরি করে;
  • smart-scan.sh/usr/local/bin/ (chmod +x) — ডিস্কের অবস্থা (smartctl) data/disk/-এ সংগ্রহ করে;
  • debsums-scan.sh/usr/local/bin/ (chmod +x) — প্যাকেজের ইনটিগ্রিটি (debsums) data/debsums/-এ যাচাই করে;
  • clamav-scan.sh/usr/local/bin/ (chmod +x) — বিপজ্জনক পাথে (web, home, temp) ClamAV অ্যান্টিভাইরাস স্ক্যান; সারসংক্ষেপ /var/log/clamav/scan.log-এ লেখে, যেখান থেকে ClamAV পেজ তা পড়ে (উপরের crontab-এ 01:30 লাইন);
  • load-ipsum.sh/usr/local/bin/ (chmod +x) — ipsum ipset সেট (level 1) জায়গাতেই আপডেট করে, চালু ফায়ারওয়াল নিয়ম না ভেঙে (উপরের crontab-এ 04:00 লাইন);
  • daily-report-all.sh/usr/local/bin/ (chmod +x) — প্যানেলের cron/daily_report.php রিপোর্ট চালায় (উপরের crontab-এ 08:00 লাইন);
  • daily_report.php — প্যানেলের মধ্যে আগে থেকেই আছে (cron/daily_report.php), daily-report-all.sh দিয়ে চলে, আলাদা বসানোর দরকার নেই;
  • collect-metrics-all.sh/usr/local/bin/ (chmod +x) — প্যানেলের cron/collect_metrics.php চালায় (“পারফরম্যান্স” পেজ, উপরের crontab-এ */5 লাইন); collect_metrics.php প্যানেলের মধ্যে আগে থেকেই আছে, আলাদা বসানোর দরকার নেই;
  • crontab.txt (system/cron/) — জবের নমুনা; প্রয়োজনীয় লাইনগুলো sudo crontab -e দিয়ে যোগ করুন।
crontab-এ স্ক্রিপ্টের পাথ অবশ্যই আপনি যেখানে রেখেছেন তার সঙ্গে মিলতে হবে।
স্ক্রিপ্ট /usr/local/bin/-এ কীভাবে রাখবেন। FileZilla থেকে সরাসরি সেখানে লেখা যায় না — ডিরেক্টরিটি root-এর মালিকানায়, আর SFTP-ক্লায়েন্ট SSH_FX_PERMISSION_DENIED পাবে। ক্রমটি এমন: প্রথমে ফাইলটি /tmp-এ আপলোড করুন (সেখানে সবাই লিখতে পারে), তারপর একটি কমান্ডেই সেটি জায়গামতো সরান:
# FileZilla-তে: “রিমোট সাইট” ফিল্ডে /tmp লিখে সেখানে স্ক্রিপ্ট আপলোড করুন, # তারপর SSH দিয়ে (install সঙ্গে সঙ্গে মালিকানা ও পারমিশন বসায়, chown/chmod লাগে না): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # যাচাই: ফাইল জায়গামতো আছে, পারমিশন rwxr-xr-x, সিনট্যাক্স অক্ষত bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
ডিরেক্টরি গুলিয়ে ফেলবেন না: সার্ভারের রুটে থাকা /tmp দরকার — /var/tmp নয় এবং প্যানেলের ভেতরের tmp/-ও নয় (শেষেরটি www-data-এর মালিকানায় ও আপনার ইউজারের কাছে বন্ধ)। FileZilla-র ট্রিতে /tmp হলো উপরের স্তরের একটি শাখা, var-এর পাশে, তার ভেতরে নয়।
সার্ভার স্বয়ংক্রিয় কনফিগারেশনে বসিয়েছিলেন? এই র‍্যাপার ও তাদের cron-জব স্ক্রিপ্ট দিয়ে ইতিমধ্যে ইনস্টল হয়ে গেছে (/usr/local/bin/-এ, লগ — /var/log/arciveo-cron.log) — ম্যানুয়ালি কিছু করার দরকার নেই।
স্ক্রিপ্টগুলো প্যানেল কোথায় খোঁজে। র‍্যাপারগুলো ডোমেন-নিরপেক্ষ: /home/*/web/*/public_html/var/www/* ঘেঁটে প্যানেলের ইনস্টলেশন খুঁজে বের করে এবং রিপোর্ট তাদের data/-তে রাখে। প্যানেল অন্য পাথে থাকলে — স্ক্রিপ্টের ভেতরের for app in … লাইনে সেটি যোগ করুন, নইলে Lynis/SMART/debsums/Logwatch-এর রিপোর্ট প্যানেলে পৌঁছাবে না।
cron.log ও অ্যাক্সেস পারমিশন। logs/cron.log ফাইলটি প্রথমে তৈরি করে root-cron — এটি root-এর মালিকানায় থাকবে, ফলে প্যানেলের “cron জার্নাল” ট্যাব সেটি পড়তেও পারবে না, পরিষ্কারও করতে পারবে না। ফাইলটি আগেভাগেই ওয়েব-ইউজারের নামে তৈরি করুন (সাইট ডিরেক্টরির মালিক; HestiaCP-তে এটি একটি অ্যাকাউন্ট, যেমন admin) — তখন root-cron কেবল যোগ করে লিখবে, মালিকানা বদলাবে না:
# ওয়েব-ইউজারের নামে আগেভাগে তৈরি করুন (cron-লাইন যোগ করার আগে): sudo -u OWNER touch /path/to/monitor/logs/cron.log # cron.log যদি root-cron আগেই তৈরি করে ফেলে — ওয়েব-ইউজারকে দিন: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
ডিরেক্টরির মালিক জানতে: stat -c %U /path/to/monitor
প্যানেল থেকে পরিচালনা। “সিস্টেম” অংশে একটি “Crontab” পেজ আছে — SSH ছাড়াই জব দেখা ও যোগ করা যায়। প্যানেল কেবল সেই জবগুলোই সম্পাদনা করে যেগুলো এটির মাধ্যমেই যোগ করা হয়েছে (root-crontab-এ পরিষেবা-কমেন্ট দিয়ে চিহ্নিত আলাদা ব্লক); crontab-এ ইতিমধ্যে থাকা সবকিছু (উপরের তালিকা) সেখানে read-only “সার্ভারের অন্যান্য জব” তালিকায় দেখানো হয় “এডিটরে কপি করুন” বোতাম সহ — এটি কেবল সময়সূচি/কমান্ড যোগ করার ফর্মে সরিয়ে নেয়, মূল লাইন ছোঁয় না। বিদ্যমান একটি জবকে প্যানেলের অধীনে “আনতে” — এটি এডিটরে কপি করুন, সংরক্ষণ করুন, তারপর পুরনো লাইনটি ম্যানুয়ালি মুছে ফেলুন (sudo crontab -e), নইলে এটি দুবার চলবে।
সার্ভারে একবারের সেটআপ। পেজটির একটি প্রিভিলেজড র‍্যাপার-স্ক্রিপ্ট দরকার — সরাসরি sudo crontab নয় (তাহলে প্যানেলের সেশনে অ্যাক্সেস পাওয়া যে কেউ সরাসরি root-এ এসকেলেট করতে পারত), বরং দুটি কমান্ড (list/set) সহ একটি সংকীর্ণ স্ক্রিপ্ট, যা কেবল পরিষেবা-কমেন্টের মাঝে থাকা নিজের ব্লকটিই ছোঁয়। একবার ইনস্টল করুন:
sudo install -m 0755 -o root -g root /dev/stdin /usr/local/sbin/arciveo-cron <<'ARCIVEO_CRON_EOF' #!/bin/bash set -euo pipefail BEGIN='# >>> ARCIVEO-CRON-MANAGED (edited from the panel; do not edit by hand) >>>' END='# <<< ARCIVEO-CRON-MANAGED <<<' cmd=${1:-} case "$cmd" in list) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} list" >&2; exit 2; } crontab -l -u root 2>/dev/null || true ;; set) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} set (body on stdin)" >&2; exit 2; } body=$(cat) if grep -qF "$BEGIN" <<<"$body" || grep -qF "$END" <<<"$body"; then echo "invalid body: markers not allowed" >&2; exit 2 fi current=$(crontab -l -u root 2>/dev/null || true) tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT { if grep -qF "$BEGIN" <<<"$current"; then awk -v b="$BEGIN" '{print} $0==b{exit}' <<<"$current" else [ -n "$current" ] && printf '%s\n' "$current" echo "$BEGIN" fi printf '%s\n' "$body" echo "$END" if grep -qF "$END" <<<"$current"; then awk -v e="$END" 'f{print} $0==e{f=1}' <<<"$current" fi } > "$tmp" crontab -u root "$tmp" ;; *) echo "usage: ${0##*/} <list|set>" >&2; exit 2 ;; esac ARCIVEO_CRON_EOF echo "www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/arciveo-cron" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c
ওয়েব-ইউজার www-data থেকে ভিন্ন হতে পারে — সাইটের PHP-FPM পুল কার নামে চলছে তা যাচাই করুন (ps -o user= -C php-fpm) এবং সেটি sudoers-লাইনে বসান।
নতুন ফাইল ভুল মালিকানায় আপলোড হয়েছে — পেজ “Access denied.” দেখাচ্ছে। যদি public/crontab_monitor.php ফাইলটি FTP/SFTP-তে সাইটের অন্য ফাইলের চেয়ে আলাদা সিস্টেম-ইউজারে (যেমন root) আপলোড হয়, ওয়েব-সার্ভার সেটি পড়তে পারবে না। পাশের ফাইলের সঙ্গে মালিকানা ও পারমিশন মিলিয়ে নিয়ে ঠিক করুন:
ls -la public/crontab_monitor.php public/ssl_monitor.php sudo chown OWNER:OWNER public/crontab_monitor.php sudo chmod 644 public/crontab_monitor.php

ডায়াগনস্টিকস

36. টুল ইনস্টল করা আছে, তবু “ইনস্টল করা নেই” দেখাচ্ছে

Monitor dpkg-query — APT প্যাকেজ ডেটাবেসের মাধ্যমে টুলের উপস্থিতি শনাক্ত করে। যদি টুলটি apt দিয়ে ইনস্টল না করা হয় (ম্যানুয়ালি, snap থেকে বা সোর্স থেকে), তাহলে dpkg সেটি দেখতে পায় না।

# dpkg দিয়ে যাচাই করুন: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # বাইনারির পাথ খুঁজুন: which ufw fail2ban-client auditctl # www-data থেকে sudo পরীক্ষা: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

37. সমস্যা সমাধান (500, ডেটা নেই)

500 ত্রুটি — PHP, nginx এবং মনিটরের নিজস্ব লগ পরীক্ষা করুন:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # মনিটরের লগ: tail -50 logs/monitor_$(date +%Y-%m-%d).log # ফোল্ডারের অনুমতি: ls -la data/ tmp/ logs/
হোস্টিং প্যানেলে (HestiaCP, ISPmanager, cPanel) ড্যাশবোর্ড? সেখানে PHP www-data-এর অধীনে নয়, বরং ব্যবহারকারীর অ্যাকাউন্টের অধীনে চলে (যেমন admin — সাইট ডিরেক্টরির মালিক)। সব sudo-নিয়ম ও গ্রুপ সদস্যপদ (adm, systemd-journal) এই ব্যবহারকারীর জন্য নির্ধারণ করতে হবে, অন্যথায় সার্ভিস চললেও মডিউলগুলো “নিষ্ক্রিয় / 0” দেখাবে। PHP-এর প্রকৃত ব্যবহারকারী জানতে: ps -o user= -C php-fpm | sort -u অথবা সাইট ডিরেক্টরির মালিক stat -c '%U' /path/to/monitor। এরপর নিচের সব কমান্ডে www-data-এর জায়গায় তাকে বসান। স্বয়ংক্রিয় ইনস্টলেশন ওয়েব-ব্যবহারকারীকে নিজেই শনাক্ত করে এবং তার জন্য sudoers নির্ধারণ করে।

ডেটা প্রদর্শিত হচ্ছে না — প্রায় সবসময়ই sudo-অনুমতি নির্ধারণ করা হয়নি। ওয়েব-ব্যবহারকারীর হয়ে নির্দিষ্ট কমান্ডটি পরীক্ষা করুন (www-data নিজের ব্যবহারকারী দিয়ে বদলান)। -n ফ্ল্যাগ = পাসওয়ার্ড ছাড়া, PHP-এর মতো — যদি পাসওয়ার্ড চায়, তার মানে sudoers-এ নিয়মটি নেই:

sudo -u www-data sudo -n fail2ban-client status sudo -u www-data sudo -n ufw status verbose sudo -u www-data sudo -n ipset list -t ipsum sudo -u www-data sudo -n /usr/sbin/ausearch -m USER_LOGIN -ts today sudo -u www-data sudo -n /usr/sbin/aa-status sudo -u www-data sudo -n /usr/sbin/psad --Status sudo -u www-data journalctl -u falco --no-pager -n 5
টুল চললেও মডিউল “নিষ্ক্রিয়” / “0” দেখাচ্ছে (যেমন টার্মিনালে sudo aa-status প্রোফাইল দেখায়, অথচ “AppArmor” পৃষ্ঠা “নিষ্ক্রিয়” দেখায়)। কারণ: এই মডিউলের কমান্ডটির উপর ওয়েব-ব্যবহারকারীর sudo-অনুমতি নেই। উপরের তালিকা থেকে এটি পরীক্ষা করুন: যদি পাসওয়ার্ড চায় — /etc/sudoers.d/monitor-এ অনুপস্থিত লাইনটি যোগ করুন (“sudo কনফিগারেশন”)। সাধারণ “নতুন” কমান্ড: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD)।
যদি কোনো নির্দিষ্ট পৃষ্ঠা (Falco, ModSecurity, Auditd, খোলা UFW পোর্ট) ফাঁকা থাকে — sudo সম্পর্কিত অংশের তালিকার সাথে মিলিয়ে দেখুন: সম্ভবত apache2ctl, ausearch, aa-status বা ss অনুমোদিত নয়, অথবা ওয়েব-ব্যবহারকারী adm/systemd-journal গ্রুপে নেই (সেখান থেকে fail2ban/auth/modsec লগ ও journalctl — Falco এবং কার্নেল ইভেন্ট পড়া হয়)।

38. সার্ভারে ডেটা থাকা সত্ত্বেও পেজ ফাঁকা

লক্ষণ: সার্ভারে ডেটা আছে (shell দিয়ে দেখা যায়), কিন্তু পেজে “কোনো ডেটা নেই” বা ভুল স্ট্যাটাস দেখায় — যেমন বেস তৈরি হওয়া সত্ত্বেও AIDE “ইনিশিয়ালাইজ করা হয়নি” দেখায়।

কারণ হলো open_basedir: অনেক প্যানেল ও হোস্টিং PHP-FPM পুলকে ডোমেনের ডিরেক্টরিতে সীমিত করে রাখে, তাই সিস্টেম পাথে (/var/lib/aide, /var/log, /proc…) PHP ফাংশন file_exists(), file_get_contents(), filemtime() ব্লক হয়ে যায়। মনিটর এই সমস্যা এড়াতে এমন পাথ স্ট্যান্ডার্ড সিস্টেম কমান্ড (cat, test, stat) দিয়ে পড়ে।

# shell দিয়ে ফাইলটি দেখা যায় কিনা (মনিটর এভাবেই পড়ে): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # ডোমেন পুলের জন্য open_basedir-এর বর্তমান মান: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
shell যদি ফাইলটি “দেখে” (VISIBLE) কিন্তু পেজ না দেখে — তবে এটি open_basedir। সঠিক সমাধান হলো সিস্টেম কমান্ড দিয়ে পড়া (AIDE ও নেটওয়ার্ক মনিটরের জন্য ইতিমধ্যে করা হয়েছে)। open_basedir-কে /var, /proc-এ সম্প্রসারিত করার প্রয়োজন নেই এবং তা কম নিরাপদ।

39. SSL পেজ কাজ করছে না

মনিটর ৪৪৩ পোর্টের মাধ্যমে সরাসরি ডোমেনে সংযোগ করে সার্টিফিকেট যাচাই করে। সার্ভার থেকেই যদি ডোমেন অগম্য হয় বা ফায়ারওয়াল পোর্ট বন্ধ করে রাখে — তাহলে যাচাই ব্যর্থ হবে।

# সার্টিফিকেট ম্যানুয়ালি যাচাই করুন: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # সংযোগযোগ্যতা যাচাই করুন: curl -I https://monitor.example.com
মনিটর nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) ও Apache (/etc/apache2/sites-enabled/) কনফিগ থেকে এবং HTTP_HOST-এর বর্তমান হোস্ট থেকে ডোমেনগুলো স্বয়ংক্রিয়ভাবে নেয়।
সাবডোমেন স্বয়ংক্রিয় শনাক্তকরণ। সাবডোমেনগুলো Certificate Transparency-র পাবলিক লগ থেকে স্বয়ংক্রিয়ভাবে শনাক্ত হয় এবং নেটওয়ার্কের মাধ্যমে যাচাই করা হয় — এমনকি অন্য সার্ভারে থাকলেও। ম্যানুয়ালি কিছু যোগ করার দরকার নেই।

40. কয়েকটির মধ্যে শুধু একটি ডেটাবেস দেখা যাচ্ছে

মনিটর config.php-এর ব্যবহারকারী দিয়ে MySQL-এ সংযুক্ত হয়, যার শুধু নিজের ডেটাবেসে অ্যাক্সেস আছে। MySQL information_schema-তে শুধু সেই ডেটাবেসগুলো দেখায় যেগুলোতে অধিকার আছে — তাই বাকিগুলো দেখা যায় না।

মনিটর যাতে সব ডেটাবেস দেখতে পারে, এই ব্যবহারকারীকে শুধু পড়ার অধিকার দিন (একবার root থেকে; config.php-এর ব্যবহারকারীর নাম বসান):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* শুধু পড়ার অধিকার দেয় — কিছু পরিবর্তন, মুছে ফেলা বা তৈরি করা যায় না, তাই মনিটরিংয়ের জন্য এটি নিরাপদ।
এই GRANT ছাড়া প্যানেল শুধু নিজের ডেটাবেস দেখে — এটি ভুল নয়, বরং অধিকারের সীমাবদ্ধতা। প্যানেল কোনো sudo mysql ব্যবহার করে না: ডেটাবেসের তালিকা তার নিজস্ব PDO-সংযোগের মাধ্যমে নেওয়া হয়।

41. “ডেটাবেস” পৃষ্ঠায় PostgreSQL দেখা যাচ্ছে না

PostgreSQL-এর জন্য postgres ব্যবহারকারী পর্যায়ের অ্যাক্সেস দরকার, যা প্যানেলের ওয়েব-ব্যবহারকারীর নেই। PHP থেকে বিস্তৃত sudo psql খোলা নিরাপদ নয় — এর বদলে প্যানেল প্যারামিটারবিহীন একটি সংকীর্ণ র‍্যাপার কল করে, যা শুধু সংস্করণ, সংযোগসংখ্যা এবং আকারসহ ডেটাবেসের তালিকা ছাপায়। এটি তৈরি করুন:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Monitor - read-only PostgreSQL version, connections and per-database size sudo -u postgres psql -tAc "SELECT version();" | grep -oE 'PostgreSQL [0-9.]+' echo "---" sudo -u postgres psql -tAc "SELECT count(*) FROM pg_stat_activity;" echo "---" sudo -u postgres psql -tAc "SELECT datname || '|' || pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;" EOF sudo chown root:root /usr/local/bin/monitor-pgstat sudo chmod 755 /usr/local/bin/monitor-pgstat # /etc/sudoers.d/monitor-এ (ব্যবহারকারী = যার অধীনে PHP-FPM চলে): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
PostgreSQL ব্যবহার না করলে — sudoers থেকে monitor-pgstat লাইনটি সরিয়ে দিন (ম্যানুয়াল ইনস্টলেশনের ধাপ ১৩) এবং স্ক্রিপ্টটিও তৈরি করবেন না: PostgreSQL কার্ডটি কেবল নিষ্ক্রিয় থাকবে।

42. অ্যালার্ট এসেছে — কী করবেন

প্যানেল দেখায় কী ঘটছে; নিচে দেওয়া হলো সাধারণ পরিস্থিতিতে কী করবেন। মূল নীতি: আতঙ্কিত হবেন না, বৈধ কার্যকলাপের সঙ্গে মিলিয়ে দেখুন (আপনার নিজের কাজ, আপডেট, ব্যাকআপ), এবং গুরুত্ব অনুযায়ী সাড়া দিন।

  • আক্রমণের মানচিত্র / fail2ban-এর অনেক ব্যান — ইন্টারনেটে থাকা যেকোনো সার্ভারের জন্য এটি স্বাভাবিক (বটরা নিরন্তর SSH/ওয়েব চেষ্টা করে)। মূল বিষয় হলো ব্যানগুলো কাজ করছে কিনা। নিশ্চিত করুন SSH লগইন কেবল কী দিয়ে হয় (পাসওয়ার্ড বন্ধ), এবং আপনার IP ignoreip-এ আছে।
  • ModSecurity অনুরোধ ব্লক করেছে — WAF সাইটের ওপর আক্রমণ প্রতিহত করছে, এটাই তার কাজ। যদি আপনার বৈধ ট্র্যাফিক ব্লক হয় (মিথ্যা সতর্কতা) — বিস্তারিততে rule id খুঁজুন এবং CRS কনফিগে একটি ব্যতিক্রম যোগ করুন।
  • AIDE: ফাইল পরিবর্তিত হয়েছে — তালিকাটি আপনি যা করেছেন তার সঙ্গে মিলিয়ে দেখুন (প্যাকেজ আপডেট, কনফিগ সম্পাদনা — স্বাভাবিক)। আপনি স্পর্শ করেননি এমন সিস্টেম বাইনারির পরিবর্তন সতর্ক হওয়ার কারণ। বৈধ পরিবর্তনের পর AIDE ডেটাবেস আপডেট করুন।
  • debsums: বাইনারি/লাইব্রেরি পরিবর্তিত (/etc-এর বাইরে, /usr/share-এর বাইরে) — সম্ভাব্য প্রতিস্থাপন। প্যাকেজটি যাচাই করুন: debsums PACKAGE_NAME, সন্দেহ হলে এটি পুনরায় ইনস্টল করুন (apt install --reinstall)।
  • ClamAV / maldet: হুমকি পাওয়া গেছে — কোয়ারেন্টিনে থাকা ফাইলটি পরীক্ষা করুন, এটি খুলবেন না। এটি যদি সাইট ডিরেক্টরিতে ওয়েব-শেল হয় — সার্ভার বিচ্ছিন্ন করুন এবং প্রবেশপথ খুঁজুন (দুর্বল প্লাগইন, অ্যাক্সেস ফাঁস)।
  • Falco: গুরুতর ইভেন্ট (কন্টেইনারে shell চালু, সংবেদনশীল ফাইলে অ্যাক্সেস) — ইভেন্টটি বিশ্লেষণ করুন: কার প্রসেস, কে চালু করেছে। প্রায়ই এটি বৈধ অ্যাডমিন কার্যকলাপ।
  • বাহ্যিক এক্সপোজার: লাল রঙে ডেটাবেস/ক্যাশ — অবিলম্বে বন্ধ করুন: সার্ভিসটি 127.0.0.1-এ বাঁধুন বা UFW-তে পোর্ট বন্ধ করুন। এটি একটি বাস্তব ফাঁক।
  • SSL শেষ হচ্ছে / শেষ হয়ে গেছে — সার্টিফিকেট নবায়ন করুন (Let's Encrypt নিজে নবায়ন হয়; না হলে certbot renew বা প্যানেলের সেটিংস পরীক্ষা করুন)।
  • নিরাপত্তা আপডেট অপেক্ষমাণ — ইনস্টল করুন: sudo apt update && sudo apt upgrade; কার্নেল আপডেটের পর সার্ভার রিবুট করুন।
বাস্তব হ্যাকের লক্ষণ (অজানা প্রসেস/ব্যবহারকারী, পরিবর্তিত বাইনারি, বহির্গামী স্প্যাম, অজানা cron-কাজ): সার্ভারকে বাহ্যিক অ্যাক্সেস থেকে বিচ্ছিন্ন করুন, বিশ্লেষণের জন্য একটি ব্যাকআপ নিন, এবং ডেটা গুরুত্বপূর্ণ হলে একটি বিশ্বস্ত ব্যাকআপ থেকে পরিষ্কার সার্ভার চালু করুন — রুটকিট নির্ভরযোগ্যভাবে মুছে ফেলা কঠিন।
Arcivéo - Security Monitor © 2026