عزل المستأجر
معمارية من 9 طبقات لبنية تحتية مشتركة
ملخص
لا يمكن لعزل المستأجر في بنية تحتية مشتركة أن يرتكز على طبقة واحدة. نوثّق معمارية العزل ذات الطبقات التسع المنشورة على البنية التحتية 0DATA: أمان مستوى الصف في PostgreSQL، وSPINA لكل مستأجر، وNOVA لكل مستأجر، وCockpit لكل نطاق، وALFA لكل مستوى، وتطبيق ويب تقدمي دون اتصال، وخطة المنافذ، وموضوعات NATS المُقسَّمة بمساحات أسماء، وDNS wildcard. تعمل كل طبقة باستقلالية؛ فلا يُضعف تعطّل إحداها الأخريات. وتستلهم هذه المعمارية الوصلات المحكمة في الظهارة البيولوجية، حيث تحافظ كل خلية على غشائها الخاص مع مشاركتها في النسيج المشترك. نصف كل طبقة بالتفصيل، ونعرض خطة المنافذ الموثقة (لا تستمع أي خدمة على 0.0.0.0)، ونورد نتائج اختبار الاختراق عبر المستأجرين — إذ فشلت جميع محاولات القراءة بين المستأجرين.
في جملة واحدة
تضمن تسع طبقات عزل مستقلة ألا يتمكن مستأجر من رؤية بيانات مستأجر آخر أو الوصول إليها أو تعديلها — على أي مستوى من الحزمة.
1. لماذا تسع طبقات
1.1 الدفاع المتعمق ليس استعارة
في الأمن السيبراني الكلاسيكي، يُعد الدفاع المتعمق مبدأً نظريًا. أما في بنية تحتية مشتركة تستضيف عملاء MSP ذوي مصالح متضاربة، فيغدو ضرورة حيوية. قد يستضيف مزوّد الخدمات المُدارة في آنٍ واحد مكتب محاماة وعيادةً ومنافسًا مباشرًا للأول — على الخادم المادي نفسه.
يستند النهج التقليدي لتعدد المستأجرين إلى فصل على مستوى التطبيق: يصفّي التطبيق الاستعلامات وفقًا لـ tenant_id. ويفشل هذا النهج فشلاً ذريعًا عندما يتجاوز خطأ برمجي أو ثغرة حقن أو تصعيد امتيازات هذه الطبقة الوحيدة.
1.2 النموذج البيولوجي: الغشاء الخلوي والوصلات المحكمة
تجسّد الظهارة المعوية البشرية نموذجنا. تمتلك كل خلية غشاءً فوسفوليبيديًا خاصًا بها — وهو الحاجز الأول. وبين الخلايا، تشكّل الوصلات المحكمة (tight junctions) حاجزًا ثانيًا، غير منفذ حتى للجزيئات الصغيرة. أما الحاجز الثالث — الغليكوكاليكس — فيصفّي الجزيئات الكبيرة. لا يكفي أي من هذه الحواجز وحده؛ فتراكبها يخلق إحكامًا يقارب المطلق.
الوصلات المحكمة → يمنع RLS في PostgreSQL أي تسرب على مستوى قاعدة البيانات
الغليكوكاليكس → تشكّل خطة المنافذ وDNS wildcard وNATS المُقسَّم بمساحات الأسماء طبقة ترشيح شبكية
1.3 الطبقات التسع
| الطبقة | الاسم | المجال | الآلية |
|---|---|---|---|
| 1 | PostgreSQL RLS | قاعدة البيانات | سياسات أمان مستوى الصف |
| 2 | مخطط PostgreSQL | قاعدة البيانات | مخطط منطقي لكل مستأجر |
| 3 | سياسات التطبيق | قاعدة البيانات | قيود CHECK ومحفزات |
| 4 | SPINA v2 | التوقيع | HMAC-SHA256 محلي + eIDAS RFC 3161 |
| 5 | NOVA | المراقبة | نسخة لكل مستأجر، ربط 127.0.0.1 |
| 6 | ALFA | القرار | محرك مشترك، ذاكرة معزولة |
| 7 | Cockpit | الواجهة | نطاق خاص، JWT موقّع لكل مستأجر |
| 8 | DNS / NATS | الاتصال | DNS wildcard وموضوعات مُقسَّمة |
| 9 | خطة المنافذ | الشبكة | لا خدمات على 0.0.0.0، منافذ موثقة |
2. الطبقات 1–3: PostgreSQL، الأساس
2.1 أمان مستوى الصف (الطبقة 1)
يُعد أمان مستوى الصف (Row-Level Security) في PostgreSQL أعمق آليات العزل. يحمل كل صف في كل جدول tenant_id. تضمن سياسة RLS المطبقة على كل جدول ألا تتمكن جلسة PostgreSQL المتصلة للمستأجر أ من قراءة صفوف المستأجر ب ماديًا.
تقرأ الدالة current_setting متغير جلسة في PostgreSQL. يضبط هذا المتغير مجمّع الاتصالات لحظة مصادقة المستأجر. لا يمكن لأي استعلام تطبيقي تعديله — فهو للقراءة فقط من جانب التطبيق. وهذه الطبقة منيعة دون وصول مستخدم فائق (superuser) في PostgreSQL.
2.2 مخطط لكل مستأجر (الطبقة 2)
إضافةً إلى RLS، يملك كل مستأجر مخططًا منطقيًا مخصصًا — ليس مخطط PostgreSQL بمعنى CREATE SCHEMA، بل إسقاط بيانات مقيد. تُصفّى العروض المُجسّدة والفهارس الجزئية والتسلسلات وفقًا لـ tenant_id. لا يستطيع المستأجر تعداد المستأجرين الآخرين، لأن جدول tenants نفسه محمي بـ RLS.
تمنع هذه الطبقة هجمات الاستدلال: حتى لو تمكّن مستأجر من قياس زمن تنفيذ استعلام (هجوم توقيت)، تضمن الفهارس الجزئية ألا تُمسح بيانات المستأجرين الآخرين أبدًا.
2.3 القيود والمحفزات (الطبقة 3)
تستخدم طبقة PostgreSQL الثالثة قيود CHECK ومحفزات BEFORE INSERT/UPDATE لمنع كتابة بيانات تنتهك العزل:
يقفل محفز إضافي أي محاولة لتعديل عمود tenant_id بعد الإدراج. وهذا التكرار مقصود: إذا عُطّلت سياسة RLS عن طريق الخطأ (أثناء صيانة مثلاً)، تحافظ القيود والمحفزات على العزل.
3. الطبقات 4–6: SPINA وNOVA وALFA
3.1 SPINA v2 — التوقيع لكل مستأجر (الطبقة 4)
SPINA (بروتوكول التوقيع لسلامة الأصول وعدم إنكارها) هو بروتوكول التوقيع الخاص بـ 0DATA. في الإصدار الثاني، يملك كل مستأجر:
- مفتاح HMAC-SHA256 محليًا، يُولَّد ويُخزَّن في مساحة المستأجر
- شهادة eIDAS RFC 3161 للختم الزمني المؤهل
- مخزن مفاتيح معزولاً، مشفرًا بعبارة مرور مشتقة من سر المستأجر
لا يتشارك مستأجران أي مادة تشفيرية أبدًا. إذا عرّض المستأجر أ مفتاح HMAC الخاص به للخطر، تبقى تواقيع المستأجر ب صالحة. أما الختم الزمني eIDAS فيُدار اتحاديًا على مستوى البنية التحتية، لكن رمز الطابع الزمني يُخزَّن في مخطط المستأجر.
تُنفَّذ عملية التحقق من التوقيع في سياق PostgreSQL الخاص بالمستأجر. تستخدم الدالة spina_verify() صفة SECURITY DEFINER مع SET app.current_tenant_id صريح — ولا يمكنها التسرب خارج المستأجر.
3.2 NOVA — نسخة لكل مستأجر (الطبقة 5)
NOVA هو محرك مراقبة الشبكة. يملك كل مستأجر MSP نسخة NOVA خاصة به، تعمل كعملية مخصصة:
- ربط حصري على
127.0.0.1، بمنفذ مميز لكل مستأجر - قاعدة بيانات مسح محلية (SQLite أو مخطط PostgreSQL معزول)
- لا مشاركة في الذاكرة بين النسخ
- ملف إعدادات مميز (
/opt/nova/tenants/<tenant_id>/config.yaml)
لا يستطيع مستأجر يتحكم في شبكته المحلية (وبالتالي في الأهداف التي يمسحها NOVA) التأثير في نسخة NOVA الخاصة بمستأجر آخر. فالعمليات معزولة على مستوى نظام التشغيل — فإرسال kill -9 إلى معرّف عملية المستأجر أ لا يؤثر على المستأجر ب.
3.3 ALFA — محرك مشترك، ذاكرة معزولة (الطبقة 6)
ALFA (طبقة التحليلات للتقييم الجنائي) هو محرك القرار المشترك. وخلافًا لـ NOVA، يستخدم ALFA محركًا مشتركًا لكفاءة الموارد، لكن مع عزل صارم للذاكرة:
- يُقسَّم كل مستوى تحليل (مستأجر، موقع، جهاز) في حجيرات منفصلة
- تُحمَّل البيانات في أجزاء ذاكرة محكمة الإغلاق
- تُكتب نتائج التحليل في مخطط PostgreSQL الخاص بالمستأجر
- لا يُجرى أي ترابط بين المستأجرين دون موافقة صريحة
يطبق ALFA مبدأ الحاجة إلى المعرفة على المستوى الخوارزمي: لا يستقبل نموذج التحليل المنفَّذ للمستأجر أ سوى بيانات المستأجر أ. أما الإحصاءات المجمعة متعددة المستأجرين (المفيدة لقياس الأداء) فتستخدم بيانات مُجهَّلة الهوية مع خصوصية تفاضلية (ε = 1.0).
4. الطبقات 7–9: Cockpit وDNS وNATS
4.1 Cockpit — نطاق خاص وJWT لكل مستأجر (الطبقة 7)
يصل كل مستأجر إلى واجهة Cockpit عبر نطاق مخصص: client.odata.fr. تُصدَر شهادة SSL (Let's Encrypt) لهذا النطاق. يُوقَّع رمز JWT للمصادقة بمفتاح سري خاص بالمستأجر، ويحوي tenant_id ضمن مطالباته (claims).
يتحقق وسيط nginx من JWT قبل توجيه الطلب. تُرفض محاولة الوصول إلى client-b.odata.fr باستخدام JWT للمستأجر أ على مستوى الوكيل العكسي — قبل أن يصل الطلب إلى واجهة API أصلًا. ويشكّل النطاق نفسه حدودًا للعزل: لا يستطيع مستأجر تخمين النطاق الفرعي لمستأجر آخر (فالأسماء هي UUIDs أو معرّفات مبهمة).
4.2 DNS wildcard وNATS المُقسَّم بمساحات الأسماء (الطبقة 8)
تعمل الطبقة 8 على مستوى الاتصال بين الخدمات:
DNS wildcard. يشير السجل *.odata.fr إلى البنية التحتية. يُحل كل نطاق فرعي، لكن خادم التطبيق يصفّي النطاقات غير المسجلة. لا يستطيع مستأجر إنشاء نطاق فرعي اعتباطي — فسجل DNS خاضع لسيطرة البنية التحتية.
NATS المُقسَّم بمساحات الأسماء. يستخدم ناقل رسائل NATS موضوعات مسبوقة ببادئة المستأجر:
تُضبط قوائم ACL الخاصة بـ NATS بحيث لا تتمكن اعتمادات المستأجر أ من النشر أو الاشتراك سوى في الموضوعات tenant.a1b2c3d4.*. يطبّق خادم NATS هذه القوائم على مستوى البروتوكول — فلا يستطيع أي عميل تجاوز تقسيم مساحات الأسماء.
4.3 خطة المنافذ — لا خدمات على 0.0.0.0 (الطبقة 9)
الطبقة 9 هي الأكثر مادية: خطة المنافذ الموثقة. لا تستمع أي خدمة داخلية على 0.0.0.0. ترتبط كل خدمة بـ 127.0.0.1 بمنفذ صريح. يمنع الجدار الناري (UFW، سياسة الرفض الافتراضي) كل حركة المرور الواردة غير المصرح بها صراحةً. وتُوثَّق هذه الطبقة بالتفصيل في القسم 5.
5. خطة المنافذ الموثقة
يوثق الجدول التالي جميع المنافذ المستمعة في البنية التحتية. يشير عمود الربط (Bind) إلى واجهة الاستماع. لا تستمع أي خدمة على 0.0.0.0، باستثناء المنافذ العامة المعرَّضة عمدًا (HTTP/S وSSH وSIP).
5.1 المنافذ العامة (المعرَّضة)
| المنفذ | البروتوكول | الخدمة | المبرر |
|---|---|---|---|
| 22 | TCP | SSH | وصول إداري |
| 80 | TCP | HTTP (nginx) | إعادة توجيه HTTPS + ACME |
| 443 | TCP/UDP | HTTPS (nginx) | وكيل عكسي، HTTP/3 QUIC |
| 5060 | UDP | SIP (FreeSWITCH) | اتصالات VoIP |
| 5080 | UDP | SIP (FreeSWITCH) | اتصالات VoIP |
5.2 المنافذ الداخلية (ربط 127.0.0.1)
| المنفذ | الخدمة | المستأجر | الدور |
|---|---|---|---|
| 5432 | PostgreSQL | مشترك (RLS) | قاعدة البيانات الرئيسية |
| 6379 | Redis | مشترك (ببادئة) | الذاكرة المؤقتة والجلسات |
| 4222 | NATS | مشترك (بمساحات أسماء) | ناقل الرسائل |
| 5090–5099 | نسخ NOVA | لكل مستأجر | مسح الشبكة |
| 5100–5109 | واجهة NOVA API | لكل مستأجر | واجهة REST لـ NOVA |
| 5110–5119 | عمال SPINA | لكل مستأجر | التوقيع/الختم الزمني |
| 8300 | واجهة API الرئيسية | مشترك (RLS) | واجهة FastAPI |
| 8400–8409 | عمال Cockpit | لكل مستأجر | واجهة الويب Cockpit |
| 9090 | Cockpit النظام | البنية التحتية | إدارة النظام |
5.3 قواعد UFW
تُحجب جميع المنافذ الأخرى على مستوى الجدار الناري. يضيف الربط 127.0.0.1 حاجزًا ثانيًا: حتى لو عُطّل الجدار الناري، لما أمكن الوصول إلى الخدمات الداخلية من الخارج.
6. التحقق — اختبار اختراق عبر المستأجرين
6.1 بروتوكول الاختبار
أُجري اختبار الاختراق عبر المستأجرين في 23 يوليو 2026. أُنشئ مستأجران للاختبار:
- المستأجر أ (
a1b2c3d4-...): بيانات اختبار «عيادة بيطرية» - المستأجر ب (
e5f6g7h8-...): بيانات اختبار «مكتب محاسبة»
نُفِّذت الاختبارات من سياق المستأجر أ، في محاولة للوصول إلى بيانات المستأجر ب. استخدمت جميع الاختبارات اعتمادات صالحة للمستأجر أ.
6.2 النواقل المُختبَرة
| # | الناقل | الطريقة | النتيجة |
|---|---|---|---|
| 1 | قراءة SQL مباشرة | SELECT * FROM organisms (دون مرشح tenant_id) | فشل — يعيد RLS صفر صفوف |
| 2 | تعديل tenant_id | UPDATE organisms SET tenant_id = 'e5f6...' | فشل — يرفض قيد CHECK |
| 3 | وصول API عبر المستأجرين | GET /api/organisms?tenant_id=e5f6... | فشل — تتجاهل API المعامل وتستخدم JWT |
| 4 | JWT مزوَّر | JWT مع tenant_id: "e5f6..." موقّع بمفتاح أ | فشل — توقيع غير صالح |
| 5 | وصول Cockpit عبر النطاق ب | الاتصال بـ tenant-b.odata.fr بJWT للمستأجر أ | فشل — عدم تطابق النطاق + JWT، 403 |
| 6 | اشتراك NATS | nats.sub("tenant.e5f6.*") باعتمادات أ | فشل — ترفض قائمة ACL الاشتراك |
| 7 | عملية NOVA | الاتصال بمنفذ NOVA للمستأجر ب | فشل — ربط 127.0.0.1، والجدار الناري يمنع |
| 8 | مفتاح SPINA | محاولة تحقق بمفتاح المستأجر ب | فشل — عدم تطابق HMAC |
| 9 | تعداد DNS | محاولة اكتشاف النطاقات الفرعية | فشل — UUIDs مبهمة، ولا نقل منطقة |
6.3 النتيجة
لم تُتجاوز أي طبقة. ولم تمكّن أي تركيبة من النواقل من استدلال بيانات بين المستأجرين.
7. لماذا تعدد المستأجرين الكلاسيكي غير كافٍ
7.1 نموذج الطبقة الواحدة
تعتمد معمارية تعدد المستأجرين الكلاسيكية — تلك التي تعتمدها معظم تطبيقات SaaS — على فصل تطبيقي واحد. يضيف التطبيق WHERE tenant_id = ? إلى كل استعلام. يعاني هذا النهج من ثلاثة عيوب بنيوية:
- نقطة فشل واحدة. إن نسيان عبارة WHERE في عملية ربط، أو ترحيل مخطط لم يُختبر جيدًا، أو خطأ في ORM يعرّض بيانات جميع المستأجرين.
- لا دفاع ضد تصعيد الامتيازات. إن المهاجم الذي يحصل على وصول مدير تطبيقي (عبر حقن SQL أو حشو الاعتمادات أو ثغرة في التبعيات) يتجاوز العزل بالكامل.
- لا عزل على مستوى البنية التحتية. قاعدة البيانات والذاكرة المؤقتة وناقل الرسائل — كلها مكونات مشتركة دون حاجز داخلي. فتسريب ذاكرة في Redis يعرّض جلسات جميع المستأجرين.
7.2 مقارنة مع نهج 0DATA
| البُعد | تعدد المستأجرين الكلاسيكي | عزل 0DATA (9 طبقات) |
|---|---|---|
| قاعدة البيانات | WHERE tenant_id = ? | RLS + قيود + محفزات |
| التوقيع | مشترك | HMAC لكل مستأجر + eIDAS |
| المراقبة | مشتركة | نسخة NOVA لكل مستأجر |
| التحليل | مشترك | ALFA بذاكرة معزولة |
| الواجهة | النطاق نفسه | نطاق لكل مستأجر، JWT مخصص |
| الرسائل | موضوعات مشتركة | NATS مُقسَّم بمساحات أسماء مع ACL |
| الشبكة | خدمات على 0.0.0.0 | ربط 127.0.0.1 وجدار ناري |
| العمق | طبقة واحدة | 9 طبقات مستقلة |
7.3 كلفة العزل
للعزل ذي الطبقات التسع كلفة: تعقيد النشر، واستهلاك ذاكرة إضافي (نسخة NOVA لكل مستأجر)، وصيانة قوائم ACL الخاصة بـ NATS. تُقبل هذه الكلفة بوصفها استثمارًا بنيويًا. ففي سياق MSP، حيث يمكن لتسريب بيانات عبر المستأجرين أن يجرّ ملاحقات قضائية وعقوبات RGPD وخسارة العملاء، تكون كلفة العزل أدنى من كلفة الانتهاك.
المعمارية موثقة ومؤتمتة (النشر عبر Ansible) ومختبَرة (اختبار اختراق عبر المستأجرين عند كل نشر). ويُضبط التعقيد عبر قابلية التكرار.
8. أعمال ذات صلة وآفاق
يُعد عزل المستأجر في البنى التحتية المشتركة موضوعًا نشطًا في الأدبيات. تستخدم المعماريات من نوع «القفص» (Google Borg وAWS Nitro Enclaves) المحاكاة الافتراضية العتادية لعزل المستأجرين — وهو نهج متين لكنه مكلف الموارد. أما المعماريات «shared-nothing» (كل مستأجر على مجموعته الخاصة) فتقدم عزلًا مثاليًا مقابل عدم كفاءة اقتصادية.
يحتل نهج 0DATA نقطة توازن: مشاركة البنية التحتية مع عزل البيانات. يوجه النموذج البيولوجي للوصلات المحكمة هذه المعمارية — فكل طبقة مستقلة ومتكررة وقابلة للتحقق.
تشمل الأعمال المستقبلية:
- التدوير التلقائي لمفاتيح SPINA لكل مستأجر (دورية قابلة للضبط)
- خصوصية تفاضلية متعددة المستأجرين للتجميعات الإحصائية
- عزل عتادي (SGX/TDX) للمستأجرين ذوي المتطلبات التنظيمية العالية
- تدقيق مستمر عبر المستأجرين — اختبار تلقائي للطبقات التسع عند كل نشر
المراجع
TIKIJJA, Hadda. «الانضباط». مختبر 0DATA، البحث 001، يوليو 2026.
TIKIJJA, Hadda. «الجهاز العصبي». مختبر 0DATA، البحث 003، يوليو 2026.
TIKIJJA, Hadda. «الطُعم الرقمي». مختبر 0DATA، البحث 004، يوليو 2026.
TIKIJJA, Hadda. «الجهاز المناعي». مختبر 0DATA، البحث 005، يوليو 2026.
TIKIJJA, Hadda. «تدقيق السطح». مختبر 0DATA، البحث 014، يوليو 2026.
PostgreSQL Documentation. «Row Security Policies». PostgreSQL 16، 2024.
NATS Documentation. «Subject-Based Messaging and ACLs». Synadia Communications، 2024.
eIDAS Regulation (EU) No 910/2014. «Electronic Identification and Trust Services».
RFC 3161. «Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)».
Dwork, C., Roth, A. «The Algorithmic Foundations of Differential Privacy». Foundations and Trends in Theoretical Computer Science، 2014.