এটি Arcivéo Monitor ইনস্টল, কনফিগার ও রক্ষণাবেক্ষণের নির্দেশিকা। বিভাগগুলো সাজানো হয়েছে: সাধারণ পরিচিতি, প্যানেল স্থাপন, নিরাপত্তা টুল যুক্ত করা, অন্তর্নির্মিত মডিউল এবং ডায়াগনস্টিক্স। ডান দিকের বোতাম দিয়ে কমান্ড কপি করা যায়।
প্যানেল ইনস্টলেশন আলাদা ধাপে-ধাপে পৃষ্ঠায় দেওয়া আছে। পদ্ধতি বেছে নিন:
Arcivéo Monitor — সার্ভার নিরাপত্তার ড্যাশবোর্ড। ইনস্টল করা টুল (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco প্রভৃতি) থেকে তথ্য সংগ্রহ করে এবং ড্যাশবোর্ড, অ্যাটাক ম্যাপ ও প্রতিটি টুলের বিস্তারিত পৃষ্ঠাসহ একটি একক ইন্টারফেসে সেগুলো দেখায়।
মনিটর কোনো সক্রিয় সুরক্ষা ব্যবস্থা নয় — এটি নিজে থেকে আক্রমণ ব্লক করে না। এর কাজ হলো ইতিমধ্যে চালু থাকা টুলগুলোর তথ্য একত্র করে সুবিধাজনকভাবে উপস্থাপন করা।
মনিটর শুধু লোকালি কাজ করে — যে সার্ভার মনিটর করা হচ্ছে, সেটিতেই এটি ইনস্টল করতে হবে। কোনো SSH বা রিমোট API নেই।
সব কমান্ড (fail2ban-client, ufw status, ipset list ইত্যাদি) প্যানেল ওয়েব-সার্ভার ব্যবহারকারীর নামে চালায় (সাধারণত www-data, হোস্টিং প্যানেলে — সাইটের অ্যাকাউন্ট) এবং sudo-এর সীমিত অনুমতিসহ — শুধু নির্দিষ্ট ইউটিলিটির জন্য, সম্পূর্ণ root অ্যাক্সেস ছাড়াই। ফলাফল পার্স করে ব্রাউজারে দেখানো হয়।
স্কোর সর্বোচ্চ মান থেকে শুরু হয় এবং শনাক্ত হওয়া প্রতিটি সমস্যার জন্য কমে:
PermitRootLogin yes) — −20ফলাফল: 80+ = সুরক্ষিত, 60–79 = সতর্কতা, <60 = ঝুঁকিতে।
WebAuthn — হার্ডওয়্যার কি ব্যবহার করে পাসওয়ার্ড ছাড়াই প্রমাণীকরণের একটি স্ট্যান্ডার্ড। YubiKey, Touch ID, Face ID, Windows Hello, Passkey সমর্থন করে।
পাসওয়ার্ড দিয়ে লগইনের পর সিস্টেম নিবন্ধিত কি দিয়ে নিশ্চিতকরণ চায়। পাসওয়ার্ড ফাঁস হলেও ফিজিক্যাল কি বা বায়োমেট্রিক ছাড়া লগইন করা অসম্ভব।
সেট আপ করতে পাশের মেনু থেকে WebAuthn কি খুলুন এবং “কি নিবন্ধন করুন” চাপুন। একসাথে দুটি কি নিবন্ধন করুন: একমাত্র কি হারিয়ে গেলে বা নষ্ট হয়ে গেলে সেটি দিয়ে প্যানেলে লগইন করা সম্ভব হবে না।
প্যানেল Telegram ও ইমেইলে নিরাপত্তা রিপোর্ট পাঠাতে পারে (বোতাম চেপে ও সময়সূচি অনুযায়ী)। “সেটিংস” বিভাগে কনফিগার করা যায়।
Telegram. প্রয়োজন বট টোকেন ও chat id:
@BotFather → /newbot লিখুন → 123456:ABC... ধরনের একটি টোকেন পাবেন।@userinfobot-কে লিখুন, অথবা https://api.telegram.org/bot<TOKEN>/getUpdates খুলে "chat":{"id":...} খুঁজুন।Email. “সেটিংস” → Email-এ বেছে নেওয়ার দুটি উপায়:
re_...) এবং যাচাইকৃত প্রেরক ডোমেন উল্লেখ করুন।রিপোর্টের অবস্থা: “সতর্কতা” বা “ঠিক আছে”. শিরোনাম “সতর্কতা” হয় কেবল প্রকৃত সমস্যা বা অপেক্ষমাণ অ্যাকশন থাকলে: ClamAV হুমকি শনাক্ত করেছে, AIDE-তে ফাইল পরিবর্তন, Falco-র গুরুতর ইভেন্ট (গত ২৪ ঘণ্টায় Emergency/Alert/Critical), Monit-এ পড়ে যাওয়া সার্ভিস, রিবুট দরকার, SSL মেয়াদ শেষ হচ্ছে (≤১৪ দিন) বা security-আপডেট অপেক্ষমাণ। ব্যাকগ্রাউন্ড নয়েজ — বটদের SSH ব্রুট-ফোর্স, fail2ban-এ ব্যান হওয়া IP, Suricata অ্যালার্ট, Lynis সতর্কতা এবং ইতিমধ্যে ঠেকানো ModSecurity রিকোয়েস্ট — অবস্থা বাড়ায় না, তাই এসব সংখ্যা নিজে থেকে “সতর্কতা” বোঝায় না।
বিস্তারিত মনিটরিং মডিউল (Lynis, UFW, ModSecurity, আক্রমণের মানচিত্র, AIDE, ClamAV প্রভৃতি) একটি বৈধ লাইসেন্স থাকলে চালু হয়। এটি ছাড়াও ড্যাশবোর্ড, সেটিংস ও অ্যাকাউন্ট কাজ করে, তবে মডিউলগুলো “লাইসেন্স প্রয়োজন” কার্ড দেখায়।
অ্যাকাউন্টে কেনার পর আপনার কাছে ARCIVEO-XXXX-XXXX-XXXX-XXXX রূপের একটি সক্রিয়করণ কোড থাকে। এটি আপনার প্যানেলের ডোমেনে “সক্রিয়” করতে হবে — এতে কোডটি একটি স্বাক্ষরিত লাইসেন্স ফাইলে ([license] ব্লক) পরিণত হয়, যা আপনি প্যানেলে বসিয়ে দেন।
কীভাবে সক্রিয় করবেন (৩ ধাপ):
my.arciveo.com → “লাইসেন্স” / “লাইসেন্স সক্রিয়করণ” বিভাগ — ARCIVEO-… কোডটি কপি করুন।monitor.example.com)। সক্রিয় করুন বোতামে ক্লিক করুন — সিস্টেম সেই ডোমেনে বাঁধা একটি লাইসেন্স ফাইল তৈরি করবে এবং “কপি” বোতামসহ একটি ঘরে তা দেখাবে।প্যানেল কী-টি ক্রিপ্টোগ্রাফিকভাবে যাচাই করে: স্বাক্ষর, ডোমেন-বাঁধন ও মেয়াদ।
config.php-এর APP_URL কনস্ট্যান্ট থেকে নিন এবং শুধু হোস্টের নাম দিন — https:// ছাড়া এবং www প্রিফিক্স ছাড়া। সক্রিয়করণ একবারই: কোডটি প্রদত্ত ডোমেনের জন্য লাইসেন্সে পরিণত হয় এবং পুনরায় সক্রিয় হয় না — ডোমেনে ভুল হলে কী আপনার প্যানেলে চলবে না, আর কোডটিও খরচ হয়ে যাবে। তাই ডোমেন সাবধানে দিন।
প্যানেলের সব মূল প্যারামিটার একটিমাত্র config.php ফাইলে রুটে (public/ ফোল্ডারের পাশে) সাধারণ define() ধ্রুবক হিসেবে দেওয়া থাকে। ফাইলটি ইনস্টলের সময় তৈরি হয়; হাতে সম্পাদনার দরকার খুব কমই পড়ে — মূলত ডোমেন বদলানো, স্থানান্তর বা অন্য ডেটাবেসে সংযোগের সময়। যেকোনো সম্পাদনার পর PHP-FPM পুনরায় চালু করুন (নয়তো OPcache-এর কারণে পরিবর্তন প্রয়োগ হবে না)।
হাইলাইট করা জায়গায় নিজের মান বসান; বাকিটা যেমন আছে রেখে দিন:
ডেটাবেস। MySQL/MariaDB-তে সংযোগের তথ্য:
DB_HOST — DBMS হোস্ট, প্রায় সবসময় localhost;DB_NAME — প্যানেলের ডেটাবেসের নাম;DB_USER — ডেটাবেস ব্যবহারকারী (শুধু নিজের ডেটাবেসে অ্যাক্সেস);DB_PASS — এই ব্যবহারকারীর পাসওয়ার্ড;DB_CHARSET — সংযোগের এনকোডিং, utf8mb4 রেখে দিন।অ্যাপ্লিকেশন।
APP_URL — প্যানেলের পূর্ণ ঠিকানা (যেমন https://monitor.example.com)। যে ডোমেনে লাইসেন্স সক্রিয় করা হয়েছে তার সঙ্গে মিলতে হবে — নয়তো কী প্রত্যাখ্যাত হবে (দেখুন “লাইসেন্স” বিভাগ);TIMEZONE — PHP-এর টাইম জোন: শুধু প্যানেল কীভাবে তারিখ ও সময় দেখায় তার উপর প্রভাব ফেলে। cron কাজ চালানোর সময়ের উপর প্রভাব ফেলে না — সেখানে সিস্টেমের জোন কার্যকর থাকে (দেখুন “সব cron কাজ”)।সেশনের সময়। SESSION_LIFETIME — সেশনের নিষ্ক্রিয়তার টাইমআউট সেকেন্ডে (চলমান: সক্রিয়তায় নবায়ন হয়)। ডিফল্ট 28800 = ৮ ঘণ্টা; এতটা সময় নিষ্ক্রিয় থাকার পর প্যানেল আবার লগইন করতে বলবে। যেমন, 3600 = ১ ঘণ্টা, 86400 = এক দিন।
ত্রুটি লগিং। ত্রুটি কখনও দর্শকদের দেখানো হয় না, বরং logs/php_errors.log-এ লেখা হয় — সেগুলো “অ্যাপ্লিকেশন লগ” পৃষ্ঠায় দেখা যায়। এই লাইনগুলো (display_errors=0, log_errors=1, error_log পথ) সাধারণত বদলানোর দরকার নেই — সেটিংস সরাসরি ফাইলেই দেওয়া আছে এবং php.ini-র উপর নির্ভর করে না।
public/-এর পাশে), আর এই প্যানেলের ওয়েব-রুট (DocumentRoot) — ঠিক প্যানেলের রুটই, public/ নয়। ফাইলটি নিজে থেকে “ফাঁস” হয় না: রুটের .htaccess-এ এর জন্য স্পষ্ট নিষেধ (Require all denied) আছে — সার্ভার 403 ফেরত দেয়। এই নিয়ম ছাড়াও সোর্স ফাঁস হতো না: এটি PHP — সার্ভার এটি চালায়, টেক্সট হিসেবে দেয় না। যেকোনো ক্ষেত্রে: এটি পাবলিক রিপোজিটরিতে রাখবেন না এবং প্রকৃত পাসওয়ার্ডসহ সাপোর্টে পাঠাবেন না। ফাইলের অনুমতি — 640।
UFW (Uncomplicated Firewall) — nftables/iptables-এর একটি সহজ ইন্টারফেস। স্পষ্টভাবে অনুমোদিত পোর্ট ছাড়া সব ইনকামিং পোর্ট বন্ধ করে দেয়। “UFW ফায়ারওয়াল” পৃষ্ঠাটি স্ট্যাটাস ও নিয়মগুলো দেখায়।
ufw enable-এর আগে অবশ্যই SSH অনুমোদন করুন (ufw allow OpenSSH), নাহলে সার্ভারে অ্যাক্সেস হারাবেন।
deny নিয়মে বন্ধ করা পোর্ট বাইরে থেকে অ্যাক্সেসযোগ্য হিসেবে গণ্য হয় না।
Skipping adding existing rule — এটি কোনো ত্রুটি নয়। UFW এভাবে জানায় যে ঠিক এমন একটি নিয়ম ইতিমধ্যেই আছে এবং তা পুনরায় যোগ করে না। স্বয়ংক্রিয় কনফিগারেশন আবার চালালে (এটি ইডেমপোটেন্ট) এটি একটি স্বাভাবিক বার্তা — কিছু করার দরকার নেই।
ব্যর্থ লগইন চেষ্টার সংখ্যা সীমা ছাড়ালে স্বয়ংক্রিয়ভাবে IP ব্লক করে। SSH, nginx, Apache ও অন্যান্য সার্ভিসের লগ বিশ্লেষণ করে।
মৌলিক ইনস্টলেশন উপরে দেওয়া আছে। এখানে রয়েছে কার্যকর কনফিগারেশন, যা কয়েক ডজন সক্রিয় jail এবং হাজার হাজার ব্লক তৈরি করে: সাধারণ সেটিংস, মূল jail এবং ipsum তালিকা থেকে ক্ষতিকর IP-র স্বয়ংক্রিয় ব্যান।
/etc/fail2ban/jail.local ফাইল — সাধারণ সেটিংস ও সবচেয়ে গুরুত্বপূর্ণ jail:
ignoreip-এ অবশ্যই আপনার নিজের IP ও বিশ্বস্ত নেটওয়ার্ক লিখুন, নইলে নিজেকেই ব্যান করে ফেলতে পারেন। সম্পাদনার পর: sudo fail2ban-client reload।
ipsum ব্লক-লিস্টের স্বয়ংক্রিয় লোডিং — root-cron-এ (sudo crontab -e): level 1 (১ লক্ষাধিক IP) ipsum সেটে লোড হয়, যা ফায়ারওয়ালে কেটে দেওয়া হয় (বিস্তারিত — “IPset ব্লক-লিস্ট” অংশে):
ipsum হতে হবে — ঠিক এটিই ড্যাশবোর্ড পড়ে (“IPset ipsum” কার্ড)। লেভেল: levels/1.txt — সর্বোচ্চ কভারেজ, levels/3.txt — আরও নির্ভুল (৩+ উৎস)।
“নিরাপত্তা মনিটর” কেন দুটি জোনে বিভক্ত। সুরক্ষা দুটি স্তরে কাজ করে, আর ড্যাশবোর্ড এদের মেশায় না:
sshd, apache-*, nginx-* ইত্যাদি jail) এবং দুর্দান্ত পুনরাবৃত্তিকারী (recidive jail — যারা ইতিমধ্যে কয়েকবার ব্যান হয়েছে)। এগুলো এমন IP যারা সত্যিই আপনার কাছে ঢোকার চেষ্টা করেছিল — এরা আক্রমণ মানচিত্র ও “টাইমলাইনে” থাকে।ipset ipsum, যা ফায়ারওয়ালে DROP নিয়ম দিয়ে কেটে দেওয়া হয়। এই ঠিকানাগুলোর বেশিরভাগই আপনার সার্ভার স্পর্শও করেনি — এদের আগেভাগে কেটে দেওয়া হয়; “IPset ipsum” কাউন্টার দেখায় কতগুলো প্রতিরোধমূলকভাবে কাটা হয়েছে।পার্থক্যটা সহজ: প্রতিক্রিয়ামূলক — “এরা আক্রমণ করেছে এবং ব্যান খেয়েছে”, প্রতিরোধমূলক — “এদের চেষ্টা করার আগেই ব্লক করা হয়েছে”। আগে recidive-এ কৃত্রিমভাবে ipsum list-3 ঢোকানো হতো (এখান থেকেই পুরনো বিভাজন “তালিকাভিত্তিক recidive”); এখন recidive-এ কেবল প্রকৃত পুনরাবৃত্তিকারীরা, আর প্রতিরোধমূলক অংশ পুরোপুরি ফায়ারওয়ালে।
ipsum — ক্ষতিকর IP-এর একটি পাবলিক তালিকা, প্রতিদিন আপডেট হয়। মনিটর ড্যাশবোর্ড ও অ্যাটাক ম্যাপে লোড হওয়া ঠিকানার সংখ্যা দেখায় এবং তা নিরাপত্তা স্কোরে হিসাব করে (সেট লোড না থাকলে −10)।
fail2ban ছাড়া সবচেয়ে সরল বিকল্প — iptables দিয়ে ব্লক করে এমন একটি আলাদা ipsum সেট:
@reboot-এ যুক্ত করুন। পাশাপাশি create … -exist কমান্ড maxelem 300000 সীমা নির্ধারণ করে (ডিফল্ট 65536 — level 1 আঁটে না, “Hash is full” দেখাবে):
ipsum সেটে লোড করে, এবং ফায়ারওয়াল যদি ইনস্টলার পরিচালনা করে (নতুন VPS — “পূর্ণ”/“লাইট” প্রোফাইল), তবে DROP নিয়মে সেটটি UFW-তে সংযুক্ত করে — এই IP থেকে ট্রাফিক সত্যিই ব্লক হয়। নিয়মটি ESTABLISHED,RELATED-এর পরে থাকে, তাই বর্তমান সংযোগগুলো (আপনার SSH সহ) বিচ্ছিন্ন হয় না — শুধু তালিকার নতুন সংযোগ কাটা পড়ে। সেটটি ipsum-load.service সার্ভিস লোড হওয়ার সময় ফায়ারওয়ালের আগে পুনরুদ্ধার হয় (নইলে UFW উঠত না), এবং 04:00-এর ক্রনে আপডেট হয়। ইতিমধ্যে কনফিগার করা সার্ভারে (প্যানেল, নিজের ফায়ারওয়াল) ইনস্টলার ফায়ারওয়ালে হাত দেয় না — সেখানে ipsum ড্যাশবোর্ড ও অ্যাটাক ম্যাপের তালিকা হিসেবেই থাকে, আর DROP নিয়ম চাইলে ম্যানুয়ালি যোগ করা যায় (iptables … --match-set ipsum … -j DROP সহ সরল বিকল্প — উপরে)। অটোইনস্টলে ম্যানুয়ালি কিছু করার দরকার নেই।
যৌথ threat intelligence সহ Fail2ban-এর আধুনিক বিকল্প: কমিউনিটির ব্লক এবং নিজস্ব নিয়ম। ফায়ারওয়ালে ব্লক প্রয়োগ করতে আলাদা bouncer প্রয়োজন।
systemctl is-active crowdsec দিয়ে যাচাই করে)। চালু করুন: sudo systemctl enable --now crowdsec; ক্র্যাশ করলে দেখুন sudo journalctl -u crowdsec -n 30। “চালু নেই” স্ট্যাটাসের যেকোনো সার্ভিসের (Suricata, Falco, Monit, MySQL) জন্য একই নিয়ম।
stream halted / ব্লক প্রয়োগ হচ্ছে না। এটি একটি অনাথ api-কী: bouncer cscli bouncers list থেকে মুছে গেছে, কিন্তু তার পুরনো কী /etc/crowdsec/bouncers/*.yaml-এ রয়ে গেছে। bouncer পুনরায় নিবন্ধন করুন এবং নতুন কী লিখুন:
AIDE (Advanced Intrusion Detection Environment) ফাইল সিস্টেমের একটি স্ন্যাপশট তৈরি করে এবং প্রতিটি পরীক্ষার সময় /etc, /bin, /usr-এর পরিবর্তনগুলো জানায়। ইনস্টলেশনের পরে ডেটাবেস ইনিশিয়ালাইজ (aideinit) করা অবশ্যই প্রয়োজন।
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 কনফিগ-স্নিপেটের একটি পরিচিত বাগ। ডেটাবেস তৈরি হয় না। ভাঙা স্নিপেটটি সরিয়ে আবার চেষ্টা করুন:
aideinit চালানো হয়নি, নয়তো (Ubuntu 24.04) /var/lib/aide ডিরেক্টরি 700 মোডে তৈরি হয়েছে ও www-data-এর কাছে অগম্য — sudo chmod 755 /var/lib/aide দিয়ে সমাধান হয় (উপরের ব্লক দেখুন)। “কোনো পরীক্ষা হয়নি” = ডেটাবেস আছে, কিন্তু এখনও পরীক্ষা চালানো হয়নি — এটি কোনো ত্রুটি নয়। মনিটর ফলাফল /var/log/aide/aide.log থেকে পড়ে।
/etc/cron.daily/aide হয়তো প্রয়োজনীয় ফরম্যাটে /var/log/aide/aide.log নাও লিখতে পারে (এবং তাতে aide.wrapper-ও আর নেই)। স্পষ্ট --config সহ নিজস্ব ক্রন যোগ করা বেশি নির্ভরযোগ্য — এটি root থেকে 644 মোডে লগ লেখে, আর মনিটর অতিরিক্ত গ্রুপ ছাড়াই তা পড়ে:
chmod 755 /var/lib/aide এবং 02:00-এ পরীক্ষার ক্রন — হাতে কিছুই করার দরকার নেই।
sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db।
Linux-এর জন্য অ্যান্টিভাইরাস স্ক্যানার। PHP-শেল ও ক্ষতিকর কোড আছে কিনা /var/www যাচাই করতে বিশেষভাবে কার্যকর।
enable --now-এর পরেও clamd ডেমন “নিষ্ক্রিয়” দেখাচ্ছে? তিনটি সাধারণ কারণ:
1. কনফিগে Example লাইনটি রয়ে গেছে — এটি থাকা অবস্থায় clamd চালু হতে অস্বীকার করে:
2. সিগনেচার ডেটাবেস ডাউনলোড হয়নি — এটি ছাড়া clamd চালু হয় না:
3. কেবল লোড হচ্ছে — clamd ~৮০ লক্ষ সিগনেচার মেমরিতে লোড করতে ৩০–৬০ সেকেন্ড নেয়। অপেক্ষা করে যাচাই করুন: systemctl is-active clamav-daemon (activating স্ট্যাটাস → এখনও লোড হচ্ছে)।
sudo journalctl -u clamav-daemon -n 30 --no-pager।
clamd ডেমন শুধু সিগনেচার মেমরিতে ধরে রাখে, নিজে থেকে সময়সূচি অনুযায়ী কিছু স্ক্যান করে না। প্যানেল নির্ধারিত স্ক্যানের ফলাফল দেখায়, তাই এমন একটি ক্রন দরকার যা স্ক্যান করে ও লগ লেখে। স্বয়ংক্রিয় ইনস্টলেশন /usr/local/bin/clamav-scan.sh র্যাপার এবং 01:30-এ একটি ক্রন বসায় — প্রথম রানের পর “ফাইল যাচাই” ও “শেষ স্ক্যান” পূরণ হবে। সময়সূচির অপেক্ষা না করে এখনই চালাতে: sudo /usr/local/bin/clamav-scan.sh।
Linux Malware Detect (LMD) — ওয়েব হুমকির জন্য ম্যালওয়্যার স্ক্যানার: PHP-শেল, ওয়েব-ব্যাকডোর, লোডার। এটি ClamAV ইঞ্জিন ব্যবহার করে এবং নিজস্ব সিগনেচার দিয়ে তা পরিপূরক করে।
maldet --report।
update-rc.d: error: unable to read /etc/init.d/maldet লাইনটি দেখা যেতে পারে — এটি ক্ষতিকর নয়। maldet init.d ব্যবহার করে না, সিগনেচার আপডেট ও স্ক্যান /etc/cron.daily/maldet এর মাধ্যমে চলে। নিচে installation completed দেখা গেলে — সবকিছু ইনস্টল হয়ে গেছে।
apt দিয়ে নয়, বরং /usr/local/maldetect-এ ইনস্টল হয়, এবং open_basedir চালু থাকলে এর উপস্থিতি shell-এর মাধ্যমে যাচাই করা হয় — দেখুন “পেজ ফাঁকা, যদিও সার্ভারে ডেটা আছে” অংশটি।
নেটওয়ার্ক অনুপ্রবেশ শনাক্তকরণ সিস্টেম: প্যাকেট স্তরে ট্রাফিক বিশ্লেষণ করে এবং হাজার হাজার আক্রমণের সিগনেচার চেনে। ModSecurity-কে পরিপূরক করে (সেটি HTTP স্তরে কাজ করে, Suricata — TCP/IP স্তরে)।
/var/log/suricata/eve.json ফাইলটি root হিসেবে লেখে এবং ডিরেক্টরিতে 750 মোড থাকায় ওয়েব-সার্ভার (www-data) সেটি পড়তে পারে না। ডিরেক্টরিটি পাস-থ্রুয়ের জন্য খুলুন — ভেতরের ফাইলগুলো সুরক্ষিত থাকে:
eBPF/kernel module-এর মাধ্যমে সিস্টেম কল ইন্টারসেপ্ট করে এবং রিয়েল-টাইমে অস্বাভাবিকতা শনাক্ত করে: nginx থেকে shell, ওয়েব প্রসেস দিয়ে /etc/passwd পড়া, /bin-এ লেখা ইত্যাদি।
journalctl -u falco দিয়ে পড়ে (sudo ছাড়া — systemd-journal গ্রুপের মাধ্যমে)। www-data এই গ্রুপে আছে কিনা নিশ্চিত করুন — দেখুন ম্যানুয়াল ইনস্টলেশন পৃষ্ঠায় “sudo সেটআপ” (পয়েন্ট ২)।
/etc/passwd পড়া, সিস্টেম ডিরেক্টরিতে লেখা) ইভেন্ট লেখে। শান্ত সার্ভারে দিনে শূন্য ক্রিটিক্যাল — একটি সুস্থ অবস্থা।
journalctl দিয়ে পড়তে জার্নালে অনুমতি লাগে; ড্যাশবোর্ড যাতে স্থিরভাবে ইভেন্ট দেখে, তার জন্য অটো-ইনস্টল Falco-তে file_output → /var/log/falco/falco.log চালু করে এবং সার্ভিসে UMask=0022 সেট করে (লগ ওয়েব-সার্ভার পড়তে পারে)। নতুন ইনস্টলেশনে এটি হাতে কনফিগার করার দরকার নেই।
ModSecurity — Apache বা Nginx-এর জন্য ওয়েব ফায়ারওয়াল (WAF)। অ্যাপ্লিকেশন স্তরের আক্রমণ ব্লক করে: SQL ইনজেকশন, XSS, পাথ ট্রাভার্সাল, স্ক্যানার।
IncludeOptional /etc/modsecurity/*.conf লাইন দিয়ে কনফিগ যুক্ত করে, কিন্তু প্যাকেজ শুধু modsecurity.conf-recommended রাখে — যা *.conf মাস্কের আওতায় পড়ে না। এটি modsecurity.conf-এ কপি না করলে SecRuleEngine Off থেকে যায়: মডিউল লোড হয়, CRS রুল লোড হয়, কিন্তু ট্রাফিক পরীক্ষা হয় না এবং অডিট লগ তৈরি হয় না। মধ্যবর্তী মোড DetectionOnly শুধু লগে ইভেন্ট লেখে, অনুরোধ ব্লক করে না — প্যানেল একে হলুদ রঙে দেখায়।
অডিট লগে প্যানেলের অ্যাক্সেস। /var/log/apache2/modsec_audit.log লগটি root-এর মালিকানাধীন (অনুমতি 640), ওয়েব-ব্যবহারকারী এটি পড়তে পারে না। প্যানেল একটি র্যাপার দিয়ে ডেটা নেয় — এটি তৈরি করুন:
SecRuleEngine নির্দেশনা নেয়: ইন্ডেন্টযুক্ত লাইনগুলো <LocationMatch>/<Directory> ব্লকের ভেতরে থাকে (যেমন, phpMyAdmin-এর জন্য WAF বন্ধ করা) এবং গ্লোবাল মোড নির্ধারণ করে না।www-data, HestiaCP-তে সাইটের পুল সাইটের মালিকের অধীনে চলে (যেমন, admin) — grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf দিয়ে যাচাই করুন।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 কমান্ড দিয়ে প্রকৃত পাথ খুঁজে বের করে তালিকায় বসান। র্যাপার পুরনো হলে (এই সেকশন ছাড়া) — বিভাগটি শুধু “অনুপলব্ধ” সতর্কতা দেখাবে, বাকি পৃষ্ঠা আগের মতোই কাজ করবে।
Auditd (Linux Audit Daemon) কার্নেল স্তরে সিস্টেম কল রেকর্ড করে: লগইন ও লগআউট, sudo কমান্ড, ব্যর্থ প্রমাণীকরণ প্রচেষ্টা, ফাইল পরিবর্তন। মনিটর আজকের লগইন, ব্যর্থ প্রচেষ্টা এবং sudo কমান্ড দেখায়।
ausearch (/usr/sbin/ausearch) এর মাধ্যমে এবং প্রয়োজনে /var/log/audit/audit.log থেকে tail কমান্ড দিয়ে ইভেন্ট পড়ে। উভয়ই sudoers-এ থাকতে হবে।
সার্ভিসগুলো (nginx, php-fpm, mysql ইত্যাদি) পর্যবেক্ষণ করে এবং বন্ধ হয়ে গেলে পুনরায় চালু করে। ইমেইলে অ্যালার্ট পাঠাতে পারে।
monit status এর মাধ্যমে সার্ভিসের তালিকা পায়। /etc/monit/monitrc ফাইলে HTTP ইন্টারফেস চালু থাকতে হবে (allow localhost সহ set httpd ব্লক), নাহলে monit status ত্রুটি ফেরত দেবে।
monitrc-এ set httpd লাইনটি কমেন্ট করা আছে (ডিফল্টভাবে # set httpd port 2812 … হিসেবে থাকে)। ব্লকটি আনকমেন্ট করুন এবং localhost অনুমোদন করুন। (২) শুধু httpd চালু থাকলে তা কিছুই পর্যবেক্ষণ করে না — Monit কেবল check-স্ট্যানজায় বর্ণিত জিনিসই গণনা করে; সেগুলো ছাড়া ইন্টারফেস চালু থাকলেও তালিকা খালি থাকে। ন্যূনতম কার্যকর কনফিগ:
conf.d রেখে দেয় — নতুন ইনস্টলেশনে হাতে কনফিগার করার দরকার নেই।
PSAD iptables লগ বিশ্লেষণ করে পোর্ট স্ক্যানিং ও নেটওয়ার্ক আক্রমণ শনাক্ত করে এবং প্রতিটি উৎসকে হুমকির মাত্রা (১–৫) নির্ধারণ করে। এটি fail2ban ও Suricata-কে সম্পূর্ণ করে।
psad --Status দিয়ে ডেটা পড়ে (sudoers-এ থাকা দরকার)। iptables লগিং ছাড়া পৃষ্ঠাটি ফাঁকা থাকবে — কোনো স্ক্যান না হওয়া পর্যন্ত এটি স্বাভাবিক।
Mandatory Access Control নিয়ন্ত্রণ করে কোনও প্রোগ্রাম কোন কোন ফাইল ও রিসোর্সে অ্যাক্সেস করতে পারবে, এমনকি প্রোগ্রামটি হ্যাক হলেও। Ubuntu/Debian-এ ডিফল্টভাবে AppArmor ব্যবহৃত হয় (সাধারণত ইতিমধ্যে ইনস্টল করা ও সক্রিয়)।
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)-এ এই মোড নেই আর সংখ্যাগুলো সবসময় মিলে যায়।
unconfined রেখেছে সেগুলো enforce মোডে আনা কেবল বুঝেশুনেই উচিত: এগুলো ভুলবশত বন্ধ নয়, বরং এভাবে না করলে প্রোগ্রামগুলোর কাজই ভেঙে পড়ে। complain মোডের প্রোফাইল ভিন্ন ব্যাপার: সেখানে নিয়মগুলো ইতিমধ্যে লেখা আছে, কেবল প্রয়োগ হয় না।
debsums যাচাই করে যে ইনস্টল করা প্যাকেজের ফাইলগুলো রিপোজিটরির চেকসামের সাথে মেলে কিনা — বদলে ফেলা সিস্টেম বাইনারি শনাক্ত করে (AIDE-এর পরিপূরক)। পূর্ণ যাচাইয়ে ১–২ মিনিট লাগে, তাই এটি cron দিয়ে চলে, আর প্যানেল ফলাফল data/debsums/debsums.log থেকে পড়ে নিজেই বিভাগে সাজিয়ে নেয় (শুধু বাইনারি ও লাইব্রেরিই গুরুত্বপূর্ণ)।
কাজটি root-cron-এ যোগ হয় (sudo crontab -e)। প্রস্তুত র্যাপার debsums-scan.sh রাখা হয় /usr/local/bin/-এ (chmod +x; cron-কাজের সারসংক্ষেপ দেখুন) এবং নিজেই প্যানেলের data/debsums/-এ রিপোর্ট লেখে।
র্যাপার debsums-scan.sh নিজেই প্যানেলের data/ খুঁজে নেয় — পথ লেখার দরকার নেই।
/etc/ (কনফিগ) ও /usr/share/ (রিসোর্স)-এর পরিবর্তন সাধারণত স্বাভাবিক — প্যানেল সেগুলো আলাদা রঙে চিহ্নিত করে। বাইনারি ও লাইব্রেরির পরিবর্তনই উদ্বেগজনক (/bin, /sbin, /usr/lib ইত্যাদি) — “বাইনারি / লাইব্রেরি” কার্ডটি ঠিক সেগুলোই দেখায়।
Lynis ম্যানুয়ালি বা cron দিয়ে চালানো হয়। রিপোর্টটি প্রকল্পের data/lynis/ ফোল্ডারে সংরক্ষিত হতে হবে — মনিটর lynis-report.dat ফাইলটি পড়ে।
lynis-scan.sh চালায় (cron-এর অপেক্ষা না করে): “স্ক্যান করা হচ্ছে…” দেখায় এবং শেষ হলে নিজেই রিপোর্ট আপডেট করে। এর জন্য ওয়েব-ব্যবহারকারীর স্ক্রিপ্ট চালানোর একটি sudoers লাইন দরকার — ইনস্টলার এটি /etc/sudoers.d/monitor-এ স্বয়ংক্রিয়ভাবে যোগ করে। প্যানেলটি ম্যানুয়ালি/আগে বসানো হলে, ফাইলে ইতিমধ্যে উল্লিখিত সেই একই ব্যবহারকারী দিয়ে এটি যোগ করুন:
Logwatch-কে প্রতিদিনের রিপোর্ট প্রকল্পের data/logwatch/ ফোল্ডারে .txt ফরম্যাটে সংরক্ষণ করতে হবে। মনিটর সর্বশেষ রিপোর্ট ও আর্কাইভ দেখায়।
নেটওয়ার্ক মনিটরে ইনস্টলেশন লাগে না — এটি ড্যাশবোর্ডের একটি অন্তর্নির্মিত পৃষ্ঠা। এটি স্থানীয় উৎস থেকে সার্ভারের নেটওয়ার্ক অবস্থা দেখায়:
/proc/net/dev থেকে;ip দিয়ে;ss দিয়ে;journalctl -k দিয়ে।প্রথম তিনটি উৎস sudo ছাড়াই কাজ করে, তাই ইন্টারফেস, ট্রাফিক, সংযোগ ও পোর্ট সঙ্গে সঙ্গেই দেখা যায়। “কার্নেল ইভেন্ট” ব্লকটি journalctl -k ব্যবহার করে — এটি systemd-journal গ্রুপের মাধ্যমে পড়া হয় (“sudo কনফিগারেশন”, ধাপ ২), sudo লাগে না। ওয়েব-ব্যবহারকারীর কাছে সবকিছু অ্যাক্সেসযোগ্য কিনা যাচাই করুন:
UFW BLOCK এন্ট্রি এখানে আসে না — সেগুলি “UFW ফায়ারওয়াল” ও “অ্যাটাক ম্যাপ” পৃষ্ঠায় থাকে। সবুজ টিকসহ খালি ব্লক = গত ২৪ ঘণ্টায় কোনো নেটওয়ার্ক সমস্যা হয়নি।
বিল্ট-ইন পৃষ্ঠাটি তিনটি জিনিস দেখায়:
df); ≥৯০% হলে বার লাল হয়ে যায়;lsblk), শুধু বাস্তবগুলো (loop/snap লুকানো);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/-এ লেখে।
র্যাপার smart-scan.sh নিজেই ড্যাশবোর্ডের data/ খুঁজে নেয় — পাথ লেখার দরকার নেই। ভেতরে lsblk -e7,11 loop/cdrom বাদ দেয়।
এই পৃষ্ঠাটি গত ২৪ ঘণ্টার সার্ভার লোডের ইতিহাস দেখায় — 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 অধিকার ছাড়াই পড়া হয়। ২৪ ঘণ্টার চেয়ে পুরনো পয়েন্ট প্রতিটি লেখার সময় স্বয়ংক্রিয়ভাবে মুছে যায়।
র্যাপার collect-metrics-all.sh (cron-কাজের সারসংক্ষেপ দেখুন) নিজেই সার্ভারে ইনস্টল করা সমস্ত প্যানেল ইনস্ট্যান্স খুঁজে বের করে এবং প্রতিটির cron/collect_metrics.php সাইটের মালিকের নামে চালায়।
লোড সংক্রান্ত সতর্কতা (“সেটিংস” → “লোড সংক্রান্ত সতর্কতা” বিভাগ) — CPU/RAM/ডিস্ক/inodes-এর সীমা ছাড়িয়ে গেলে প্যানেল Telegram/Email-এ বিজ্ঞপ্তি পাঠায় (দৈনিক রিপোর্টের মতোই একই চ্যানেল — অ্যালার্টের জন্য আলাদাভাবে চালু করার দরকার নেই), এবং মেট্রিক স্বাভাবিকে ফিরলে আরও একটি। সীমা ধরে রাখার সময় বারবার স্প্যাম করে না: পরের বিজ্ঞপ্তি কেবল “স্বাভাবিক হলো → আবার ছাড়িয়ে গেল” চক্রের পরেই আসবে।
collect_metrics.php পরীক্ষা করে — আলাদা cron লাগে না। “ইতিমধ্যে বিজ্ঞপ্তি পাঠানো হয়েছে / এখনও নয়” অবস্থা data/alerts_state.json-এ সংরক্ষিত থাকে, আর সীমা প্যানেলের সেটিংসে।
“আক্রমণের মানচিত্র” পৃষ্ঠাটি geoiplookup কমান্ড দিয়ে IP থেকে দেশ শনাক্ত করে। GeoIP প্যাকেজ ছাড়া দেশ শনাক্ত হবে না এবং মানচিত্রে বিন্দু দেখা যাবে না:
/usr/share/GeoIP/GeoIP.dat ডেটাবেস সবাই পড়তে পারে, ফলাফল tmp/geoip_cache.json-এ ক্যাশ হয়। মানচিত্রটি নিজে (Leaflet + OpenStreetMap টাইল) ব্রাউজারে লোড হয় — যে কম্পিউটারে ড্যাশবোর্ড খোলা, সেখানে ইন্টারনেট প্রয়োজন।
ড্যাশবোর্ডের দুটি অন্তর্নির্মিত কার্ড, যা কোনো টুলের “চালু/বন্ধ” নয়, বরং সার্ভারের প্রকৃত সুরক্ষা দেখায়। এগুলোর ইনস্টল লাগে না, sudo ছাড়াই স্থানীয়ভাবে পড়া যায়।
বাহ্যিক এক্সপোজার — কতগুলো সার্ভিস সব ইন্টারফেস (0.0.0.0/[::]) শোনে এবং বাইরে থেকে অ্যাক্সেসযোগ্য। বাইরের দিকে যদি DBMS বা ক্যাশ (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) উন্মুক্ত থাকে তবে লাল রঙে দেখায় — এটি সরাসরি ফাঁক (নিরাপত্তা স্কোরে −10)। উৎস: ss -tuln।
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-সার্ভিস সেখানে ধরা পড়ে না।
/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। বিস্তারিত তালিকা — “নিরাপত্তা আপডেট” পৃষ্ঠায়।
update-notifier-common)। apt-check না থাকলে — মনিটর apt-get -s upgrade দিয়ে প্যাচ গণনা করে।
স্বয়ংক্রিয় নিরাপত্তা আপডেট (unattended-upgrades) — “নিরাপত্তা আপডেট” পৃষ্ঠায় একটি আলাদা কার্ড দেখায় যে security-প্যাচের স্বয়ংক্রিয় ইনস্টল চালু আছে কিনা এবং সর্বশেষ কখন তা চলেছে। sudo লাগে না — স্ট্যাটাস apt-config dump দিয়ে পড়া হয়।
ব্যাকআপই প্রধান বিমা: ডেটা হারানো যেকোনো হ্যাকের চেয়ে ভয়ংকর। দুটি জিনিস দরকার — সার্ভার/সাইটের ব্যাকআপ এবং আলাদাভাবে প্যানেলের ডেটাবেসের ব্যাকআপ (সেখানে ব্যবহারকারী, WebAuthn কী, সেটিংস, লাইসেন্স থাকে)।
বিকল্প A — HestiaCP: ব্যবহারকারীর Backup ট্যাব → ব্যাকআপ তৈরির বোতাম (বা সার্ভার সেটিংসে সময়সূচী অনুযায়ী)। ব্যাকআপে সাইট ও তাদের ডেটাবেস অন্তর্ভুক্ত থাকে।
বিকল্প B — ম্যানুয়ালি (cron): ডেটাবেস ডাম্প + প্যানেলের data/ ডিরেক্টরির আর্কাইভ:
নতুন সংস্করণে আপডেট। প্রথমে ব্যাকআপ নিন। এরপর নিজের ডেটা রেখে কোড ফাইলগুলো পুনরায় আপলোড করুন:
public/, includes/, assets/, cron/, database/, এবং রুট-এর .htaccess (ফ্রন্ট-কন্ট্রোলার — রাউটিং পুরনো সংস্করণের রাখা যাবে না), manifest.json, sw.js;config.php (ডেটাবেস তথ্য), data/ (রিপোর্ট), logs/, tmp/ (সেশন ও ক্যাশ)।SSH_FX_PERMISSION_DENIED — Permission denied। প্যানেলের ফাইলগুলো www-data-এর মালিকানাধীন (ইনস্টলেশনের সময় এভাবেই সেট করা হয়েছিল), আর SFTP ক্লায়েন্ট সংযোগ করে আপনার নিজের ব্যবহারকারী দিয়ে, যার লেখার অনুমতি নেই। “চালু হোক” ভেবে পুরো প্যানেল www-data-কে দিয়ে দেওয়াই ঠিক এই ত্রুটির কারণ; নিচে তিনটি পদ্ধতি, যেকোনোটিই সমস্যা সমাধান করে।
data/ (রিপোর্ট), tmp/ (সেশন ও ক্যাশ), logs/; সেগুলো www-data-এর অধীনেই থাকে। বাকিটা কোড, আর ওয়েব সার্ভারের কেবল পড়ার প্রয়োজন, যা 644 অনুমতিসহ www-data গ্রুপ দিয়ে থাকে। বাড়তি সুবিধা: PHP-তে দুর্বলতা থাকলেও প্যানেলের ফাইল আর বদলানো যায় না। হোস্টিং প্যানেলে (HestiaCP ও সমজাতীয়) বিকল্প A প্রয়োজন নেই: সেখানে সাইটের ফাইল এমনিতেই সেই অ্যাকাউন্টের মালিকানাধীন যা দিয়ে আপনি SFTP-তে ঢোকেন, আর ওয়েব সার্ভার সেগুলো গ্রুপ দিয়ে পড়ে।
chmod ACL-মাস্ক রিসেট করে দেয়, আর অ্যাক্সেস নীরবে হারিয়ে যায়। যদি “অনুমতি গোছানোর” পরে আপলোড আবার Permission denied-এ আটকে যায় — setfacl দুটি কমান্ডই আবার চালান।
2 বিটটিই setgid: SFTP-তে আপলোড করা ফাইল www-data গ্রুপে থেকে যায়, নইলে প্যানেল সেগুলো পুনরায় লিখতে পারবে না। বিকল্প C-এর পরে FileZilla-তে আবার সংযোগ করুন — নতুন গ্রুপ কেবল নতুন লগইনেই কার্যকর হয়। যাচাই: id deploy (www-data গ্রুপ দেখা যেতে হবে) এবং ls -ld /path/to/monitor (drwxrwsr-x — s অক্ষরের মানে setgid সেট করা আছে)।
অন্য সার্ভারে স্থানান্তর:
config.php, data/ সহ কপি করুন।mysqldump → নতুনে ইমপোর্ট; config.php-এ ডেটাবেস তথ্য সংশোধন করুন।adm গ্রুপে সদস্যপদ, cron-কাজ।যদি লগ-ইন করতে না পারেন — সবকিছু সার্ভার থেকে সরাসরি ডেটাবেসে ঠিক করা যায়। ডেটাবেস খুলুন (নাম — config.php থেকে):
WebAuthn কী হারিয়েছেন (দ্বিতীয় ফ্যাক্টর পার হচ্ছে না) — 2FA বন্ধ করুন, পাসওয়ার্ড দিয়ে লগ-ইন করুন, নতুন কী নিবন্ধন করুন:
পাসওয়ার্ড ভুলে গেছেন — নতুন হ্যাশ সেট করুন (সার্ভারে তৈরি করে বসিয়ে দিন):
IP-ফিল্টারে নিজেকে ব্লক করে ফেলেছেন — সীমাবদ্ধতা বন্ধ করুন:
sudo mysql, অথবা phpMyAdmin / হোস্টিং প্যানেলের ডেটাবেস বিভাগ। পুনরুদ্ধারের পর WebAuthn ও IP-ফিল্টার আবার চালু করুন।
জবগুলোর সারসংক্ষেপ থাকে সার্ভারের root-cron-এ (যোগ করা হয় sudo crontab -e দিয়ে)। আপনি যেসব টুল ব্যবহার করেন কেবল সেগুলোর লাইন রেখে দিন; পাথগুলো নিজের সার্ভার অনুযায়ী ঠিক করে নিন।
sudo crontab -l এবং cron-সার্ভিস সক্রিয় কিনা।
config.php-এর TIMEZONE নয়। TIMEZONE কনস্ট্যান্ট শুধু PHP-তে প্রভাব ফেলে (প্যানেল কীভাবে তারিখ দেখায়), কিন্তু cron-ডিমন জবগুলো চালায় OS-এর সিস্টেম সময় অনুযায়ী। সার্ভারের টাইমজোন আপনার সঙ্গে না মিললে “08:00”-এর রিপোর্ট ভুল সময়ে আসবে। উদাহরণ: সার্ভার অন্য টাইমজোনে (Asia/Karachi, UTC+5), আর আপনি ঢাকায় (UTC+6) → “08:00”-এর রিপোর্ট আপনার সময়ে 09:00-এ আসবে। যাচাই করুন এবং প্রয়োজনে সিস্টেমের টাইমজোন নিজের মতো ঠিক করে নিন:
0 8 * * * লাইনটি স্থানীয় সময় অনুযায়ী 08:00-এ চলবে। নইলে cron নিজেই সরাতে হতো, কিন্তু শীত/গ্রীষ্মকালীন সময়ে পরিবর্তনের সময় ব্যবধান আবার এলোমেলো হয়ে যাবে — তাই সিস্টেমের টাইমজোন সেট করাই সঠিক।
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 দিয়ে যোগ করুন।/usr/local/bin/-এ কীভাবে রাখবেন। FileZilla থেকে সরাসরি সেখানে লেখা যায় না — ডিরেক্টরিটি root-এর মালিকানায়, আর SFTP-ক্লায়েন্ট SSH_FX_PERMISSION_DENIED পাবে। ক্রমটি এমন: প্রথমে ফাইলটি /tmp-এ আপলোড করুন (সেখানে সবাই লিখতে পারে), তারপর একটি কমান্ডেই সেটি জায়গামতো সরান:
/tmp দরকার — /var/tmp নয় এবং প্যানেলের ভেতরের tmp/-ও নয় (শেষেরটি www-data-এর মালিকানায় ও আপনার ইউজারের কাছে বন্ধ)। FileZilla-র ট্রিতে /tmp হলো উপরের স্তরের একটি শাখা, var-এর পাশে, তার ভেতরে নয়।
/usr/local/bin/-এ, লগ — /var/log/arciveo-cron.log) — ম্যানুয়ালি কিছু করার দরকার নেই।
/home/*/web/*/public_html ও /var/www/* ঘেঁটে প্যানেলের ইনস্টলেশন খুঁজে বের করে এবং রিপোর্ট তাদের data/-তে রাখে। প্যানেল অন্য পাথে থাকলে — স্ক্রিপ্টের ভেতরের for app in … লাইনে সেটি যোগ করুন, নইলে Lynis/SMART/debsums/Logwatch-এর রিপোর্ট প্যানেলে পৌঁছাবে না।
logs/cron.log ফাইলটি প্রথমে তৈরি করে root-cron — এটি root-এর মালিকানায় থাকবে, ফলে প্যানেলের “cron জার্নাল” ট্যাব সেটি পড়তেও পারবে না, পরিষ্কারও করতে পারবে না। ফাইলটি আগেভাগেই ওয়েব-ইউজারের নামে তৈরি করুন (সাইট ডিরেক্টরির মালিক; HestiaCP-তে এটি একটি অ্যাকাউন্ট, যেমন admin) — তখন root-cron কেবল যোগ করে লিখবে, মালিকানা বদলাবে না:
stat -c %U /path/to/monitor।
sudo crontab -e), নইলে এটি দুবার চলবে।
sudo crontab নয় (তাহলে প্যানেলের সেশনে অ্যাক্সেস পাওয়া যে কেউ সরাসরি root-এ এসকেলেট করতে পারত), বরং দুটি কমান্ড (list/set) সহ একটি সংকীর্ণ স্ক্রিপ্ট, যা কেবল পরিষেবা-কমেন্টের মাঝে থাকা নিজের ব্লকটিই ছোঁয়। একবার ইনস্টল করুন:
www-data থেকে ভিন্ন হতে পারে — সাইটের PHP-FPM পুল কার নামে চলছে তা যাচাই করুন (ps -o user= -C php-fpm) এবং সেটি sudoers-লাইনে বসান।
public/crontab_monitor.php ফাইলটি FTP/SFTP-তে সাইটের অন্য ফাইলের চেয়ে আলাদা সিস্টেম-ইউজারে (যেমন root) আপলোড হয়, ওয়েব-সার্ভার সেটি পড়তে পারবে না। পাশের ফাইলের সঙ্গে মালিকানা ও পারমিশন মিলিয়ে নিয়ে ঠিক করুন:
Monitor dpkg-query — APT প্যাকেজ ডেটাবেসের মাধ্যমে টুলের উপস্থিতি শনাক্ত করে। যদি টুলটি apt দিয়ে ইনস্টল না করা হয় (ম্যানুয়ালি, snap থেকে বা সোর্স থেকে), তাহলে dpkg সেটি দেখতে পায় না।
500 ত্রুটি — PHP, nginx এবং মনিটরের নিজস্ব লগ পরীক্ষা করুন:
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 aa-status প্রোফাইল দেখায়, অথচ “AppArmor” পৃষ্ঠা “নিষ্ক্রিয়” দেখায়)। কারণ: এই মডিউলের কমান্ডটির উপর ওয়েব-ব্যবহারকারীর sudo-অনুমতি নেই। উপরের তালিকা থেকে এটি পরীক্ষা করুন: যদি পাসওয়ার্ড চায় — /etc/sudoers.d/monitor-এ অনুপস্থিত লাইনটি যোগ করুন (“sudo কনফিগারেশন”)। সাধারণ “নতুন” কমান্ড: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD)।
apache2ctl, ausearch, aa-status বা ss অনুমোদিত নয়, অথবা ওয়েব-ব্যবহারকারী adm/systemd-journal গ্রুপে নেই (সেখান থেকে fail2ban/auth/modsec লগ ও journalctl — Falco এবং কার্নেল ইভেন্ট পড়া হয়)।
লক্ষণ: সার্ভারে ডেটা আছে (shell দিয়ে দেখা যায়), কিন্তু পেজে “কোনো ডেটা নেই” বা ভুল স্ট্যাটাস দেখায় — যেমন বেস তৈরি হওয়া সত্ত্বেও AIDE “ইনিশিয়ালাইজ করা হয়নি” দেখায়।
কারণ হলো open_basedir: অনেক প্যানেল ও হোস্টিং PHP-FPM পুলকে ডোমেনের ডিরেক্টরিতে সীমিত করে রাখে, তাই সিস্টেম পাথে (/var/lib/aide, /var/log, /proc…) PHP ফাংশন file_exists(), file_get_contents(), filemtime() ব্লক হয়ে যায়। মনিটর এই সমস্যা এড়াতে এমন পাথ স্ট্যান্ডার্ড সিস্টেম কমান্ড (cat, test, stat) দিয়ে পড়ে।
open_basedir। সঠিক সমাধান হলো সিস্টেম কমান্ড দিয়ে পড়া (AIDE ও নেটওয়ার্ক মনিটরের জন্য ইতিমধ্যে করা হয়েছে)। open_basedir-কে /var, /proc-এ সম্প্রসারিত করার প্রয়োজন নেই এবং তা কম নিরাপদ।
মনিটর ৪৪৩ পোর্টের মাধ্যমে সরাসরি ডোমেনে সংযোগ করে সার্টিফিকেট যাচাই করে। সার্ভার থেকেই যদি ডোমেন অগম্য হয় বা ফায়ারওয়াল পোর্ট বন্ধ করে রাখে — তাহলে যাচাই ব্যর্থ হবে।
/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) ও Apache (/etc/apache2/sites-enabled/) কনফিগ থেকে এবং HTTP_HOST-এর বর্তমান হোস্ট থেকে ডোমেনগুলো স্বয়ংক্রিয়ভাবে নেয়।
মনিটর config.php-এর ব্যবহারকারী দিয়ে MySQL-এ সংযুক্ত হয়, যার শুধু নিজের ডেটাবেসে অ্যাক্সেস আছে। MySQL information_schema-তে শুধু সেই ডেটাবেসগুলো দেখায় যেগুলোতে অধিকার আছে — তাই বাকিগুলো দেখা যায় না।
মনিটর যাতে সব ডেটাবেস দেখতে পারে, এই ব্যবহারকারীকে শুধু পড়ার অধিকার দিন (একবার root থেকে; config.php-এর ব্যবহারকারীর নাম বসান):
sudo mysql ব্যবহার করে না: ডেটাবেসের তালিকা তার নিজস্ব PDO-সংযোগের মাধ্যমে নেওয়া হয়।
PostgreSQL-এর জন্য postgres ব্যবহারকারী পর্যায়ের অ্যাক্সেস দরকার, যা প্যানেলের ওয়েব-ব্যবহারকারীর নেই। PHP থেকে বিস্তৃত sudo psql খোলা নিরাপদ নয় — এর বদলে প্যানেল প্যারামিটারবিহীন একটি সংকীর্ণ র্যাপার কল করে, যা শুধু সংস্করণ, সংযোগসংখ্যা এবং আকারসহ ডেটাবেসের তালিকা ছাপায়। এটি তৈরি করুন:
monitor-pgstat লাইনটি সরিয়ে দিন (ম্যানুয়াল ইনস্টলেশনের ধাপ ১৩) এবং স্ক্রিপ্টটিও তৈরি করবেন না: PostgreSQL কার্ডটি কেবল নিষ্ক্রিয় থাকবে।
প্যানেল দেখায় কী ঘটছে; নিচে দেওয়া হলো সাধারণ পরিস্থিতিতে কী করবেন। মূল নীতি: আতঙ্কিত হবেন না, বৈধ কার্যকলাপের সঙ্গে মিলিয়ে দেখুন (আপনার নিজের কাজ, আপডেট, ব্যাকআপ), এবং গুরুত্ব অনুযায়ী সাড়া দিন।
ignoreip-এ আছে।/etc-এর বাইরে, /usr/share-এর বাইরে) — সম্ভাব্য প্রতিস্থাপন। প্যাকেজটি যাচাই করুন: debsums PACKAGE_NAME, সন্দেহ হলে এটি পুনরায় ইনস্টল করুন (apt install --reinstall)।127.0.0.1-এ বাঁধুন বা UFW-তে পোর্ট বন্ধ করুন। এটি একটি বাস্তব ফাঁক।certbot renew বা প্যানেলের সেটিংস পরীক্ষা করুন)।sudo apt update && sudo apt upgrade; কার্নেল আপডেটের পর সার্ভার রিবুট করুন।