این راهنمای نصب، پیکربندی و نگهداری Arcivéo Security Monitor است. بخشها گروهبندی شدهاند: مرور کلی، استقرار پنل، اتصال ابزارهای امنیتی، ماژولهای داخلی و عیبیابی. دستورها را میتوان با دکمهٔ سمت راست کپی کرد.
نصب پنل در صفحههای گامبهگام جداگانه توضیح داده شده است. روش را انتخاب کنید:
Arcivéo Security Monitor — داشبورد امنیت سرور. دادهها را از ابزارهای نصبشده (Fail2ban، UFW، Lynis، ModSecurity، AIDE، ClamAV، Auditd، CrowdSec، Suricata، Falco و غیره) جمعآوری کرده و آنها را در یک رابط یکپارچه با داشبورد، نقشهٔ حملات و صفحات جزئیات هر ابزار نمایش میدهد.
Monitor یک ابزار حفاظتی فعال نیست — خودش حملات را مسدود نمیکند. وظیفهٔ آن گردآوری اطلاعات از ابزارهای درحالاجرا و نمایش آن به شکلی کاربردی است.
مانیتور فقط بهصورت محلی کار میکند — باید روی همان سروری نصب شود که پایش میکند. هیچ SSH یا API از راه دور وجود ندارد.
همهٔ فرمانها (fail2ban-client، ufw status، ipset list و غیره) را پنل با کاربر وبسرور (معمولاً www-data، و در پنلهای میزبانی حساب سایت) و با مجموعهٔ محدودی از دسترسیهای sudo اجرا میکند — فقط روی ابزارهای مشخص، بدون دسترسی کامل root. نتایج تجزیه شده و در مرورگر نمایش داده میشوند.
دو ریتم کار. صفحههای پنل در همان لحظهٔ باز شدن از ابزارها میپرسند — بنابراین همیشه وضعیت کنونی را میبینید. جدا از آن، کارهایی هم طبق زمانبندی (cron) در پسزمینه اجرا میشوند:
فهرست کامل کارها در بخش «همهی cron-jobها در یک جا» آمده است.
امتیاز از حداکثر آغاز میشود و برای هر مشکل شناساییشده کاهش مییابد:
PermitRootLogin yes) — −20PasswordAuthentication yes) — −10X11Forwarding فعال است، MaxAuthTries بیش از ۳ است یا فایل sshd_config برای همهٔ حسابها خواندنی است — −5TRACE فعال است یا هدر Strict-Transport-Security یا X-Frame-Options وجود ندارد — −5نتیجه: 80+ = محافظتشده، 60–79 = هشدار، <60 = در معرض خطر.
WebAuthn — استاندارد احراز هویت بدون رمز عبور از طریق کلید سختافزاری. از YubiKey، Touch ID، Face ID، Windows Hello و Passkey پشتیبانی میکند.
پس از ورود با رمز عبور، سیستم تأیید از طریق کلید ثبتشده را درخواست میکند. حتی اگر رمز عبور لو برود، بدون کلید فیزیکی یا زیستسنجی ورود ممکن نیست.
برای پیکربندی، بخش کلیدهای WebAuthn را در منوی کناری باز کنید و روی «ثبت کلید» بزنید. همان ابتدا دو کلید ثبت کنید: اگر تنها کلید گم شود یا خراب شود، ورود به پنل با آن ممکن نخواهد بود.
کانالها چهارتاست: Telegram، ایمیل، webhook و اعلان فوری در مرورگر. اینها از یکدیگر مستقلاند — هرکدام را که خواستید روشن کنید، حتی هر چهار تا را. گزارش امنیتی روزانه، هشدارهای بار و یافتههای حسگر رویداد هم از همین کانالها میروند؛ تنظیمشان یک بار همینجا، در «تنظیمات» انجام میشود.
Telegram. به توکن ربات و chat id نیاز دارید:
@BotFather پیام دهید ← /newbot ← یک توکن به شکل 123456:ABC... دریافت کنید.@userinfobot پیام دهید، یا https://api.telegram.org/bot<TOKEN>/getUpdates را باز کنید و "chat":{"id":...} را بیابید.ایمیل. دو روش برای انتخاب در «تنظیمات» ← ایمیل:
re_...) و دامنه تأییدشده فرستنده را وارد کنید.Webhook. یک نشانی که POST بپذیرد، Slack و Discord و Mattermost و n8n و پردازشگر خودتان را پوشش میدهد. «تنظیمات» ← Webhook: نشانی را بچسبانید و کلید را روشن کنید.
{"text": …} فرستاده میشود و به Discord شکل {"content": …} (Discord پیامهای بلندتر از ۲۰۰۰ نویسه را نمیپذیرد، از این رو متن کوتاه میشود)؛text، event، severity، source، count، host، ts — دیگر لازم نیست متن پیام دوباره تجزیه شود.اعلانهای فوری. پیام مستقیم به مرورگر میرسد و اگر پنل را به صفحهٔ اصلی گوشی افزوده باشید، مانند اعلان معمولی یک برنامه نمایان میشود — بیآنکه بات یا کارساز ایمیلی در میان باشد. «تنظیمات» ← اعلانهای فوری: کلید را روشن کنید و روی هر دستگاهی که باید اعلان بگیرد دکمهٔ «اتصال این دستگاه» را بزنید. شمارندهٔ «دستگاههای متصل» نشان میدهد چند تا هستند.
وضعیت گزارش: «هشدار» یا «سالم». عنوان فقط در صورت وجود یک مشکل واقعی یا اقدامی در انتظار، به «هشدار» تغییر میکند: کشف تهدید ClamAV، تغییر فایلها در AIDE، رویدادهای بحرانی Falco (Emergency/Alert/Critical در ۲۴ ساعت گذشته)، از کار افتادن سرویس در Monit، نیاز به راهاندازی مجدد، انقضای SSL (≤۱۴ روز) یا انتظار برای بهروزرسانیهای امنیتی. نویز پسزمینه — تلاشهای SSH رباتها، IPهای بنشده توسط fail2ban، هشدارهای Suricata، اخطارهای Lynis و درخواستهای ازپیشدفعشده ModSecurity — وضعیت را بالا نمیبرد، بنابراین چنین اعدادی در گزارش بهخودیخود به معنای «هشدار» نیستند.
ماژولهای تفصیلی پایش (Lynis، UFW، ModSecurity، نقشه حملات، AIDE، ClamAV و غیره) با داشتن لایسنس معتبر باز میشوند. بدون آن، داشبورد، تنظیمات و حساب کاربری کار میکنند، اما ماژولها کارت «نیازمند لایسنس» را نشان میدهند.
پس از خرید در حساب کاربری، یک کد فعالسازی به شکل ARCIVEO-XXXX-XXXX-XXXX-XXXX دارید. باید آن را روی دامنه پنل خود «فعال» کنید — این کار کد را به یک فایل لایسنس امضاشده (بلوک [license]) تبدیل میکند که آن را در پنل وارد میکنید.
نحوه فعالسازی (۳ گام):
my.arciveo.com ← بخش «لایسنسها» / «فعالسازی لایسنس» — کد ARCIVEO-… را کپی کنید.monitor.example.com). روی فعالسازی بزنید — سیستم یک فایل لایسنس متصل به این دامنه میسازد و آن را در فیلدی با دکمه «کپی» نمایش میدهد.پنل کلید را بهصورت رمزنگاریشده بررسی میکند: امضا، اتصال به دامنه و مدت اعتبار.
APP_URL در config.php بردارید و فقط نام میزبان را وارد کنید — بدون https:// و بدون پیشوند www. فعالسازی یکبار مصرف است: کد به لایسنسِ دامنه واردشده تبدیل میشود و دوباره فعال نمیشود — با اشتباه در دامنه، کلید با پنل شما جور در نمیآید و کد مصرف میشود. بنابراین دامنه را با دقت وارد کنید.
همه پارامترهای اصلی پنل در یک فایل config.php در ریشه (کنار پوشه public/) با ثابتهای معمول define() تعریف شدهاند. این فایل هنگام نصب ساخته میشود؛ ویرایش دستی آن بهندرت لازم است — بیشتر هنگام تغییر دامنه، انتقال یا اتصال به پایگاهداده دیگر. پس از هر ویرایش PHP-FPM را دوباره راهاندازی کنید (وگرنه بهدلیل OPcache تغییرات اعمال نمیشوند).
مقادیر خود را در جاهای مشخصشده جایگزین کنید؛ بقیه را همانطور رها کنید:
پایگاهداده. مشخصات اتصال به MySQL/MariaDB:
DB_HOST — میزبان سامانه پایگاهداده، تقریباً همیشه 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.
پنل پشت ورود با گذرواژه است و اگر پالایهٔ IP روشن باشد پشت آن هم. برای یک برنامه هیچکدام به کار نمیآید، پس سامانههای بیرونی ورودی جداگانهٔ خود را دارند — دو نشانی فقطخواندنی که با توکن محافظت میشوند. توکن روی کارساز چیزی را تغییر نمیدهد: تنها میتوان با آن شاخصها را گرفت.
روشنکردن — «تنظیمات» ← «API فقطخواندنی»: کلید «روشن کردن API»؛ توکن در نخستین ذخیره خودکار ساخته میشود. دکمهٔ «توکن تازه» توکن دیگری صادر میکند و در همان لحظه دسترسی همهٔ کسانی را که از توکن پیشین استفاده میکردند قطع میکند.
/api/status.php — JSON: امتیاز امنیت، وضعیت ماژولها، آخرین اندازهگیری بار همراه با سنگینترین فرایندها، و رویدادهای امنیتی ۲۴ ساعت گذشته؛/api/metrics.php — همان عددها در قالب متنی Prometheus (سنجههای arciveo_*: arciveo_security_score، arciveo_fail2ban_banned، arciveo_cpu_busy_pct و جز آن).اگر کارخواه شما نمیتواند سرایند بگذارد، توکن بهصورت پارامتر هم پذیرفته میشود — ?token=…. توجه داشته باشید که در این شکل به گزارش دسترسی کارساز وب راه مییابد، پس سرایند بهتر است.
Prometheus. بلوک آمادهٔ scrape_configs:
api disabled — API در تنظیمات خاموش است. درخواستهای ردشده همراه با IP فرستنده در گزارش برنامه نوشته میشوند، پس تلاش برای حدسزدن توکن در صفحهٔ «لاگهای برنامه» دیده میشود.
پنل روی هر کارساز جداگانه نصب میشود و به پرسش «حال این ماشین چطور است» خوب پاسخ میدهد. به پرسش «حال همهٔ ماشینهای من چطور است» پاسخ نمیدهد — برای همین هر پنل میتواند خلاصهای کوتاه به حساب کاربری بفرستد، جایی که کارسازها در یک فهرست دیده میشوند.
آنچه در حساب کاربری برمیدارید my.arciveo.com ← بخش «کارسازهای من»: آنجا یک توکن (به شکل fk_…) صادر میشود و نشانی گیرنده https://my.arciveo.com/api/fleet.php آورده شده است. توکن برای هر حساب یکی است — برای همهٔ کارسازهای شما همان یکی.
آنچه در پنل تنظیم میکنید — «تنظیمات» ← «خلاصهٔ کارسازها»: نشانی گیرنده، توکن، نام کارساز (نامی که در فهرست میآید؛ خالی بگذارید، دامنهٔ پنل برداشته میشود) و کلید «فرستادن خلاصه». دکمهٔ «همین حالا بفرست» ارتباط را بیدرنگ و بدون انتظار برای زمانبندی میآزماید.
پس از آن خلاصه با cron هر ۱۵ دقیقه فرستاده میشود:
دقیقاً چه چیزی فرستاده میشود: نام و دامنهٔ کارساز، سیستمعامل، مدت کارکرد، نسخهٔ PHP؛ امتیاز امنیت؛ وضعیت ماژولها (UFW، شمار jailهای Fail2ban، مسدودسازیهای امروز، اجرا بودن CrowdSec و Suricata و Falco، تهدیدهای ClamAV، تغییرات AIDE، شاخص Lynis، بهروزرسانیهای در انتظار، نیاز به راهاندازی دوباره، روزهای باقیمانده تا انقضای گواهی، شمار بندرهای باز خطرناک)؛ آخرین اندازهگیری بار (load، CPU، RAM، دیسک، inodes)؛ شمارندههای رویداد ۲۴ ساعت گذشته و آخرین رویداد بحرانی. در خلاصه نه گزارشی هست، نه گذرواژهای و نه محتوای فایلی.
sudo crontab -l) و پاسخ دکمهٔ «همین حالا بفرست». خطاهای فرستادن با نشان FLEET در گزارش برنامه نوشته میشوند — همانجا پیداست که توکن رد شده (HTTP 401) یا اصلاً ارتباط برقرار نشده است.
UFW (Uncomplicated Firewall) رابطی ساده برای nftables/iptables است. همه پورتهای ورودی را جز مواردی که صراحتاً مجاز شدهاند میبندد. صفحه «فایروال UFW» وضعیت و قوانین را نشان میدهد.
ufw enable حتماً SSH را مجاز کنید (ufw allow OpenSSH)، وگرنه دسترسی به سرور را از دست میدهید.
deny بسته شده، از بیرون قابلدسترس محسوب نمیشود.
Skipping adding existing rule خطا نیست. UFW با این پیام اعلام میکند که دقیقاً همین قانون از قبل وجود دارد و آن را دوباره اضافه نمیکند. هنگام اجرای مجدد پیکربندی خودکار (که خودتکرارپذیر است) این پیام عادی است — نیازی به واکنش نیست.
پس از عبور از تعداد تلاشهای ناموفق ورود، بهطور خودکار IP را مسدود میکند. لاگهای SSH، nginx، Apache و دیگر سرویسها را تحلیل میکند.
نصب پایه بالاتر آمده است. اینجا پیکربندی عملی ارائه میشود که دهها jail فعال و هزاران بلاک ایجاد میکند: تنظیمات عمومی، jailهای کلیدی و بن خودکار IPهای مخرب از فهرست ipsum.
فایل /etc/fail2ban/jail.local — تنظیمات عمومی و مهمترین jailها:
ignoreip حتماً IP خود و شبکههای مورد اعتماد را وارد کنید، وگرنه ممکن است خودتان را بن کنید. پس از ویرایش: sudo fail2ban-client reload.
بارگذاری خودکار بلاکلیست ipsum — در کرون root (sudo crontab -e): level 1 (بیش از ۱۰۰ هزار IP) در ست ipsum بارگذاری میشود که روی فایروال مسدود میگردد (جزئیات بیشتر — در بخش «بلاکلیست IPset»):
ipsum باشد — دقیقاً همین را داشبورد میخواند (کارت «IPset ipsum»). سطوح: levels/1.txt — حداکثر پوشش، levels/3.txt — دقیقتر (۳ منبع یا بیشتر).
چرا «مانیتور امنیت» به دو ناحیه تقسیم شده است. حفاظت در دو سطح کار میکند و داشبورد آنها را با هم مخلوط نمیکند:
sshd، apache-*، nginx-* و غیره) و مکررهای بدخیم (jail recidive — کسانی که قبلاً چند بار بن شدهاند). اینها IPهایی هستند که واقعاً به شما نفوذ کردهاند — روی نقشهٔ حملات و «خط زمانی» دیده میشوند.ipset ipsum که روی فایروال با قانون DROP مسدود میشود. این آدرسها در بیشتر موارد اصلاً به سرور شما نزدیک نشدهاند — از پیش مسدود میشوند؛ شمارندهٔ «IPset ipsum» نشان میدهد چند مورد پیشگیرانه مسدود شده است.تفاوت ساده است: واکنشی — «اینها حمله کردند و بن شدند»، پیشگیرانه — «اینها پیش از تلاش مسدود شدند». پیشتر در recidive بهصورت مصنوعی list-3 ipsum بارگذاری میشد (از همینجا تقسیم قدیمی «recidiveهای فهرستی» آمده بود)؛ اکنون recidive فقط مکررهای واقعی است و پیشگیری کاملاً روی فایروال انجام میشود.
ipsum — فهرست عمومی IPهای مخرب که روزانه بهروزرسانی میشود. Monitor تعداد آدرسهای بارگذاریشده را روی داشبورد و نقشهٔ حملات نشان میدهد و آن را در امتیاز امنیتی لحاظ میکند (−۱۰ اگر مجموعه بارگذاری نشده باشد).
سادهترین گزینه بدون fail2ban — یک مجموعهٔ جداگانهٔ ipsum با انسداد از طریق iptables:
@reboot ببندید. ضمناً فرمان create … -exist حد maxelem 300000 را تعیین میکند (پیشفرض ۶۵۵۳۶ است — 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 — بالاتر). در نصب خودکار نیازی به انجام دستی کاری نیست.
جایگزین امروزی 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) — یک باگ شناختهشدهٔ قطعهٔ پیکربندی AIDE در Ubuntu 22.04. پایگاهداده ساخته نمیشود. قطعهٔ خراب را جدا کنید و دوباره تلاش کنید:
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 در Ubuntu/Debian جدید ممکن است /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. بهویژه برای بررسی /var/www از نظر شلهای PHP و کد مخرب مفید است.
enable --now «غیرفعال» نشان میدهد؟ سه علت رایج:
1. خط Example در فایل پیکربندی باقی مانده است — تا وقتی این خط باشد، clamd از راهاندازی خودداری میکند:
2. پایگاه امضاها دانلود نشده است — clamd بدون آن راهاندازی نمیشود:
3. فقط در حال بارگذاری است — clamd حدود ۸ میلیون امضا را در ۳۰ تا ۶۰ ثانیه در حافظه بارگذاری میکند. صبر کنید و بررسی کنید: systemctl is-active clamav-daemon (وضعیت activating ← هنوز در حال بارگذاری است).
sudo journalctl -u clamav-daemon -n 30 --no-pager.
clamd فقط امضاها را در حافظه نگه میدارد و خودش بهصورت زمانبندیشده چیزی اسکن نمیکند. پنل نتایج اسکن زمانبندیشده را نشان میدهد، پس به یک cron نیاز است که اسکن کند و لاگ بنویسد. نصب خودکار یک پوشش /usr/local/bin/clamav-scan.sh و یک cron در ساعت 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 و حالت ۷۵۰ روی دایرکتوری مینویسد و وبسرور (www-data) نمیتواند آن را بخواند. دایرکتوری را برای عبور باز کنید — فایلهای داخل آن محافظتشده باقی میمانند:
فراخوانیهای سیستمی را از طریق eBPF/kernel module رهگیری میکند و ناهنجاریها را در لحظه تشخیص میدهد: اجرای shell از nginx، خواندن /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 — یک فایروال وب (WAF) برای Apache یا Nginx. حملات در سطح برنامه را مسدود میکند: تزریق 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> هستند (مثلاً غیرفعالکردن WAF برای phpMyAdmin) و حالت سراسری را تعیین نمیکنند.www-data است، در HestiaCP استخر سایت با مالک سایت کار میکند (مثلاً admin) — با grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf بررسی کنید.X-Forwarded-For میگیرد. تنها تراکنشهایی که قانونی روی آنها فعال شده وارد آمار میشوند: دستور 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 فعال باشد (بلوک set httpd با allow localhost)، وگرنه monit status خطا برمیگرداند.
monitrc خط set httpd کامنت شده (بهطور پیشفرض بهصورت # set httpd port 2812 … است). بلوک را از کامنت خارج کنید و به localhost اجازه دهید. (۲) httpd فعال بهتنهایی چیزی را زیر نظر نمیگیرد — Monit فقط چیزهایی را میشمارد که با استانزای check تعریف شدهاند؛ بدون آنها فهرست حتی با رابط فعال خالی است. حداقل پیکربندی کارآمد:
conf.d آماده با httpd روی ۲۸۱۲ و مجموعهای از بررسیها قرار میدهد — در نصب جدید نیازی به پیکربندی دستی نیست.
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 اضافه شده است: پروفایل در هسته بارگذاری میشود اما چیزی را محدود نمیکند. Ubuntu دهها پروفایل را برای برنامههایی که از user namespaces استفاده میکنند (مرورگرها، کلاینتهای torrent و مانند آن) به این شکل علامتگذاری میکند. وقتی چنین پروفایلهایی وجود دارند، کارت «پروفایلهای بارگذاریشده» کهربایی میشود و تعدادشان را نمایش میدهد — برای مثال unconfined: 90 با ۱۲۰ پروفایل بارگذاریشده و ۲۶ در enforce. تنها پروفایلهای در enforce واقعاً محافظت میکنند؛ در Ubuntu 22.04 (AppArmor 3.x) این حالت وجود ندارد و اعداد همیشه با هم میخوانند.
unconfined گذاشته به enforce فقط باید آگاهانه انجام شود: آنها بهاشتباه غیرفعال نشدهاند، بلکه چون در غیر این صورت کارکرد خودِ برنامهها مختل میشود. پروفایلهای در complain موضوع دیگری هستند: در آنجا قوانین از پیش نوشته شدهاند و فقط اعمال نمیشوند.
debsums بررسی میکند که فایلهای بستههای نصبشده با چکسامهای مخزن مطابقت دارند — باینریهای سیستمی دستکاریشده را شناسایی میکند (مکمل AIDE). بررسی کامل ۱ تا ۲ دقیقه طول میکشد، بنابراین با cron اجرا میشود و پنل نتیجه را از data/debsums/debsums.log میخواند و خودش آن را دستهبندی میکند (فقط باینریها و کتابخانهها مهماند).
وظیفه در cron کاربر root قرار میگیرد (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 ذخیره کند. Monitor آخرین گزارش و بایگانی را نمایش میدهد.
مانیتور شبکه به نصب نیاز ندارد — این یک صفحهٔ توکار در پنل است. وضعیت شبکهٔ سرور را از منابع محلی نمایش میدهد:
/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 گرفته میشود و پنل آن را میخواند.
وظیفه در cron کاربر root قرار میگیرد (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 دیسک (خواندن/نوشتن)، پرشدگی دیسک و inodeها، توصیفگرهای فایل باز و اتصالات 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') در جدول پایگاهداده system_metrics مینویسد؛ درصدها و سرعتها را خود صفحه از تفاوت میان عکسهای مجاور محاسبه میکند (پرشدگی دیسک/inode/توصیفگر/اتصالات MySQL مقادیر لحظهایاند، بدون محاسبهٔ مجدد). به sudo نیاز نیست — منابع بدون دسترسی root خوانده میشوند.
دو ژرفای نگهداری. نماهای لحظهای «خام» پنجدقیقهای یک شبانهروز میمانند (بهعلاوهٔ یک ساعت ذخیره، تا کهنهترین نقطهٔ نمودار هم نقطهٔ پیشین برای محاسبه داشته باشد). هر ساعت که به پایان میرسد در یک سطر تا میشود؛ این سری ساعتی ۳۰ روز نگه داشته میشود و نماهای «۷ روز» و «۳۰ روز» دقیقاً همین را میخوانند. به این ترتیب یک ماه تاریخچه بهجای حدود ۸۶۰۰ سطر، حدود ۷۲۰ سطر هزینه دارد.
پوشش collect-metrics-all.sh (رجوع به خلاصهٔ وظایف cron) خودش همهٔ نمونههای نصبشدهٔ پنل روی سرور را پیدا میکند و cron/collect_metrics.php هر کدام را از نام مالک سایت اجرا میکند.
سنگینترین فرایندها. زیر نمودارها دو جدول هست که هرکدام پنج فرایند پرمصرفتر از نظر CPU را نشان میدهد:
هر دو جدول همیشه ۲۴ ساعت گذشته را توصیف میکنند، حتی وقتی نمودارها یک ماه را نشان میدهند: نمای لحظهای فرایندها تنها در سطرهای پنجدقیقهای وجود دارد و آن سطرها بیش از یک شبانهروز نگهداری نمیشوند.
ps، اسکریپت PHP گردآورنده و زنجیرهٔ cron/sudo بالای آن) از فهرست کنار گذاشته میشوند — وگرنه در هر نما صدرنشین میشدند: ps در لحظهٔ اجرا نزدیک به ۱۰۰ ٪ CPU نشان میدهد. اما دیگر کارهای cron که در همان دقیقه اجرا شدهاند نمایش داده میشوند و جدول دقیقاً برای همین است.
هشدارهای بار (بخش «تنظیمات» ← «هشدارهای بار») — با گذشتن از آستانهٔ CPU/RAM/دیسک/inodes پنل از همهٔ کانالهای روشن اعلان میفرستد (Telegram، ایمیل، webhook، اعلان فوری — همان کانالهایی که گزارش روزانه از آنها میرود؛ برای هشدارها لازم نیست چیزی جداگانه روشن شود) و یکی دیگر هم وقتی که مقدار به حالت عادی بازگردد. تا وقتی آستانه رد شده باقی بماند، پیام تکرار نمیشود: اعلان بعدی تنها پس از چرخهٔ «به حالت عادی بازگشت ← دوباره از آستانه گذشت» میآید.
collect_metrics.php در هر اجرا (هر ۵ دقیقه) بررسی میکند — به cron جداگانه نیاز نیست. وضعیت «قبلاً اطلاع داده شده / هنوز نه» در data/alerts_state.json ذخیره میشود، آستانهها در تنظیمات پنل.
گزارش روزانه به این پرسش پاسخ میدهد که «حال کارساز چطور است». حسگر به پرسشی دیگر پاسخ میدهد — «همین حالا چه رخ داد». هر ۵ دقیقه از منابع سریع میپرسد و تنها آنچه را که از بررسی پیشین تغییر کرده ثبت میکند؛ صفحهٔ «رویدادهای امنیتی» در فهرست، یافتهها را نشان میدهد.
بررسیهای کند — Lynis، debsums، بهروزرسانی بستهها، اعتبار SSL — را حسگر دست نمیزند: عددهایشان بههرحال روزی یک بار عوض میشود و در حوزهٔ گزارش روزانه میماند.
چه چیزهایی را میبیند — نُه منبع:
[Priority: 1] یافته را به سطح بحرانی میبرد؛FOUND در گزارش پویش؛root (بحرانی) و ورود از نشانیای که پیشتر دیده نشده بود (هشدار)؛ابزاری که نصب نشده یا پنل نمیتواند گزارشش را بخواند، تنها خاموش میماند — این نه خطاست و نه رویداد.
data/secwatch_state.json) و اجرای نخست تنها همین نشان را مینویسد. وگرنه بهمحض روشنکردن پایش، اعلانی دربارهٔ هر آنچه ماهها در گزارشها انباشته شده به دستتان میرسید.
تنظیم — «تنظیمات» ← «پایش رویدادها»:
23-7 که در آن هشدارها فرستاده نمیشوند.اعلانها از همان کانالهای گزارش روزانه میروند (Telegram، ایمیل، webhook، اعلان فوری) — لازم نیست چیزی جداگانه روشن شود. همهٔ یافتهها صرفنظر از اینکه اعلانی رفته باشد یا نه در فهرست ثبت میشوند و ۹۰ روز نگه داشته میشوند.
فهرست رویدادها. پالایهها: بازه (۲۴ ساعت، ۷، ۳۰ یا ۹۰ روز)، اهمیت و منبع؛ ۵۰۰ رکورد آخر نمایش داده میشود. دکمهٔ «همین حالا بررسی کن» دقیقاً همان بررسیای را اجرا میکند که cron اجرا میکند — درست پس از تنظیم به کار میآید تا پنج دقیقه منتظر نمانید؛ و اگر اعلانی نرفته باشد دلیلش را هم میگوید («پایینتر از آستانهٔ اهمیت»، «ساعات سکوت»، «هیچ کانال اعلانی تنظیم نشده است»). شمارندهٔ قرمز کنار گزینهٔ فهرست، شمار رویدادهای بحرانی ۲۴ ساعت گذشته است.
کارت نشانی. کلیک روی سطری در فهرست رویدادها یا در بخش نشانیهای مرتبط هر چه درباره یک نشانی دانسته است را باز میکند: گاهشمار رویدادهایش، کشور و در نخستین سطر، نتیجه. سطر فهرست وقتی کارت را باز میکند که رویداد دقیقاً به یک نشانی مربوط باشد؛ اگر چند نشانی در کار باشد، پیوندها همان نشانیهای درون سطرند. نتیجهها چهار تاست:
زیر گاهشمار بخش در همان زمان روی سرور چه گذشت قرار دارد: رویدادهایی که اصلاً نشانی ندارند. AIDE نمیداند چه کسی فایل را تغییر داده و ClamAV نمیداند چه کسی فایل آلوده را آورده است. آنهایی نشان داده میشوند که در بازه فعالیت نشانی و شش ساعت پس از آن رخ دادهاند. همین پیوند ورود با آنچه پس از آن آمده است که تلاش را از دسترسی واقعی جدا میکند.
زمانبندی. این کار در crontab کاربر root گذاشته میشود (sudo crontab -e) و ۲ دقیقه نسبت به گردآوری سنجهها جابهجا شده تا هر دو همزمان آغاز نشوند:
php cron/security_watch.php را صدا نزنید. wrapper همهٔ نصبهای پنل روی کارساز را مییابد و بررسی را به نام مالک سایت اجرا میکند — با همان اختیارات sudo که پنل از وب به کار میگیرد. فراخوانی مستقیم از crontab کاربر root، فایل وضعیت data/secwatch_state.json را با مالکیت root میسازد و دکمهٔ «همین حالا بررسی کن» در پنل از کار میافتد.
صفحهٔ «کارساز وب» گزارش دسترسی را تحلیل میکند و نشان میدهد چند درخواست بوده، چه بخشی از آنها با خطا پایان یافته و چه کسی آنها را فرستاده است. ModSecurity به پرسش «چه چیزی مسدود شد» پاسخ میدهد و این صفحه به پرسش «اصلاً چه چیزی به سایت رسید».
آنچه دیده میشود: شمار درخواستها، RPS، سهم خطاها، شمارندهٔ جداگانهٔ 5xx و حجم دادههای فرستادهشده؛ نمودار درخواستها بر پایهٔ ساعت؛ توزیع کدهای 2xx/3xx/4xx/5xx؛ نشانیهای پرتکرار، IPهای پرتکرار، خطاهای پرتکرار (کد بههمراه مسیر) و کارخواهها (User-Agent). بازه: ۲۴ ساعت یا ۷ روز.
منبع، گزارش دسترسی در قالب combined است، از این رو هم Nginx و هم Apache مناسباند و به هیچ ماژول افزودهای نیاز نیست. پنل گزارش را در میان فایلهای استاندارد جستوجو میکند:
/var/log/nginx/access.log/var/log/apache2/access.log/var/log/apache2/other_vhosts_access.log/var/log/httpd/access_logافزون بر اینها، پنل فایلهای *access*.log و *requests*.log را در /var/log/nginx/، /var/log/apache2/ و /var/log/httpd/ نیز بررسی میکند. بدین ترتیب گزارشی هم پیدا میشود که سایت با رهنمود CustomLog در فایل خودش مینویسد — برای نمونه arciveo-monitor_requests.log که نصبکنندهٔ Arcivéo آن را میسازد.
تنها یک گزارش خوانده میشود: وقتی Nginx پیش از Apache قرار دارد، جمعبستن دو گزارش هر درخواست را دو بار میشمرد. پنل نخستین گزارشِ فهرست بالا را برمیدارد که در یک روز گذشته در آن نوشته شده است (فایلهایی که با الگوی نام پیدا شدهاند پس از آن، از تازهترین، آزموده میشوند)؛ اگر یک روز در هیچکدام نوشته نشده باشد، تازهترین گزارش غیرخالی برداشته میشود. از این رو گزارشی که logrotate خالیاش کرده یا از کارساز وبِ خاموششده به جا مانده، دیگر گزارش فعال را نمیپوشاند. آخرین تکهٔ گزارش خوانده میشود (۳ مگابایت) و نتیجه ۵ دقیقه در حافظهٔ نهان میماند — بنابراین روی سایت پرمراجعه ممکن است بازهٔ انتخابشده بهطور کامل پوشش داده نشود؛ پوشش واقعی بالای نمودار نوشته شده است.
adm تعلق دارند و کاربر وب در این گروه نیست. نصبکنندهٔ Arcivéo او را به این گروه میافزاید؛ پس از نصب دستی، یک wrapper کوچک از root که تنها یک کار برایش مجاز است — نمایش گزارش — مشکل را حل میکند (صفحهٔ ModSecurity هم به همین شیوه کار میکند). wrapper گزارش را با همان قاعدههای پنل برمیگزیند. فرمان در خود صفحه نشان داده میشود؛ اینجا هم میآید. آن را یکجا بچسبانید — این یک فرمان است:
کاربر وب ممکن است با www-data فرق داشته باشد — ببینید استخر PHP-FPM سایت با کدام کاربر اجرا میشود (ps -o user= -C php-fpm) و همان را در سطر sudoers بگذارید. اگر نام گزارش نه access دارد و نه requests، مسیر آن را به ابتدای سطر L=… درون wrapper بیفزایید.
تلاش برای سوءاستفاده از آسیبپذیریهای شناختهشده. پنل درخواستهای گزارش را با امضای حدود بیست اکسپلویت رایج مقایسه میکند: PHP-CGI، پیمایش پوشهها در Apache، PHPUnit، Log4Shell و آسیبپذیریهای روترها، دوربینها و درگاههای VPN. برای هر تلاش، پنل بر پایهٔ واقعیتها میگوید که آیا روی این سرور کار میکند: نسخههای نصبشدهٔ Apache و PHP، وجود Java و کد پاسخ سرور به درخواست فایل. فقط آنچه واقعاً ممکن است کار کند قرمز میشود.
سختسازی وبسرور. پنل هر سایت روی سرور را از راه 127.0.0.1 درخواست میکند و بررسی میکند بازدیدکننده چه دریافت میکند: آیا نسخهٔ وبسرور و PHP دیده میشود، آیا متد TRACE فعال است و آیا هدرهای محافظ Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy و Content-Security-Policy وجود دارند. سایتها از نشانیای که پنل با آن باز شده و از فایلهای میزبان مجازی، اگر پنل بتواند آنها را بخواند، گرفته میشوند. نتیجه هر ۱۰ دقیقه بهروز میشود.
اگر چیزی کم باشد، زیر جدول یک فرمان نمایش داده میشود. این فرمان فایل جداگانهٔ zz-arciveo-hardening.conf را میسازد و وبسرور را فقط پس از موفقیت آزمون پیکربندی دوباره بارگذاری میکند؛ هدرهایی که سایت خودش میفرستد تکرار نمیشوند. CSP بهصورت یک خط پیشنهاد نمیشود: سیاست برای هر سایت جداگانه ساخته میشود، وگرنه سایت دیگر اسکریپتها، استایلها و فونتهای خودش را بارگذاری نمیکند. برای بازگرداندن تغییر در Apache:
ServerSignature) علامتگذاری نمیشود: بدون نسخه، فقط نام سرور و نام میزبان را نشان میدهد.
صفحه «نقشه حملات» کشور را از روی IP با فرمان geoiplookup تشخیص میدهد. بدون بسته GeoIP کشورها شناسایی نمیشوند و نقطهای روی نقشه ظاهر نخواهد شد:
/usr/share/GeoIP/GeoIP.dat برای همه خواندنی است و نتایج در tmp/geoip_cache.json کش میشوند. خود نقشه (Leaflet + کاشیهای OpenStreetMap) در مرورگر بارگذاری میشود — پس رایانهای که داشبورد در آن باز است به اینترنت نیاز دارد.
دو کارت داخلی داشبورد که نه «روشن/خاموش» بودن ابزار، بلکه امنیت واقعی سرور را نشان میدهند. نیازی به نصب ندارند و بدون sudo بهصورت محلی خوانده میشوند.
در معرض بودن خارجی — اینکه چند سرویس روی همه رابطها (0.0.0.0/[::]) گوش میدهند و از بیرون در دسترساند. اگر پایگاهداده یا کش (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) به بیرون باز باشد آن را قرمز نشان میدهد — یک حفره مستقیم (−۱۰ از امتیاز امنیتی). منبع: ss -tuln.
127.0.0.1 مقید کنید (bind-address در پیکربندی MySQL/PostgreSQL، bind 127.0.0.1 در Redis) یا پورت را در UFW ببندید.
127.0.0.1 (loopback) گوش میدهد فقط برای خود سرور دیده میشود — حتی اگر پورت «باز» باشد، از بیرون به آن نمیتوان رسید. به همین دلیل Postfix روی پورت ۲۵ که به loopback مقید شده امن است: پیکربندی خودکار inet_interfaces = loopback-only را تنظیم میکند (بهعلاوه smtpd_banner خنثی — که هشدار Lynis MAIL-8818 درباره افشای نسخه را برطرف میکند). کارت «در معرض بودن خارجی» فقط چیزی را که روی 0.0.0.0/[::] گوش میدهد بهعنوان بیرونی میشمارد؛ سرویسهای loopback در آن نمیآیند.
/etc/postfix/main.cf مقدار smtpd_banner = $myhostname ESMTP (بدون نسخه و سیستمعامل) و inet_interfaces = loopback-only را تنظیم کنید، سپس sudo systemctl restart postfix.
بهروزرسانیهای امنیتی — اینکه چند وصله امنیتی منتظر نصباند و آیا پس از بهروزرسانی هسته نیاز به راهاندازی مجدد است (−۵ از امتیاز امنیتی در صورت وجود وصله). منبع: /usr/lib/update-notifier/apt-check، فایل /var/run/reboot-required. فهرست کامل — در صفحه «بهروزرسانیهای امنیتی».
update-notifier-common). اگر apt-check نبود — مانیتور وصلهها را از طریق apt-get -s upgrade میشمارد.
بهروزرسانی خودکار امنیتی (unattended-upgrades) — در صفحه «بهروزرسانیهای امنیتی» کارتی جداگانه نشان میدهد که آیا نصب خودکار وصلههای امنیتی فعال است و آخرین بار کِی اجرا شده. نیازی به 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 میمانند. بقیه کد است و وبسرور فقط برای خواندن به آن نیاز دارد، که گروه www-data با دسترسی 644 آن را فراهم میکند. سود جانبی: با آسیبپذیری در PHP دیگر نمیتوان فایلهای پنل را بازنویسی کرد. در پنلهای میزبانی (HestiaCP و مشابه) گزینهٔ A لازم نیست: آنجا فایلهای سایت بههرحال متعلق به همان اکانتی هستند که با SFTP وارد میشوید، و وبسرور آنها را از طریق گروه میخواند.
chmod بعدی روی فایلها ماسک ACL را بازنشانی میکند و دسترسی بیصدا از بین میرود. اگر پس از «مرتب کردن دسترسیها» بارگذاری دوباره به Permission denied برخورد کرد — هر دو دستور setfacl را تکرار کنید.
2 در گزینهٔ C همان 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.پنل از قبل کار میکند و روی همین سرور به یک سایت دیگر نیاز است — با دامنهٔ خودش در کنار مانیتور. پس از راهاندازی خودکار، سرور یک Apache + PHP-FPM معمولی است، بنابراین سایت به سه چیز نیاز دارد: پوشهٔ خودش، vhost خودش و گواهی خودش. پنل دستنخورده میماند: کل سرور را زیر نظر دارد و نسخهٔ دوم برای دامنهٔ دوم لازم نیست.
site2.example.com نشانی سایت جدید است. میتواند هم دامنهٔ جداگانه (mycompany.com) باشد و هم زیردامنه (shop.mycompany.com) — برای Apache تفاوتی ندارد و فقط رکورد DNS (گام ۱) و صدور گواهی (گام ۵) فرق میکنند. site2 فقط یک نام کوتاه برای سایت است: پوشهٔ /var/www/site2 و فایل پیکربندی site2.conf با همین نام ساخته میشوند. این نام هیچ ارتباطی با دامنه ندارد؛ Apache نشانی را تنها از ServerName میگیرد و نام میتواند هر چیزی باشد — مثلاً برای shop.mycompany.com استفاده از shop راحت است: پوشهٔ /var/www/shop، پیکربندی shop.conf.
۱. DNS. در پنل DNS نزد ثبتکنندهٔ دامنه یک رکورد A به IP این سرور بسازید:
پس از چند دقیقه بررسی کنید: dig +short site2.example.com باید IP سرور را برگرداند.
۲. پوشهٔ سایت.
۳. vhost. بلوک را یکجا در ترمینال بچسبانید — مسیر سوکت PHP-FPM خودکار تشخیص داده میشود:
۴. سایت را فعال کنید و پیش از بارگذاری مجدد، پیکربندی را بررسی کنید:
۵. SSL. certbot را راهاندازی خودکار از قبل نصب کرده است؛ در این مرحله DNS باید به سرور اشاره کند:
دامنهٔ سوم و دامنههای بعدی هم به همین شکل اضافه میشوند — گامهای ۱ تا ۵ را با دامنه و پوشهٔ دیگر تکرار کنید.
Host با هیچ ServerName مطابقت نکند (ورود با IP یا دامنهٔ شخص دیگری که به سرور شما اشاره میکند)، Apache نخستین سایت به ترتیب الفبا را از /etc/apache2/sites-enabled/ ارائه میکند. سایت پیشفرض 000-default را راهاندازی خودکار غیرفعال میکند، بنابراین این نقش «کشیک» نزد vhost پنل (arciveo-monitor.conf) میماند — و بر سایتهایی که با نام خودشان باز میشوند اثری ندارد. اگر میخواهید با IP سایت دیگری باز شود، نام فایل آن را طوری بگذارید که در الفبا زودتر بیاید (مثلاً 000-site2.conf).
site2_error.log و site2_access.log در /var/log/apache2/.
.htaccess خودش اداره میشود (کنترلر جلویی) و سایت تودرتو چیزی غیر از انتظار شما ارائه میدهد. سایتها را کنار هم نگه دارید: /var/www/monitor و /var/www/site2.
اگر نمیتوانید وارد شوید — همهچیز مستقیماً در پایگاهداده روی سرور قابل تعمیر است. پایگاهداده را باز کنید (نام آن در config.php است):
کلید WebAuthn گم شده (عامل دوم رد میشود) — 2FA را غیرفعال کنید، با رمز عبور وارد شوید و کلید جدید ثبت کنید:
رمز عبور را فراموش کردهاید — هش جدیدی تنظیم کنید (آن را روی سرور بسازید و جایگزین کنید):
با فیلتر IP خودتان را مسدود کردهاید — محدودیت را غیرفعال کنید:
sudo mysql روی سرور، یا phpMyAdmin / بخش پایگاهداده در پنل هاست. پس از بازیابی، دوباره WebAuthn و فیلتر IP را فعال کنید.
خلاصهی وظایف در root-cron سرور قرار میگیرد (از طریق sudo crontab -e افزوده میشوند). فقط سطرهای ابزارهایی را که استفاده میکنید نگه دارید؛ مسیرها را متناسب با سرور خود اصلاح کنید.
sudo crontab -l و اینکه سرویس cron فعال باشد.
TIMEZONE در config.php. ثابت TIMEZONE فقط بر PHP اثر میگذارد (نحوهی نمایش تاریخها در پنل)، اما دیمن cron وظایف را بر اساس زمان سیستمعامل اجرا میکند. اگر منطقهی زمانی سرور با شما یکی نباشد، گزارش «08:00» در زمان دیگری میرسد. مثال: سرور در منطقهی دیگری است (Europe/Berlin، UTC+2) و شما در تهران هستید (UTC+3:30) ← گزارش «08:00» به وقت شما ساعت 09:30 میرسد. منطقهی زمانی سیستم را بررسی و در صورت نیاز با منطقهی خود هماهنگ کنید:
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) — اسکن آنتیویروس ClamAV روی مسیرهای خطرناک (web, home, temp)؛ خلاصه را در /var/log/clamav/scan.log مینویسد که صفحهی ClamAV از آنجا میخواند (سطر 01:30 در crontab بالا)؛load-ipsum.sh ← /usr/local/bin/ (chmod +x) — مجموعهی ipset با نام ipsum (level 1) را در جای خود بهروزرسانی میکند، بدون شکستن قواعد فعال فایروال (سطر 04:00 در crontab بالا)؛daily-report-all.sh ← /usr/local/bin/ (chmod +x) — گزارش cron/daily_report.php پنل را اجرا میکند (سطر 08:00 در crontab بالا)؛daily_report.php — از قبل در پنل هست (cron/daily_report.php)، از طریق daily-report-all.sh اجرا میشود و جداگانه نصب نمیشود؛collect-metrics-all.sh ← /usr/local/bin/ (chmod +x) — cron/collect_metrics.php پنل را اجرا میکند (صفحهی «کارایی»، سطر */5 در crontab بالا)؛ collect_metrics.php از قبل در پنل هست و جداگانه نصب نمیشود؛security-watch-all.sh ← /usr/local/bin/ (chmod +x) — فایل cron/security_watch.php پنل را به نام مالک سایت اجرا میکند (صفحهٔ «رویدادهای امنیتی»، سطر 2-57/5 در crontab بالا)؛ security_watch.php همراه خود پنل میآید و نصب جداگانه نمیخواهد؛fleet-push-all.sh ← /usr/local/bin/ (chmod +x) — خلاصهٔ کارساز را از راه cron/fleet_push.php پنل به حساب کاربری میفرستد (سطر 3,18,33,48 بالا)؛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 فرق کند — بررسی کنید pool PHP-FPM سایت با چه کاربری کار میکند (ps -o user= -C php-fpm) و همان را در سطر sudoers جایگزین کنید.
public/crontab_monitor.php از طریق FTP/SFTP با کاربر سیستمی دیگری (مثلاً root) نسبت به بقیهی فایلهای سایت آپلود شده باشد، وبسرور نمیتواند آن را بخواند. مالک و دسترسیها را با فایل مجاور مقایسه و هماهنگ کنید:
مانیتور وجود ابزارها را از طریق dpkg-query — پایگاه بستههای APT — تشخیص میدهد. اگر ابزار از طریق apt نصب نشده باشد (بهصورت دستی، از snap یا از سورس)، dpkg آن را نمیبیند.
خطای ۵۰۰ — لاگهای PHP، nginx و خودِ مانیتور را بررسی کنید:
www-data بلکه با حساب کاربری اجرا میشود (مثلاً admin — مالک دایرکتوری سایت). همهٔ قواعد sudo و عضویت در گروهها (adm، systemd-journal) باید برای همین کاربر تعریف شوند، وگرنه با وجود اجرای سرویسها ماژولها «غیرفعال / ۰» نشان میدهند. کاربر واقعی 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 را به دایرکتوری دامنه محدود میکنند، بنابراین توابع PHP یعنی file_exists()، file_get_contents()، filemtime() روی مسیرهای سیستمی (/var/lib/aide، /var/log، /proc…) مسدود میشوند. مانیتور این محدودیت را با خواندن چنین مسیرهایی از طریق دستورهای سیستمی استاندارد (cat، test، stat) دور میزند.
open_basedir است. راهحل درست، خواندن از طریق دستورهای سیستمی است (که برای AIDE و مانیتور شبکه انجام شده). گسترش open_basedir به /var و /proc لازم نیست و امنیت کمتری دارد.
مانیتور گواهیها را با اتصال مستقیم به دامنهها از طریق پورت 443 بررسی میکند. اگر دامنه از خود سرور در دسترس نباشد یا پورت با فایروال بسته باشد، بررسی انجام نمیشود.
/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 نیاز دارد که کاربر وب پنل آن را ندارد. باز کردن sudo psql گسترده از داخل PHP ناامن است — بهجای آن، پنل یک پوشش محدود و بدون پارامتر را فرا میخواند که فقط نسخه، تعداد اتصالها و فهرست پایگاههای داده بههمراه اندازهشان را چاپ میکند. آن را بسازید:
monitor-pgstat را از sudoers حذف کنید (گام ۱۳ نصب دستی) و خود اسکریپت را نسازید: کارت PostgreSQL صرفاً غیرفعال باقی میماند.
پنل نشان میدهد چه اتفاقی میافتد؛ در ادامه چه باید کرد در وضعیتهای رایج. اصل کلی: نترسید، با فعالیت مجاز (اقدامات خودتان، بهروزرسانیها، پشتیبانگیریها) مقایسه کنید و بر اساس شدت واکنش نشان دهید.
ignoreip است./etc، خارج از /usr/share) — احتمال دستکاری. بسته را بررسی کنید: debsums PACKAGE_NAME، در صورت تردید آن را دوباره نصب کنید (apt install --reinstall).127.0.0.1 مقید کنید یا پورت را در UFW ببندید. این یک حفره واقعی است.certbot renew یا تنظیمات پنل را بررسی کنید).sudo apt update && sudo apt upgrade؛ پس از بهروزرسانی هسته، سرور را راهاندازی مجدد کنید.