
منصة SIEM وEDR وSOAR مفتوحة المصدر، ذاتية الاستضافة، مدعومة بالذكاء الاصطناعي لعمليات الأمن الحديثة.
حزمة أمان ذاتية الاستضافة للفرق الصغيرة/المتوسطة التي لا تملك مركز عمليات أمنيًا (SOC) مخصصًا. ضع وكيلًا على كل نقطة نهاية، ووجّهها إلى الخادم، وستحصل على سجلات SIEM، وسلامة الملفات، وثغرات الحزم، ومستكشف سجلات مدعوم بـ OpenSearch، وفرز ذكاء اصطناعي مستقل، ومحرك قوائم تشغيل SOAR، كل ذلك في أمر واحد docker compose up.
جزء "الذكاء الاصطناعي" هو نموذج Ollama يعمل محليًا (الافتراضي llama3.2:3b). السجلات لا تغادر الجهاز أبدًا؛ لا يوجد مفتاح OpenAI، ولا مفتاح Anthropic، ولا اتصال خارجي. إذا أردت نموذجًا أذكى وكان لديك ذاكرة وصول عشوائي كافية، فاستبدله في .env.

يجمع بيانات القياس عن بُعد من وكلاء ويندوز ولينكس عبر قناة TCP واحدة. أحداث SIEM، والتنبيهات، وFIM، والحزم، واتصالات الشبكة، والمنافذ المفتوحة، ونشاط Docker، ولقطات الشاشة.
يكتشف باستخدام قواعد Sigma، على نقطة النهاية. 23 قاعدة تغطي 23 تقنية من MITRE ATT&CK مرفقة في conf/sigma/builtin/؛ ضع مجموعات قواعد المجتمع بجانبها. تطابق Sigma الحقول المسماة بدلاً من النص، لذا لا يمكن هزيمة Image|endswith: '\vssadmin.exe' بظهور كلمة "vssadmin" في رسالة غير ذات صلة — وCommandLine|utf16le|base64offset|contains يقرأ داخل حمولة -EncodedCommand المشفرة base64، حيث يُظهر سطر الأوامر النصي الغلاف فقط. مُقاس على مجموعة التقييم: 9 من 10 هجمات يكتشفها Sigma وحده، و0 من 9 سلبيات صعبة يتم الإبلاغ عنها خطأً. هذه الطبقة حتمية وتستمر في العمل عندما يكون النموذج غير متاح.
يربط بين الأحداث عبر الزمن، وهو ما لا يمكن لأي قاعدة لكل حدث منفرد أن تفعله. تسجيل دخول فاشل واحد أمر روتيني؛ خمسة حسابات تفشل من مصدر واحد خلال أربعين ثانية هو هجوم رش كلمات مرور، والنظر إلى أي من تلك الأحداث الخمسة لن يخبرك بذلك أبدًا. يغطي الرش، والهجمات بالقوة الغاشمة، والنجاح الذي يصل بعد فشل متكرر، واندفاعات إنشاء الحسابات أو تثبيت الخدمات — على كلا النظامين، من معرفات أحداث ويندوز أو من أسطر auth.log المحللة.
يعمل من نقطتي مراقبة، لأنهما ترى هجمات مختلفة. على المضيف في الوكيل، حيث يكون الهجوم ضد جهاز واحد مرئيًا بالكامل. وعبر المضيفين في مسار الاستيعاب، حيث يظهر الرش الذي سار فشلًا واحدًا في كل مرة عبر خمسين جهازًا — لا يرى أي وكيل منفرد أكثر من حدث واحد، وهذا هو الهجوم الأكثر كفاءة، لأن الرش الواسع والضحل يبقى تحت عتبات قفل الحساب وعتبات المضيف معًا.
التغطية الإجمالية مع Sigma: 27 تقنية. كل نافذة تُطلق مرة واحدة بدلاً من مرة لكل حدث، وكل عداد محدود — العداد المرتبط باسم مستخدم يقدمه المهاجم هو بدائية استنزاف ذاكرة، وليس كشفًا.
يربط الاكتشافات بـ MITRE ATT&CK، من القواعد نفسها. تحمل القواعد tags: attack.t1490، لذا لا يوجد جدول تعيين يُحفظ يدويًا ليصبح قديمًا. تفصل صفحة التغطية ثلاث حالات كانت "نسبة التغطية" الواحدة ستخفيها: مغطاة ومشاهدة، ومغطاة وهادئة، وغير مغطاة إطلاقًا — والأخيرة هي الوحيدة التي لا يعني فيها صمت لوحة التحكم شيئًا.
يفرز كل حدث باستخدام LLM محلي. تعمل ثلاث عمليات بالتوازي: واحدة تراقب كل حدث وارد في الوقت الفعلي، وواحدة تدير فحوصات عميقة يقودها المشغل، وواحدة تقرر ما إذا كانت ستتخذ إجراءً دفاعيًا (BLOCK_IP، ISOLATE_HOST، KILL_PROCESS، إلخ).
وضع الظل للعملية الدفاعية. فعّل AI_SHADOW_MODE=1 وسيتم وضع كل قرار مستقل في مرحلة موافقة بشرية في مركز SOAR بدلاً من تنفيذه. مفيد لضبط النموذج على حركة المرور الحقيقية قبل السماح له بالتصرف بمفرده.
يفهرس كل شيء في OpenSearch حتى تتمكن من البحث في أسطولك باستعلامات غامضة / دقيقة / تبدأ بـ من مكان واحد.
يشغّل قوائم تشغيل SOAR المبنية في محرر مرئي صغير مع تتبع نتائج متعدد الخطوات لكل عقدة، ويمكن تشغيلها يدويًا أو بقرار من الذكاء الاصطناعي.
يفحص الثغرات في الحزم المثبتة لكل وكيل مقابل OSV (عبر الإنترنت أو عبر مرآة داخلية).
يسحب خلاصات استخبارات التهديدات من abuse.ch (Feodo، ThreatFox، URLhaus) إلى جدول مؤشرات محلي، مع تقليم البيانات القديمة ومفتاح عزل الشبكة.
يتحقق من صحة تكوينات الوكلاء قبل دفعها. تحليل YAML، والشكل البنيوي، وتجميع التعبيرات النمطية — التعبير النمطي غير الصالح هو YAML صالح ويعطل القاعدة التي تحتويه بصمت.
سطح مكتب بعيد مدمج عبر بث JPEG عبر WebSocket، دون الحاجة إلى تثبيت VNC منفصل على نقطة النهاية.
يجمع الشريط الجانبي كل شيء في ثلاثة أقسام: القياس عن بُعد (لوحة التحكم، الوكلاء، التنبيهات، الأصول، FIM، السجلات، الذكاء الاصطناعي)، أتمتة الاستجابة (الإجراءات الدفاعية، قوائم التشغيل، قواعد الأتمتة)، والإدارة.
لكل وكيل مسجّل صفحته الخاصة مع اثنتي عشرة علامة تبويب. تعرض النظرة العامة عدادات الموارد الحية، وأحدث سجلات SIEM، وبيانات الوكيل الوصفية، وملخص التهديدات:

التنبيهات هي كل ما قامت قواعد الارتباط الخاصة بالوكيل نفسه بوضع علامة عليه بالفعل. ملونة حسب الخطورة، وقابلة للتصفية والبحث:

علامة التبويب تحليل الذكاء الاصطناعي هي الجانب الموجه للمشغل من LLM المحلي. الفحوصات اليدوية والآلية تهبط هنا معًا. يحمل كل استنتاج شارة حكم، ودرجة ثقة، ومؤشرات MITRE (عندما يعيدها النموذج)، ومؤشرات الاختراق (IOCs)، وخطوات تالية، وزر عرض المصدر الذي يفتح صف السجل الدقيق الذي نظر إليه الذكاء الاصطناعي:

الأجهزة والبرامج ومقابس الشبكة لكل وكيل. تعرض علامة تبويب الأجهزة كل جهاز PnP، وتعرض البرامج الحزم المثبتة، وتعرض الشبكة كل مقبس TCP/UDP مع العملية المالكة له:


بحث عبر الوكلاء مدعوم بـ OpenSearch. اختر وكيلًا، واختر مجموعة بيانات (أحداث SIEM، تنبيهات الأمان، أحداث العمليات، الشبكة، FIM، سجلات التدقيق)، وابحث. يوجد أيضًا زر لفتح OpenSearch Dashboards (فرع Kibana) للمستخدمين المتقدمين:

كل محاولة تسجيل دخول ضد المنصة نفسها، محلية وLDAP، مع النتيجة وعنوان IP المصدر والطابع الزمني. مفيد عندما يكون شخص ما في مزاج "من سجّل الدخول ومتى":

ستحتاج إلى Docker 24+ مع Compose v2 وPython 3.10+ على المضيف (فقط لخطوة بناء الوكيل لمرة واحدة). تتطلب الحزمة الكاملة حوالي 16 جيجابايت من ذاكرة الوصول العشوائي، انظر متطلبات النظام أدناه.```bash git clone https://github.com/d3vhex/Sentora.git cd Sentora
cp .env.example .env
python scripts/init_secrets.py
cd Sentora ./build_agent.sh # on Linux/macOS/WSL
cd ..
docker compose up --build -d
افتح <http://localhost:8000>. تسجيل الدخول الافتراضي هو `admin` / `admin123`.
غيّره فورًا ضمن **Users & Roles**.
يقوم Ollama بسحب `llama3.2:3b` تلقائيًا عند أول تشغيل. تحقق من ذلك باستخدام:```bash
docker exec sentora-ollama ollama list
نشر وكيل: من صفحة Deploy Agent، انسخ الأمر أحادي السطر لنظام التشغيل الذي تريده. على الجهاز الهدف (قشرة إدارية)، الصقه. يقوم المثبّت بتنزيل الملف الثنائي، ويضع ملف إعداد، ويسجّل الوكيل مع الخادم، ويُسجّله كمهمة مجدولة / وحدة systemd.
| الخدمة | المنفذ | يمكن الوصول إليها من | الغرض |
|---|---|---|---|
app | :8000 | أي مكان | REST API + واجهة React |
ingest | :5001 | أي مكان | جامع سجلات TCP (يرسل الوكيل هنا) |
db | :3307 | localhost | MySQL 8.0 (3306 داخل الشبكة) |
rabbitmq | :5672 / :15672 | localhost | قائمة انتظار المهام + واجهة إدارة |
ollama | :11434 | localhost | بيئة تشغيل LLM محلية |
opensearch | :9200 | localhost | بحث نصي كامل في السجلات |
opensearch-dashboards | :5601 | localhost | مستكشف اختياري بنمط Kibana |
ai-worker-{automation,manual,defensive} | — | عمال تحليل LLM |
فقط app و ingest يستمعان على جميع الواجهات. البقية مرتبطة بـ
BIND_ADDR (الافتراضي 127.0.0.1)، لأن أياً منها لا يتحقق من الهوية في
الإعداد الافتراضي — يعمل OpenSearch مع تعطيل إضافة الأمان الخاصة به و
Dashboards هي عرض غير موثّق لكل سجل تم جمعه. اكشف أحدها بوضعه
خلف نفس الوكيل العكسي والمصادقة مثل app، وليس بتوسيع
BIND_ADDR.
زر "Open Dashboards" في Log Explorer يرتبط بالمنفذ 5601 على اسم مضيف الخادم، لذا يعمل من المضيف نفسه؛ يحتاج المشغّلون عن بُعد إلى ذلك الوكيل العكسي.
| الملف الشخصي | وحدة المعالجة | الذاكرة | القرص | ملاحظات |
|---|---|---|---|---|
| مختبر (≤ 5 وكلاء) | 4 أنوية | 12 GB | 40 GB SSD | llama3.2:3b، كومة OpenSearch عند 1 GB |
| فريق صغير (10–50 وكيلاً) | 8 أنوية | 16 GB | 100 GB SSD | الإعدادات الافتراضية في compose كافية |
| إنتاج (50+ وكيلاً) | 16+ نواة | 32 GB+ | 250 GB+ NVMe | انقل OpenSearch و Ollama إلى مضيفيهما الخاصين |
البصمة في وضع الخمول:
llama3.2:3b): ~3 GB، أكثر أثناء الاستدلالإذا كانت الذاكرة محدودة لديك، بدّل إلى qwen2.5:1.5b أو نموذج Ollama صغير آخر
وقلّص كومة OpenSearch. وحدة معالجة رسومية غير مطلوبة لكن Ollama
سيستخدمها تلقائياً إذا كانت موجودة.
عندما يكون حكم العامل الدفاعي ACT بثقة ≥
AI_AUTO_ACT_CONF (الافتراضي 0.75) والإجراء الموصى به موجود في
القائمة الآمنة أدناه، يضع العامل الإجراء مباشرة في جدول
automations الخاص بالوكيل:```
BLOCK_IP KILL_PROCESS RESTART_SERVICE ISOLATE_HOST
DISABLE_USER QUARANTINE_FILE SUSPEND_PROCESS LOGOFF_USER
CONTAINER_ISOLATE CONTAINER_STOP CONTAINER_KILL
أي شيء خارج تلك القائمة (مثل `RUN_CMD`، `DELETE_FILE`، إلخ.)
يتم تخفيضه إلى رؤية استشارية. يتعين على المشغّل إرساله
يدويًا من مركز SOAR. الإجراءات المُرسلة تلقائيًا تظهر شارة AUTO
حمراء في الواجهة.
لتعطيل الاستقلالية تمامًا، اضبط `AI_AUTO_ACT_CONF=1.0` في `.env`. لتعطيل
المسح الدفاعي الدوري، اضبط `AI_DEFENSIVE_SWEEP_ENABLED=0`.
### وضع الظل
اضبط `AI_SHADOW_MODE=1` في `.env` وسيتوقف العامل الدفاعي عن إطلاق
إجراءات حقيقية. الأحكام التي كانت ستُطلق استجابة مستقلة
تُحفظ بدلًا من ذلك كـ **مقترحات**، مع `source_file = AI_DEFENSIVE_SHADOW`
و`shadow_status = pending`. يراجع المشغّل كل واحد منها من
**مركز SOAR > قائمة الظل** ويقوم إما بـ:
- **الموافقة** > يتم إطلاق إجراء SOAR الحقيقي (`call_agent_soar`) ويتم
وضع علامة `approved` على المقترح (مع الطابع الزمني + اسم المشغّل).
- **الرفض** > يتم وضع علامة `rejected` على المقترح مع ملاحظة اختيارية.
لا يتم اتخاذ أي إجراء.
لا تنتهي صلاحية المقترحات أبدًا؛ لا شيء يقرر نيابة عنك. مفيد للسماح
للنموذج بالعمل على بيانات الإنتاج عن بُعد بينما تبني الثقة في
أحكامه قبل إطلاق `BLOCK_IP` / `ISOLATE_HOST` الحقيقية وما شابه.
---
## ملاحظات أمنية
### المصادقة
تتحقق الواجهة من الهوية عبر جلسة من جانب الخادم: يُصدر تسجيل الدخول رمزًا غير شفاف
في ملف تعريف ارتباط `HttpOnly`، و`userdb.sessions` هو المرجع الموثوق. يتم
تخزين SHA-256 للرمز فقط، لذا فإن تفريغ قاعدة البيانات لا يُنتج شيئًا قابلًا للاستخدام.
تنطبق ساعتان، وكلاهما قابل للتهيئة في `.env`:
| الإعداد | الافتراضي | المعنى |
| :--- | :--- | :--- |
| `SESSION_IDLE_MINUTES` | `60` | تنتهي الجلسة بعد هذه المدة من آخر طلب لها |
| `SESSION_ABSOLUTE_HOURS` | `12` | سقف صارم بغض النظر عن النشاط |
| `SESSION_COOKIE_SECURE` | `0` | اضبطه على `1` بمجرد إنهاء TLS أمام التطبيق |
| `SESSION_COOKIE_SAMESITE` | `Lax` | `Lax` يمنع POST/XHR عبر المواقع الذي يحتاجه CSRF |
يتم إبطال الجلسات فورًا عند تغيير كلمة المرور، أو إعادة تعيين كلمة مرور المسؤول،
أو تغيير الدور، أو حذف الحساب — إزالة المسؤول لوصول شخص ما لم
يعد تترك علامة التبويب المفتوحة لديه تعمل.
كل مسار هو **رفض افتراضيًا**: بدون جلسة صالحة يتم رفض الطلب
قبل تشغيل المعالج. الاستثناءات هي نقطة نهاية تسجيل الدخول، وهيكل
SPA، والأصول الثابتة، ونقاط النهاية الموجهة للعوامل، والتي تتحقق من الهوية
عبر `X-Agent-Key` أو رمز تسجيل بدلًا من ذلك.
لا يزال `X-User-ID` يُرسل من الواجهة الأمامية، لكنه لم يعد هوية — يقوم
الخادم بالتحقق منه مقابل الجلسة ويرفض أي عدم تطابق. نظرًا لأن
المتصفحات لا يمكنها إرفاق ترويسات مخصصة بطلبات عبر المواقع دون فحص مسبق
CORS، فإن اشتراطه على الطلبات التي تغيّر الحالة يدعم `SameSite` كعنصر
تحكم ثانٍ ضد CSRF.
حماية المسارات مُعلنة عبر `@require_permission(...)` ويتم فرضها بواسطة
البرمجيات الوسيطة عبر سجل، لذا فهي تنطبق بغض النظر عن أي جانب من
`@app.route` يقع المُزيّن عليه. يطبع سجل الإقلاع الإحصاء:```
[Auth] Routes: <n> permission-gated, <n> session-only, <n> public.
إذا أبلغ هذا السطر عن 0 permission-gated، فإن RBAC لا يتم تطبيقه — تعامل معه
على أنه انقطاع.
يجب أن يكون كل مسار واحدًا من ثلاثة أشياء: مقيدًا بالأذونات، أو مدرجًا في
_PUBLIC_HANDLERS، أو مذكورًا في SESSION_ONLY_HANDLERS في
tests/test_auth_wiring.py مع تعليق يوضح لماذا الجلسة وحدها كافية. يتحقق اختبار من ذلك،
لذا لا يمكن لمسار جديد أن يصل دون حوكمة بهدوء —
وهكذا انتهى الأمر بـ run_playbook وdelete_soar_action وtest_ldap_connection
ليكون قابلاً للوصول من قبل أي حساب يمكنه تسجيل الدخول.
خمس محاولات فاشلة لحساب واحد، أو عشرون من عنوان واحد، خلال
خمس عشرة دقيقة، ويتم رفض المحاولات الإضافية برمز 429 حتى تمر النافذة.
يتم العد من login_logs، الذي كان يسجل بالفعل كل فشل
ولم يقرأه أحد — كان bcrypt هو الفرامل الوحيدة على التخمين عبر الإنترنت.
| الإعداد | الافتراضي | المعنى |
|---|---|---|
LOGIN_MAX_FAILURES_USER | 5 | حالات الفشل المسموح بها لكل حساب في النافذة |
LOGIN_MAX_FAILURES_IP | 20 | حالات الفشل لكل عنوان؛ أعلى، لأن مكتبًا يشارك عنوان NAT واحدًا |
LOGIN_LOCKOUT_WINDOW_MIN | 15 | إلى أي مدى في الماضي تُحسب حالات الفشل |
يتم الفحص قبل مقارنة كلمة المرور، لذا فهو يزيل أيضًا فرق التوقيت
بين اسم مستخدم معروف وآخر غير معروف. يفشل بشكل مفتوح إذا كان
login_logs غير قابل للوصول: صفحة تسجيل دخول لا يمكن الوصول إليها لأن
جدول التدقيق معطل هي انقطاع بحد ذاتها.
يتم تكريم X-Forwarded-For فقط من نظير مدرج في TRUSTED_PROXIES
(عناوين مفصولة بفواصل أو CIDRs، فارغة افتراضيًا). مع عدم وجود شيء أمام
التطبيق، يكون الرأس مزودًا من قبل المهاجم، لذا فإن تصديقه دون قيد أو شرط —
وهو ما حل هذا محلّه — سمح للمتصل بكتابة أي عنوان في سجل التدقيق
وإعادة تعيين حد المعدل الخاص به في نفس الطلب.```
TRUSTED_PROXIES=10.0.0.0/8,192.168.1.5
اتركه فارغًا عندما يتم الوصول إلى التطبيق مباشرة.
### واجهة برمجة التطبيقات الخاصة بالوكيل
يستمع الوكيل على `0.0.0.0:9099` ويعمل بصلاحيات SYSTEM أو root. يتطلب كل مسار
`X-Agent-Key`؛ ويتطلب `/self_destruct` مفتاح التسجيل الخاص بهذا الوكيل تحديدًا،
حتى لا يتمكن سرّ مشترك على مستوى الأسطول من إلغاء تثبيت كل
نقطة نهاية دفعة واحدة. يجيب `/health` عن حالة التشغيل بدون مفتاح ولا يكشف
أي شيء آخر بدونه.
لا يوجد أي تراجع متساهل. كان إصدار سابق يقبل أي مفتاح غير فارغ
عندما يكون `AGENT_MASTER_SECRET` غير مضبوط على المضيف — وهو ما لم يُضبط أبدًا،
لذا كان هو الافتراضي في كل مكان. نظام EDR يفشل بشكل مفتوح أسوأ من عدم وجود EDR،
لأن لوحة التحكم تُبلغ أن نقطة النهاية محمية.
`AGENT_BIND` ينقل المستمع. لا يزال `0.0.0.0` افتراضيًا لأن
الخادم يصل إلى الوكلاء عبر HTTP على هذا المنفذ؛ الربط بالحلقة المحلية يتطلب
نقلًا بديلًا، وليس تغيير إعدادات.
### CORS
`CORS_ORIGINS` افتراضيًا فارغ. في النشر العادي يقدم هذا التطبيق
SPA بنفسه، لذا تكون الطلبات من نفس الأصل ولا حاجة لأي إدخال. يتم رفض
البدل الشامل outright: ترفض المتصفحات `Access-Control-Allow-Origin: *` على أي
طلب يحمل ملفات تعريف ارتباط. يجب على عمليات النشر ذات الأصول المنقسمة سرد أصول
صريحة وتعيين `SESSION_COOKIE_SAMESITE=None` مع `SESSION_COOKIE_SECURE=1`.
### الأسرار الافتراضية
يأتي `.env.example` مع قيم نائبة. ملف `.env` الحقيقي مستثنى من git.
قم بتدوير هذه قبل تعريض المنصة لأي شيء يتجاوز `localhost`:
- `DB_PASSWORD`
- `AGENT_SHARED_SECRET` (تراجع مصادقة الوكيل). يتم توليده تلقائيًا عند أول
تشغيل إذا كان غير مضبوط.
لم يعد تسجيل الدخول `admin / admin123` بحاجة للتذكر: يتم إنشاء الحساب
المُجهز مع `must_change_password`، وطالما تم ضبط ذلك لا يمكن للجلسة الوصول
إلى أي شيء سوى `/change-password`. يتم فرض ذلك في البرمجيات الوسيطة وليس في
الواجهة، لأن علامة يُؤتمن عليها الواجهة الأمامية لاحترامها هي مجرد اقتراح
وواجهة API تستجيب أيضًا لـ curl.
### شهادات TLS
لا يُرفق أي مفتاح خاص. كان يتم إرفاق `certs/server.key` و
`certs/rootCA.key` عاملين سابقًا، مما أعطى كل نشر نفس
هوية TLS ونشرها: أي شخص استنسخ المستودع يومًا ما كان بحوزته
المفتاح، لذا لم تثبت الشهادة شيئًا عن هوية الطرف الآخر.
مع `TLS_ENABLED=1` وعدم وجود شهادة، يولد التطبيق واحدة عند أول
تشغيل. يحصل كل تثبيت على مفتاحه الخاص ولا يغادر المفتاح الجهاز
الذي أنشأه أبدًا. `certs/*.key` و `certs/*.crt` مستثنيان من git.
المرجع المصدق (CA) موقّع ذاتيًا، لذا تحذر المتصفحات ما لم تثق به صراحةً. هذا
التحذير صادق — فضّله على سر مشترك لا يُنتج أي تحذير
على الإطلاق. لأي شيء عام، وجّه `TLS_CERT` / `TLS_KEY` إلى شهادة حقيقية؛
عندما تكون مضبوطة ومفقودة، يوضح التطبيق ذلك بدلًا من استبدالها
بشهادة موقّعة ذاتيًا.
لإعادة التوليد يدويًا:```bash
python certs/generate_certs.py --force
المفاتيح القديمة ما تزال موجودة في تاريخ git. تعامل مع الزوج الذي تم إصداره قبل هذا التغيير على أنه محترق؛ التثبيتات الجديدة لم تعد تستخدمه.
يستخدم الخادم مفتاحي Fernet، وكلاهما يتم توليده تلقائيًا عند أول تشغيل:
| المفتاح | الموقع | يحمي |
|---|---|---|
| مفتاح الوكيل | data/fernet.key (أو FERNET_KEY_PATH) | بيانات الوكيل عن بُعد؛ يُسلَّم عبر /api/agents/bootstrap |
| مفتاح الخادم | .env FERNET_KEY | الحقول الداخلية المخزنة في الخادم (مثل عمود كلمة المرور) |
chmod 600 لكليهما. احتفظ بنسخة احتياطية منهما. فقدان أي منهما يجعل
البيانات المشفرة المقابلة غير قابلة للقراءة. لا يوجد حتى الآن تدوير في المكان.
آليتان مستقلتان، وكلتاهما اختيارية:
إثراء لكل حكم (ai/intel.py). يتحقق عامل الذكاء الاصطناعي من
المؤشرات الموجودة في سجل مقابل AlienVault OTX وVirusTotal. يتطلب
OTX_API_KEY / VT_API_KEY؛ عدم تعيينه يعني عدم إجراء أي استدعاء خارجي على الإطلاق.
خلاصات المؤشرات (core/threat_feeds.py). تملأ جدول threat_intel
كل ساعة من abuse.ch — Feodo Tracker (عناوين C2 للبوت نت)، ThreatFox
(مؤشرات IoCs مختلطة مع درجة ثقة) وURLhaus (عناوين URL الموزعة للبرمجيات الخبيثة).
تحمل المؤشرات last_seen ويتم تقليمها بعد THREAT_INTEL_STALE_DAYS
(الافتراضي 30): العنوان الذي استضاف C2 في الربع الماضي عادة ما ينتمي
لشخص آخر الآن، والاحتفاظ به ينتج نتائج إيجابية خاطئة إلى أجل غير مسمى. كل
خلاصة محدودة بـ THREAT_INTEL_MAX_PER_FEED صفًا لأن الجدول يُقرأ
على مسار التنبيه.
كانت abuse.ch تنقل التنزيلات خلف مفتاح حساب مجاني. خلاصة
تعيد 401/403 توضح ذلك في سجل الخادم؛ اضبط THREAT_INTEL_AUTH_KEY.
تحقق مما وصل فعليًا:```bash docker logs sentora-server | grep ThreatIntel
### وضع العزل (Air-gap mode)```ini
OSV_MODE=mirror
OSV_MIRROR_URL=http://osv.internal
THREAT_INTEL_MODE=off
# or serve the feeds internally:
# THREAT_INTEL_FEODO_URL=http://mirror.internal/feodo.json
مع ضبط هذه الإعدادات، مع ترك OTX_API_KEY / VT_API_KEY غير معيّنة، لا يغادر أي شيء
الشبكة. الخطوط مضمّنة، وOllama محلي، ولا يتم الاتصال بأي CDN.
/api/exposure/report يحسب الحزم غير المصححة وأحداث سلامة الملفات
عبر الأسطول، لكل وكيل، من الأسوأ أولاً. وهو يبلّغ عن تغطيته الخاصة:
complete: false عندما يتعذر قراءة وكيل، لأن الإجمالي الذي يغطي أكثر من نصف
الأسطول ليس إجمالي أسطول.
لا توجد درجة عمداً. كانت نقطة النهاية سابقاً تُرجع
100 - vulns*2 - fim*5 كـ"درجة امتثال" — وهذا لا يطابق أي إطار عمل،
ولا يتدرج مع حجم الأسطول، ويُثبَّت عند الصفر على أي أسطول حقيقي. تصنيف
الخطورة غائب لنفس السبب: vulnerabilities_report لا يحتوي على
عمود خطورة وحقولها مشفّرة عند التخزين، لذا أي تصنيف سيكون
مختلقاً.
POST /<agent>/config/<type> يتحقق قبل وصول أي شيء إلى مستشعر:
تحليل YAML، والشكل البنيوي، و— الطبقة الأهم — تجميع التعبيرات النمطية.
التعبير النمطي غير الصالح هو YAML صالح تماماً ويُعطّل بصمت الفئة
التي تحتويه، لذا فحص بناء الجملة فقط سيدفعه مباشرة إلى نقطة النهاية.
يقوم المحرر بالفحص اللغوي ضد نفس نقطة النهاية أثناء الكتابة و
يُبلّغ عن المشكلات مع أرقام أسطر قابلة للنقر.
Agent (Win / Linux) │ TCP frames + REST polling ▼ ingest (:5001) ──► RabbitMQ ──► AI worker fleet (3 modes) │ │ ▼ ▼ MySQL (per-agent _db) ai_analysis_results │ ▼ app (Sanic :8000) ──► React UI + REST + WebSocket screen proxy
النسخة الأعمق (تخطيط الوحدات، المخطط، خط أنابيب الذكاء الاصطناعي، استقلالية
SOAR، أسطح الفجوة الهوائية) موجودة في
[docs/Sentora_Architecture.md](https://github.com/d3vhex/sentora/blob/HEAD/docs/Sentora_Architecture.md).
الوثائق التشغيلية:
| المستند | يغطي |
| :--- | :--- |
| [البنية](https://github.com/d3vhex/sentora/blob/HEAD/docs/Sentora_Architecture.md) | تخطيط الوحدات، تدفق البيانات، نموذج المصادقة، خط أنابيب الذكاء الاصطناعي |
| [النشر الإنتاجي](https://github.com/d3vhex/sentora/blob/HEAD/docs/production-deployment.md) | تحديد الحجم، طوبولوجيا الشبكة، TLS، النسخ الاحتياطي، المراقبة، الفجوة الهوائية |
| [دليل التحديث](https://github.com/d3vhex/sentora/blob/HEAD/docs/update-runbook.md) | الترقيات، نشر الوكلاء، ترحيل قواعد البيانات، التراجع |
| [تقرير التقدم](https://github.com/d3vhex/sentora/blob/HEAD/docs/PROGRESS_REPORT.md) | ما الذي تغيّر ولماذا |
---
## إعداد التطوير```bash
# 1. Database. Only init_userdb.sql — it creates and selects `userdb`.
#
# db/init.sql is NOT a server-init script. It is the per-agent schema
# template, applied by server.create_tables_if_not_exist() after
# connecting to that agent's own database, which is why it contains no
# CREATE DATABASE or USE. Running it standalone fails at line 5 with
# "No database selected" — the same way it broke every first-time
# `docker compose up` while it was mounted into the MySQL init directory.
mysql -u root -p < db/init_userdb.sql
# 2. Backend. requirements.lock pins every version the image is built
# from; requirements.txt is the loose list it was resolved from.
pip install -r requirements.lock
python app.py
# 3. Ingest (separate terminal)
python server.py
# 4. Frontend dev server
cd frontend
npm install
npm run dev
نفس السكربت، ثلاثة أدوار:```bash WORKER_TYPE=automation python ai_worker.py WORKER_TYPE=manual python ai_worker.py WORKER_TYPE=defensive python ai_worker.py
الإنتاج: دع `docker-compose.yaml` يتولى الأمر.
---
## المساهمة
نرحب بطلبات السحب (PRs). قبل فتح طلب:
1. انسخ (Fork) → أنشئ فرعًا (branch) → قدّم طلب سحب (PR) مقابل `main`.
2. شغّل الفحوصات:```bash
pytest -ra # no MySQL or RabbitMQ needed
python -m compileall -q app.py core security
cd frontend && npx tsc --noEmit && npm run build && cd ..
# With the stack up — enumerates every route and calls it twice
python scripts/api_smoke_test.py
@require_permission(...). سجل الإقلاع
يطبع العدد الإجمالي؛ إذا أبلغ عن 0 permission-gated، فهناك خطأ
في التوصيل، وليس في مسارك.لأي شيء أكبر من إصلاح، افتح مشكلة أولاً حتى نتمكن من التوافق على النهج.
. ├── app.py # Sanic API + React SPA host ├── server.py # TCP ingest ├── ai_worker.py # AI worker fleet (3 modes) ├── ai/ │ ├── utils.py # LLM helpers, AI cache, SOAR queueing │ └── intel.py # OTX / VT per-verdict enrichment (opt-in) ├── core/ │ ├── mq.py # RabbitMQ publisher │ ├── opensearch.py # OpenSearch index/search │ ├── config_validation.py # Agent YAML validation (parse, shape, regex) │ └── threat_feeds.py # abuse.ch indicator feeds ├── security/ │ ├── session.py # Server-side session store │ └── ssrf.py # Proxy destination rules ├── scanners/ │ └── vuln.py # Server-side OSV scanner ├── scripts/ │ ├── init_secrets.py # Generate the secrets .env needs │ ├── rotate_db_password.py # Rotate the MySQL root password safely │ └── api_smoke_test.py # Exercise every route against a live server ├── tests/ # pytest; no MySQL or RabbitMQ required ├── frontend/ # React 18 + TS SPA │ └── src/lib/ # Shared logic (playbook action catalogue) ├── Sentora/ # Cross-platform agent ├── certs/ # Self-signed dev certs ├── docs/ # Architecture + screenshots └── docker-compose.yaml
---
## الترخيص
AGPL-3.0. انظر [LICENSE](https://github.com/d3vhex/sentora/blob/HEAD/LICENSE).
استخدم، عدّل، أعد التوزيع. ما تضيفه AGPL فوق GPL العادي:
إذا قمت بتشغيل نسخة معدّلة على خادم شبكة حيث يتفاعل معها مستخدمون آخرون،
فيجب عليك نشر التعديلات بموجب AGPL أيضًا.
- الاستضافة الذاتية للاستخدام الداخلي ← لا يوجد التزام بالكشف عن المصدر.
- SaaS مواجه للجمهور مبني على Sentora معدّلة ← يجب عليك نشر التعديلات.
- تريد شحن مشتق مغلق المصدر أو تخطي بند الشبكة-الكوبيليفت؟
يتوفر إعفاء ترخيص تجاري. تواصل مع المؤلف.
اسم "Sentora" وشعارها علامتان تجاريتان لمؤلفي المشروع
ولا يشملهما AGPL. انسخ بحرية، لكن أعد التسمية إذا أعدت التوزيع
كمنتج خاص بك.
---
## ما ليس في الإصدار المجتمعي
الإصدار المجتمعي لا يحتوي على أي قيود مصطنعة: لا حد للوكلاء، لا
حد للاحتفاظ، لا حجب للميزات في النواة. شغّله بأقصى ما يسمح به عتادك.
توزيعة Pro / Enterprise المدفوعة تضيف ميزات لاصقة للمؤسسات
(SSO عبر SAML/SCIM، تعدد المستأجرين، تقارير الامتثال، التوفر العالي، تدقيق WORM،
حزم تحديث موقّعة للفجوة الهوائية، موافقات SOAR بأربعة أعين،
موجّهات تذاكر/SIEM متميزة). قدرة الكشف الأساسية لا تُنقل أبدًا
خلف ذلك الجدار.
إذا كان أي من ذلك مهمًا لنشرك،
[تواصل معنا](mailto:[email protected]).