هذا دليل تثبيت Arcivéo Security Monitor وإعداده وصيانته. الأقسام مقسّمة إلى: نظرة عامة، ونشر لوحة التحكم، وربط أدوات الأمان، والوحدات المدمجة والتشخيص. يمكن نسخ الأوامر بالزر على اليمين.
تثبيت اللوحة موضّح في صفحات منفصلة خطوة بخطوة. اختر الطريقة:
Arcivéo Security Monitor — لوحة أمان السيرفر. يجمع البيانات من الأدوات المثبتة (Fail2ban وUFW وLynis وModSecurity وAIDE وClamAV وAuditd وCrowdSec وSuricata وFalco وغيرها) ويعرضها في واجهة موحدة تضم لوحة معلومات وخريطة هجمات وصفحات تفصيلية لكل أداة.
المونيتور ليس أداة حماية فعّالة — فهو لا يحجب الهجمات بنفسه. مهمته تجميع المعلومات من الأدوات العاملة بالفعل وعرضها بشكل مريح.
يعمل المونيتور محليًا فقط — يجب تثبيته على نفس السيرفر الذي يراقبه. لا يوجد أي SSH أو API عن بُعد.
تُنفّذ لوحة التحكم جميع الأوامر (fail2ban-client، ufw status، ipset list وغيرها) باسم مستخدم سيرفر الويب (عادةً www-data، وفي لوحات الاستضافة حساب الموقع) بـمجموعة صلاحيات محدودة من sudo — على أدوات محددة فقط، دون وصول root عام. تُحلَّل النتائج وتُعرَض في المتصفح.
إيقاعان في العمل. صفحات اللوحة تسأل الأدوات لحظة فتحها — لذلك ترى دائمًا الحالة الراهنة. وإلى جانب ذلك تعمل في الخلفية مهام مجدولة (cron):
القائمة الكاملة للمهام في قسم «جميع مهام cron في مكان واحد».
تبدأ الدرجة من القيمة القصوى وتنخفض عند كل مشكلة يتم اكتشافها:
PermitRootLogin yes) — −20PasswordAuthentication yes) — −10X11Forwarding مفعّل، أو MaxAuthTries أكبر من 3، أو الملف 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 الرسائل التي تتجاوز 2000 حرف، ولذلك يُقتطَع النص)؛text وevent وseverity وsource وcount وhost وts — فلا حاجة إلى تحليل نص الرسالة من جديد.التنبيهات الفورية. تصل الرسالة إلى المتصفح مباشرة، وإذا كانت اللوحة مضافة إلى الشاشة الرئيسية للهاتف فستظهر كإشعار تطبيق عادي — دون بوت ودون خادم بريد في المنتصف. «الإعدادات» → التنبيهات الفورية: فعّل المفتاح واضغط «وصل هذا الجهاز» على كل جهاز ينبغي أن يستقبل التنبيهات. ويبيّن عدّاد «الأجهزة المتصلة» كم عددها.
حالة التقرير: «تنبيه» أو «سليم». يصبح العنوان «تنبيه» فقط عند وجود مشكلة فعلية أو إجراء بانتظار التنفيذ: عُثر على تهديد في ClamAV، أو تغييرات ملفات في AIDE، أو أحداث حرجة في Falco (Emergency/Alert/Critical خلال آخر 24 ساعة)، أو خدمة متوقفة في Monit، أو حاجة لإعادة التشغيل، أو قرب انتهاء SSL (≤14 يومًا)، أو تحديثات أمان بانتظار التطبيق. أما الضجيج الخلفي — محاولات 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 = 8 ساعات؛ وبعد هذه المدة من الخمول تطلب اللوحة إعادة الدخول. مثلاً 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/status.php — JSON: تقييم الأمان، وحالة الوحدات، وآخر قياس للحِمل مع أثقل العمليات، وأحداث الأمان خلال 24 ساعة؛/api/metrics.php — الأرقام نفسها بصيغة Prometheus النصية (مقاييس arciveo_*: arciveo_security_score وarciveo_fail2ban_banned وarciveo_cpu_busy_pct وغيرها).وإن كان عميلك لا يستطيع ضبط ترويسة، فالرمز مقبول أيضًا كمعامل — ?token=…. ولاحظ أنه بهذه الصيغة ينتهي به المطاف في سجل وصول خادم الويب، ولذلك فالترويسة أفضل.
Prometheus. كتلة جاهزة لـ scrape_configs:
api disabled — الواجهة البرمجية معطّلة في الإعدادات. وتُكتَب الطلبات المرفوضة في سجل التطبيق مع عنوان IP للمرسِل، فتظهر محاولات تخمين الرمز في صفحة «سجلات التطبيق».
تُثبَّت اللوحة على كل خادم على حدة، وهي تجيب جيدًا عن سؤال «كيف حال هذا الجهاز». أما سؤال «كيف حال أجهزتي كلها» فلا تجيب عنه — ولهذا تستطيع كل لوحة أن ترسل ملخصًا قصيرًا إلى الحساب الشخصي، حيث تظهر الخوادم في قائمة واحدة.
ما تأخذه من الحساب الشخصي my.arciveo.com ← قسم «خوادمي»: يُصدَر هناك رمز (بالشكل fk_…) ويُذكَر عنوان المستقبِل https://my.arciveo.com/api/fleet.php. والرمز واحد لكل حساب — هو نفسه لجميع خوادمك.
ما تضبطه في اللوحة — «الإعدادات» ← «ملخص الخوادم»: عنوان المستقبِل، والرمز، واسم الخادم (كما سيظهر في القائمة؛ وإن تركته فارغًا أُخِذ نطاق اللوحة)، ومفتاح «إرسال الملخص». وزر «أرسل الآن» يتحقق من الاتصال في الحال دون انتظار الجدولة.
وبعد ذلك يذهب الملخص عبر cron كل 15 دقيقة:
ما الذي يُرسَل بالضبط: اسم الخادم ونطاقه، ونظام التشغيل، ومدة التشغيل، وإصدار PHP؛ وتقييم الأمان؛ وحالة الوحدات (UFW، وعدد سجون Fail2ban، وعمليات الحظر اليوم، وهل تعمل CrowdSec وSuricata وFalco، وتهديدات ClamAV، وتغيّرات AIDE، ومؤشر Lynis، والتحديثات المنتظِرة، وهل تلزم إعادة تشغيل، وكم يومًا بقي على انتهاء الشهادة، وعدد المنافذ المفتوحة الخطرة)؛ وآخر قياس للحِمل (load والمعالج والذاكرة والقرص وinodes)؛ وعدّادات الأحداث خلال 24 ساعة وآخر حدث حرج. وليس في الملخص سجلات ولا كلمات مرور ولا محتويات ملفات.
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 — في cron الخاص بـ root (sudo crontab -e): يُحمَّل level 1 (أكثر من 100 ألف IP) إلى المجموعة ipsum التي تُحظر على جدار الحماية (التفاصيل في قسم «قائمة الحظر IPset»):
ipsum — فهي التي تقرأها لوحة التحكم (بطاقة «IPset ipsum»). المستويات: levels/1.txt — أوسع تغطية، levels/3.txt — أدق (3 مصادر أو أكثر).
لماذا يُقسَّم «مراقب الأمان» إلى منطقتين. تعمل الحماية على مستويين، ولوحة التحكم لا تخلط بينهما:
sshd وapache-* وnginx-* وغيرها) والمعاودون الخطرون (jail recidive — من سبق حظرهم عدة مرات). هذه عناوين IP اقتحمتك فعلًا — وهي على خريطة الهجمات و«الخط الزمني».ipset ipsum، تُحظر على جدار الحماية بقاعدة DROP. معظم هذه العناوين لم تمسّ سيرفرك أصلًا — تُقطع مسبقًا؛ ويُظهر عدّاد «IPset ipsum» كم عنوانًا قُطع وقائيًا.الفرق بسيط: التفاعلي — «هؤلاء هاجموا وحُظروا»، والوقائي — «هؤلاء حُظروا قبل المحاولة». سابقًا كان list-3 ipsum يُحشر في recidive بشكل مصطنع (ومن هنا جاء التقسيم القديم «recidive القائمة»)؛ أما الآن فـ recidive للمعاودين الحقيقيين فقط، والوقائي كله على جدار الحماية.
ipsum — قائمة عامة بعناوين IP الخبيثة تُحدَّث يوميًا. يعرض المونيتور عدد العناوين المحمّلة على لوحة المعلومات وخريطة الهجمات ويأخذه بالحسبان في تقييم الأمان (−10 إذا لم تُحمَّل المجموعة).
الخيار الأدنى بدون fail2ban — مجموعة ipsum منفصلة مع الحظر عبر iptables:
@reboot. وبالمناسبة، الأمر create … -exist يضبط الحد maxelem 300000 (الافتراضي 65536 — لا تتّسع له level 1 وسيظهر «Hash is full»):
ipsum، وإذا كان المثبِّت هو من يدير جدار الحماية (VPS جديد — الملفان «الكامل»/«المخفّف»)، فإنه يربط المجموعة بـ UFW عبر قاعدة DROP — فيُحظر فعليًا المرور من هذه العناوين. تأتي القاعدة بعد ESTABLISHED,RELATED، لذا لا تنقطع الاتصالات الحالية (بما فيها SSH الخاص بك) — تُقطع فقط الاتصالات الجديدة من القائمة. تُستعاد المجموعة عند تحميل الخدمة ipsum-load.service قبل جدار الحماية (وإلا لما عمل UFW)، وتُحدَّث بالكرون الساعة 04:00. على سيرفر مُعدّ مسبقًا (لوحة تحكم، جدار حماية خاص) لا يتدخل المثبِّت في جدار الحماية — هناك يبقى ipsum قائمةً للوحة المعلومات وخريطة الهجمات، وتُضاف قاعدة DROP يدويًا عند الرغبة (الخيار الأدنى مع iptables … --match-set ipsum … -j DROP — أعلاه). عند التثبيت التلقائي لا حاجة لفعل أي شيء يدويًا.
بديل حديث لـ Fail2ban مع threat intelligence جماعي: حظر من المجتمع بالإضافة إلى قواعدك الخاصة. يتطلب 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... لمدة 5–15 دقيقة — وهذا طبيعي (تجزئة نظام الملفات كاملاً، حِمل على القرص). لا تقاطعه بـ 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 نحو 8 ملايين توقيع في الذاكرة خلال 30–60 ثانية. انتظر وتحقق: 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 بصلاحية 750 على المجلد، ولا يستطيع سيرفر الويب (www-data) قراءته. افتح المجلد للمرور — تبقى الملفات بداخله محمية:
يعترض استدعاءات النظام عبر eBPF/kernel module ويكتشف الحالات الشاذة في الوقت الفعلي: تشغيل shell من nginx، قراءة عملية الويب لـ /etc/passwd، الكتابة في /bin وما إلى ذلك.
journalctl -u falco (دون sudo — عبر مجموعة systemd-journal). تأكد من أن www-data ضمن هذه المجموعة — راجع «إعداد sudo» (البند 2) في صفحة التثبيت اليدوي.
/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. يجب تفعيل واجهة HTTP في /etc/monit/monitrc (كتلة set httpd مع allow localhost)، وإلا فسيُرجع monit status خطأً.
set httpd في monitrc معلّق (يأتي افتراضيًا هكذا: # set httpd port 2812 …). أزِل التعليق عن الكتلة واسمح لـ localhost. (2) تفعيل httpd وحده لا يراقب شيئًا — إذ لا يحسب Monit سوى ما يُوصف بكتل check؛ وبدونها تبقى القائمة فارغة حتى مع عمل الواجهة. أدنى إعداد فعّال:
conf.d جاهزًا مع httpd على المنفذ 2812 ومجموعة من الفحوصات — لا حاجة للإعداد اليدوي على تثبيت جديد.
PSAD يحلّل سجل iptables ويكشف فحص المنافذ والهجمات الشبكية، ويسند لكل مصدر مستوى خطورة (1–5). يكمّل 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 (المتصفحات وعملاء التورنت وما شابه). عند وجود مثل هذه الملفات، تصبح بطاقة «عدد الملفات التعريفية المحمّلة» كهرمانية وتعرض عددها — مثلًا unconfined: 90 مع 120 محمّلًا و26 في enforce. الحماية الفعلية تأتي فقط من الملفات في وضع enforce؛ أما على Ubuntu 22.04 (AppArmor 3.x) فلا يوجد هذا الوضع وتتطابق الأرقام دائمًا.
unconfined إلى enforce يجب أن يتم بوعي فقط: فهي معطّلة ليس عن خطأ، بل لأن تفعيلها يعطّل عمل البرامج نفسها. أما الملفات في وضع complain فأمرها مختلف: قواعدها مكتوبة بالفعل ولكنها غير مطبَّقة فحسب.
debsums يتحقق من أن ملفات الحزم المثبّتة تطابق المجاميع الاختبارية من المستودع — يكشف الملفات الثنائية النظامية المستبدلة (يكمّل AIDE). يستغرق الفحص الكامل 1–2 دقيقة، لذا يُشغَّل عبر cron، وتقرأ اللوحة النتيجة من data/debsums/debsums.log وتصنّفها بنفسها (يهمّ فقط الملفات الثنائية والمكتبات).
المهمة تُضاف إلى كرون الجذر (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»، البند 2)، ولا حاجة إلى sudo. للتحقق من أن كل شيء متاح لمستخدم الويب:
UFW BLOCK — فهي في صفحتَي «جدار الحماية UFW» و«خريطة الهجمات». الكتلة الفارغة مع علامة خضراء = لم تحدث أعطال شبكة خلال اليوم.
تعرض الصفحة المدمجة ثلاثة أشياء:
df)؛ يحمرّ الشريط عند ≥90%؛lsblk)، الحقيقية فقط (loop/snap مخفية)؛smartctl).تعمل المساحة وقائمة الأجهزة فورًا دون إعداد. أما SMART فيتطلب حزمة smartmontools. لا يملك عملية الويب وصولًا مباشرًا إلى أجهزة الأقراص، لذلك تُلتقط بيانات SMART عبر cron إلى الملف data/disk/smart.txt، وتقرأه لوحة التحكم.
المهمة تُضاف إلى كرون الجذر (sudo crontab -e). يوضع الغلاف الجاهز smart-scan.sh في /usr/local/bin/ (chmod +x؛ راجع ملخص مهام cron) ويكتب بنفسه في data/disk/ الخاص باللوحة.
يجد الغلاف smart-scan.sh بنفسه مجلد data/ الخاص باللوحة — لا حاجة لكتابة المسار. وفي الداخل يستبعد lsblk -e7,11 أقراص loop/cdrom.
تعرض الصفحة سِجل حِمل السيرفر خلال آخر 24 ساعة — Load Average، انشغال CPU وانتظار I/O، وRAM/Swap، وحركة الشبكة (استقبال/إرسال)، وI/O القرص (قراءة/كتابة)، وامتلاء القرص وinodes، وواصفات الملفات المفتوحة واتصالات MySQL، إضافةً إلى العدد الحالي لاتصالات TCP والعمليات. والنافذة الافتراضية 24 ساعة: تنقلها الأزرار في الأعلى إلى 7 أيام أو 30 يومًا.
يجمع البيانات cron/collect_metrics.php — كل 5 دقائق يكتب لقطة «خام» واحدة للعدّادات (/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؛ أما النِسب والسرعات فتحسبها الصفحة بنفسها من الفرق بين اللقطتين المتجاورتين (امتلاء القرص/inodes/الواصفات/اتصالات MySQL قيمٌ لحظية، بلا إعادة حساب). لا حاجة إلى Sudo — تُقرأ المصادر دون صلاحيات root.
عمقان للتخزين. تبقى اللقطات «الخام» التي تُؤخذ كل خمس دقائق يومًا واحدًا (زائد ساعة احتياطية، حتى يبقى لأقدم نقطة في الرسم البياني سلفٌ تُحسب منه). ثم تُطوى كل ساعة منتهية في سطر واحد؛ وتُحفَظ هذه السلسلة الساعية 30 يومًا، وهي بالضبط ما تقرأه العروض «7 أيام» و«30 يومًا». وهكذا يكلّف شهر كامل من السجل نحو 720 سطرًا بدل نحو 8600.
الغلاف collect-metrics-all.sh (انظر ملخص مهام cron) يعثر بنفسه على جميع نُسخ اللوحة المثبَّتة على السيرفر ويشغّل cron/collect_metrics.php لكلٍّ منها باسم مالك الموقع.
أثقل العمليات. تحت الرسوم البيانية جدولان يعرض كل منهما خمس عمليات هي الأكثر استهلاكًا للمعالج:
ويصف الجدولان دائمًا آخر 24 ساعة حتى لو كانت الرسوم تعرض شهرًا كاملًا: فلقطة العمليات لا توجد إلا في أسطر الخمس دقائق، وهذه لا تُحفَظ أكثر من يوم.
ps وسكربت PHP الذي يجمع البيانات وسلسلة cron/sudo فوقه) — وإلا لتصدّرت كل لقطة: إذ يُظهر ps لحظة انطلاقه استهلاكًا يقارب 100 % من المعالج. أما مهام cron الأخرى التي تعمل في الدقيقة نفسها فتظهر بالفعل، ولأجلها وُجد الجدول.
تنبيهات الحِمل (قسم «الإعدادات» ← «تنبيهات الحِمل») — عند تجاوز عتبة المعالج أو الذاكرة أو القرص أو inodes ترسل اللوحة إشعارًا عبر كل القنوات المفعّلة (Telegram والبريد الإلكتروني وwebhook والتنبيهات الفورية — القنوات نفسها التي يذهب بها التقرير اليومي؛ ولا حاجة إلى تفعيل شيء إضافي للتنبيهات)، ثم إشعارًا آخر عندما يعود المؤشر إلى وضعه الطبيعي. وما دامت العتبة متجاوَزة فلن يتكرر الإزعاج: لا يصل الإشعار التالي إلا بعد دورة «عاد إلى الطبيعي ← تجاوز العتبة من جديد».
collect_metrics.php نفسه عند كل تشغيل (كل 5 دقائق) — لا حاجة إلى cron منفصل. تُحفظ حالة «تم التنبيه / لم يتم بعد» في data/alerts_state.json، والعتبات في إعدادات اللوحة.
يجيب التقرير اليومي عن سؤال «كيف حال الخادم». أما المستشعر فيجيب عن سؤال آخر — «ماذا حدث للتو». فكل 5 دقائق يسأل المصادر السريعة ولا يسجّل إلا ما تغيّر منذ الفحص السابق؛ وصفحة «أحداث الأمان» في القائمة تعرض ما عُثر عليه.
ولا يمسّ المستشعر الفحوص البطيئة — Lynis وdebsums وتحديثات الحزم ومدة شهادة SSL: فأرقامها تتغير مرة واحدة يوميًا على أي حال، وتبقى من شأن التقرير اليومي.
ما الذي يلاحظه — تسعة مصادر:
[Priority: 1] ترفع الأمر إلى مستوى حرج؛FOUND جديدة في سجل الفحص؛root (حرج)، ودخول من عنوان لم يُرَ من قبل (تحذير)؛أما الأداة غير المثبَّتة، أو التي لا تستطيع اللوحة قراءة سجلها، فتبقى صامتة ببساطة — وهذا ليس خطأً ولا حدثًا.
data/secwatch_state.json)، والتشغيل الأول يكتب هذه العلامة فحسب. وإلا لجاءك عند تفعيل المراقبة إشعار بكل ما تراكم في السجلات على مدى أشهر.
الضبط — «الإعدادات» ← «مراقبة الأحداث»:
23-7 لا تُرسَل خلالها التحذيرات.وتذهب الإشعارات عبر القنوات نفسها التي يذهب بها التقرير اليومي (Telegram والبريد الإلكتروني وwebhook والتنبيهات الفورية) — دون حاجة إلى تفعيل شيء إضافي. وتُكتَب كل النتائج في القائمة بصرف النظر عن إرسال الإشعار من عدمه، وتُحفَظ 90 يومًا.
قائمة الأحداث. المرشِّحات: الفترة (24 ساعة أو 7 أو 30 أو 90 يومًا)، والأهمية، والمصدر؛ وتُعرَض آخر 500 سجل. وزر «افحص الآن» يشغّل الفحص نفسه الذي يشغّله cron — وهو مفيد بعد الضبط مباشرة كي لا تنتظر خمس دقائق؛ كما يذكر السبب حين لا يُرسَل أي إشعار («دون عتبة الأهمية»، «ساعات الهدوء»، «لم تُضبَط أي قناة إشعارات»). والعدّاد الأحمر بجانب عنصر القائمة هو عدد الأحداث الحرجة خلال الـ24 ساعة الأخيرة.
بطاقة العنوان. النقر على سطر في قائمة الأحداث أو في كتلة عناوين مترابطة يفتح كل ما هو معروف عن عنوان واحد: التسلسل الزمني لأحداثه، الدولة، وفي السطر الأول الخلاصة. سطر القائمة يفتح البطاقة عندما يخص الحدث عنوانًا واحدًا بالضبط؛ وإن كانت العناوين عدة، فالروابط هي العناوين داخل السطر. والخلاصات أربع:
تحت التسلسل الزمني كتلة ما جرى على الخادم في الوقت نفسه: أحداث بلا عنوان أصلًا. لا يعرف AIDE من غيّر الملف، ولا يعرف ClamAV من جلب الملف المصاب. تُعرض تلك التي وقعت أثناء نشاط العنوان وخلال ست ساعات بعده. واقتران الدخول بما تلاه هو ما يفرّق بين محاولة ووصول فعلي.
الجدولة. تُضاف المهمة إلى crontab الخاص بـ root (sudo crontab -e) بإزاحة دقيقتين عن جمع القياسات، حتى لا تنطلق المهمتان معًا:
php cron/security_watch.php مباشرة أبدًا. فالغلاف يعثر على كل نسخ اللوحة المثبَّتة على الخادم ويشغّل الفحص باسم مالك الموقع — بصلاحيات sudo نفسها التي تستعملها اللوحة من الويب. أما الاستدعاء المباشر من crontab الخاص بـ root فسينشئ ملف الحالة data/secwatch_state.json مملوكًا لـ root، فيتوقف زر «افحص الآن» في اللوحة عن العمل.
تحلّل صفحة «خادم الويب» سجل الوصول وتبيّن كم كان عدد الطلبات، وأي نسبة منها انتهت بخطأ، ومن أرسلها. فـ ModSecurity يجيب عن سؤال «ما الذي حُجب»، وهذه الصفحة تجيب عن سؤال «ما الذي وصل إلى الموقع أصلًا».
ما الذي يظهر: عدد الطلبات، وRPS، ونسبة الأخطاء، وعدّاد مستقل للرمز 5xx، وحجم ما أُرسِل؛ ورسم بياني للطلبات بحسب الساعات؛ وتوزيع الرموز 2xx/3xx/4xx/5xx؛ والعناوين المتكررة، وعناوين IP المتكررة، والأخطاء المتكررة (الرمز مع المسار)، والعملاء (User-Agent). والفترة: 24 ساعة أو 7 أيام.
المصدر هو سجل الوصول بصيغة 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 أو الذي تخلّف عن خادم ويب متوقف السجلَّ العامل. ويُقرأ آخر جزء من السجل (3 ميغابايت) ويُخزَّن الناتج مؤقتًا 5 دقائق — لذا قد لا تُغطّى الفترة المختارة بالكامل على موقع مزدحم؛ والتغطية الفعلية مكتوبة فوق الرسم البياني.
adm، ومستخدم الويب ليس فيها. ويضيفه مثبّت Arcivéo إلى هذه المجموعة؛ أما بعد التثبيت اليدوي فيحلّ المشكلةَ غلافٌ صغير من root مسموح له بأمر واحد فقط — عرض السجل (وصفحة ModSecurity تعمل بالطريقة نفسها). ويختار الغلاف السجل وفق القواعد نفسها التي تتبعها اللوحة. والأمر يظهر في الصفحة ذاتها، وهو أيضًا هنا. الصقه كاملًا — فهو أمر واحد:
قد يختلف مستخدم الويب عن www-data — تحقّق بأي مستخدم يعمل تجمّع PHP-FPM الخاص بالموقع (ps -o user= -C php-fpm) وضعه في سطر sudoers. وإذا لم يتضمن اسم السجل access ولا requests، فأضف مساره في بداية السطر L=… داخل الغلاف.
محاولات استغلال ثغرات معروفة. تطابق اللوحة طلبات السجل مع تواقيع نحو عشرين استغلالًا شائعًا: 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. تؤخذ المواقع من العنوان الذي تُفتح به اللوحة ومن ملفات المضيفين الافتراضيين إن استطاعت اللوحة قراءتها. تُحدَّث النتيجة كل 10 دقائق.
إذا نقص شيء يظهر أمر واحد أسفل الجدول. ينشئ ملفًا منفصلًا هو 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) — فهذه ثغرة مباشرة (−10 من تقييم الأمان). المصدر: ss -tuln.
127.0.0.1 (bind-address في إعداد MySQL/PostgreSQL، وbind 127.0.0.1 في Redis) أو أغلق المنفذ في UFW.
127.0.0.1 (loopback) مرئية للسيرفر نفسه فقط — لا يمكن الوصول إليها من الخارج حتى لو كان المنفذ «مفتوحًا». لذلك فإن Postfix على المنفذ 25 المرتبط بـ 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.
تحديثات الأمان — عدد الرقع الأمنية التي تنتظر التثبيت وما إذا كانت هناك حاجة لإعادة التشغيل بعد تحديث النواة (−5 من تقييم الأمان عند وجود رقع). المصدر: /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 (الخطوة 1) وإصدار الشهادة (الخطوة 5). أما site2 فهو مجرد اسم مختصر للموقع: به سُمّي المجلد /var/www/site2 وملف الإعدادات site2.conf. ولا علاقة له بالنطاق، إذ يأخذ Apache العنوان من ServerName فقط؛ والاسم يمكن أن يكون أي شيء — مثلاً مع shop.mycompany.com من المريح اختيار shop: المجلد /var/www/shop، والإعدادات shop.conf.
1. DNS. في لوحة DNS لدى مُسجِّل النطاق أنشئ سجل A يشير إلى عنوان IP لهذا السيرفر:
بعد بضع دقائق تحقق: يجب أن يُعيد dig +short site2.example.com عنوان IP للسيرفر.
2. مجلد الموقع.
3. الـ vhost. يُلصق المقطع في الطرفية كاملاً — ويُحدَّد مسار مقبس PHP-FPM تلقائياً:
4. فعِّل الموقع وتحقق من الإعدادات قبل إعادة التحميل:
5. SSL. certbot مثبَّت مسبقاً بواسطة الإعداد التلقائي؛ وفي هذه المرحلة يجب أن يشير DNS إلى السيرفر:
يُضاف النطاق الثالث وما بعده بالطريقة نفسها — كرِّر الخطوات 1–5 مع تغيير النطاق والمجلد.
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.
ملخص المهام موجود في cron الخاص بـ root للسيرفر (تُضاف عبر sudo crontab -e). أبقِ فقط أسطر الأدوات التي تستخدمها؛ وعدّل المسارات لتناسب سيرفرك.
sudo crontab -l وأن خدمة cron فعّالة.
TIMEZONE من config.php. الثابت TIMEZONE يؤثّر على PHP فقط (كيف تعرض اللوحة التواريخ)، لكن خادم cron يُشغّل المهام حسب توقيت نظام التشغيل. إن لم تتطابق منطقة السيرفر مع منطقتك، سيصلك تقرير «08:00» في وقت مختلف. مثال: السيرفر في منطقة أخرى (Europe/Berlin، UTC+2)، وأنت في الرياض (UTC+3) → سيصلك تقرير «08: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) — فحص 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 يُنشئه أولًا cron الخاص بـ root — فيصبح ملكًا لـ root، ولن يتمكن تبويب «سجل cron» في اللوحة من قراءته أو تفريغه. أنشئ الملف مسبقًا باسم مستخدم الويب (مالك دليل الموقع؛ في HestiaCP هو الحساب، مثلًا admin) — عندئذٍ سيكتفي cron الخاص بـ root بالإلحاق دون تغيير المالك:
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) عن بقية ملفات الموقع، فلن يتمكن سيرفر الويب من قراءته. قارن المالك والصلاحيات مع ملف مجاور ووحّدهما:
يكتشف المونيتور وجود الأدوات عبر 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 بمجلد الدومين، لذا تُحظر دوال 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.
يتصل المونيتور بـ MySQL بمستخدم من config.php لا يملك سوى صلاحية الوصول إلى قاعدته. تُظهر MySQL في information_schema القواعد ذات الصلاحيات فقط — لذلك لا تظهر البقية.
لكي يرى المونيتور كل قواعد البيانات، امنح هذا المستخدم صلاحية القراءة فقط (مرة واحدة من root؛ ضع اسم المستخدم من config.php):
sudo mysql: تُجلب قائمة القواعد عبر اتصال PDO الخاص بها.
يتطلب PostgreSQL صلاحية على مستوى المستخدم postgres، وهي غير متوفرة لمستخدم الويب في اللوحة. فتح sudo psql واسع من PHP غير آمن — بدلاً من ذلك تستدعي اللوحة غلافًا ضيقًا بلا معاملات يطبع فقط الإصدار وعدد الاتصالات وقائمة قواعد البيانات مع أحجامها. أنشئه:
monitor-pgstat من sudoers (الخطوة 13 من التثبيت اليدوي) ولا تنشئ السكربت نفسه: ستبقى بطاقة PostgreSQL غير نشطة فقط.
تُظهر لوحة التحكم ما يحدث؛ وفيما يلي ما يجب فعله في الحالات النمطية. المبدأ العام: لا تُصب بالذعر، قارن الأمر بالنشاط المشروع (أفعالك، التحديثات، النسخ الاحتياطية)، وتعامل معه حسب خطورته.
ignoreip./etc، خارج /usr/share) — احتمال تلاعب. تحقق من الحزمة: debsums PACKAGE_NAME، وعند الشك أعِد تثبيتها (apt install --reinstall).127.0.0.1 أو أغلق المنفذ في UFW. هذه ثغرة حقيقية.certbot renew أو الإعدادات في لوحة التحكم).sudo apt update && sudo apt upgrade؛ وبعد تحديث النواة أعِد تشغيل السيرفر.