مختبر 0DATA · البحث 014 · يوليو 2026

عزل المستأجر

معمارية من 9 طبقات لبنية تحتية مشتركة

Hadda TIKIJJA
مختبر 0DATA، فرنسا

ملخص

لا يمكن لعزل المستأجر في بنية تحتية مشتركة أن يرتكز على طبقة واحدة. نوثّق معمارية العزل ذات الطبقات التسع المنشورة على البنية التحتية 0DATA: أمان مستوى الصف في PostgreSQL، وSPINA لكل مستأجر، وNOVA لكل مستأجر، وCockpit لكل نطاق، وALFA لكل مستوى، وتطبيق ويب تقدمي دون اتصال، وخطة المنافذ، وموضوعات NATS المُقسَّمة بمساحات أسماء، وDNS wildcard. تعمل كل طبقة باستقلالية؛ فلا يُضعف تعطّل إحداها الأخريات. وتستلهم هذه المعمارية الوصلات المحكمة في الظهارة البيولوجية، حيث تحافظ كل خلية على غشائها الخاص مع مشاركتها في النسيج المشترك. نصف كل طبقة بالتفصيل، ونعرض خطة المنافذ الموثقة (لا تستمع أي خدمة على 0.0.0.0)، ونورد نتائج اختبار الاختراق عبر المستأجرين — إذ فشلت جميع محاولات القراءة بين المستأجرين.

في جملة واحدة

تضمن تسع طبقات عزل مستقلة ألا يتمكن مستأجر من رؤية بيانات مستأجر آخر أو الوصول إليها أو تعديلها — على أي مستوى من الحزمة.

1. لماذا تسع طبقات

1.1 الدفاع المتعمق ليس استعارة

في الأمن السيبراني الكلاسيكي، يُعد الدفاع المتعمق مبدأً نظريًا. أما في بنية تحتية مشتركة تستضيف عملاء MSP ذوي مصالح متضاربة، فيغدو ضرورة حيوية. قد يستضيف مزوّد الخدمات المُدارة في آنٍ واحد مكتب محاماة وعيادةً ومنافسًا مباشرًا للأول — على الخادم المادي نفسه.

يستند النهج التقليدي لتعدد المستأجرين إلى فصل على مستوى التطبيق: يصفّي التطبيق الاستعلامات وفقًا لـ tenant_id. ويفشل هذا النهج فشلاً ذريعًا عندما يتجاوز خطأ برمجي أو ثغرة حقن أو تصعيد امتيازات هذه الطبقة الوحيدة.

1.2 النموذج البيولوجي: الغشاء الخلوي والوصلات المحكمة

تجسّد الظهارة المعوية البشرية نموذجنا. تمتلك كل خلية غشاءً فوسفوليبيديًا خاصًا بها — وهو الحاجز الأول. وبين الخلايا، تشكّل الوصلات المحكمة (tight junctions) حاجزًا ثانيًا، غير منفذ حتى للجزيئات الصغيرة. أما الحاجز الثالث — الغليكوكاليكس — فيصفّي الجزيئات الكبيرة. لا يكفي أي من هذه الحواجز وحده؛ فتراكبها يخلق إحكامًا يقارب المطلق.

النقل المحاكي للطبيعة
الغشاء الخلوي → يمتلك كل مستأجر نسخه الخاصة من SPINA وNOVA وALFA
الوصلات المحكمة → يمنع RLS في PostgreSQL أي تسرب على مستوى قاعدة البيانات
الغليكوكاليكس → تشكّل خطة المنافذ وDNS wildcard وNATS المُقسَّم بمساحات الأسماء طبقة ترشيح شبكية

1.3 الطبقات التسع

الطبقةالاسمالمجالالآلية
1PostgreSQL RLSقاعدة البياناتسياسات أمان مستوى الصف
2مخطط PostgreSQLقاعدة البياناتمخطط منطقي لكل مستأجر
3سياسات التطبيققاعدة البياناتقيود CHECK ومحفزات
4SPINA v2التوقيعHMAC-SHA256 محلي + eIDAS RFC 3161
5NOVAالمراقبةنسخة لكل مستأجر، ربط 127.0.0.1
6ALFAالقرارمحرك مشترك، ذاكرة معزولة
7Cockpitالواجهةنطاق خاص، JWT موقّع لكل مستأجر
8DNS / NATSالاتصالDNS wildcard وموضوعات مُقسَّمة
9خطة المنافذالشبكةلا خدمات على 0.0.0.0، منافذ موثقة

2. الطبقات 1–3: PostgreSQL، الأساس

2.1 أمان مستوى الصف (الطبقة 1)

يُعد أمان مستوى الصف (Row-Level Security) في PostgreSQL أعمق آليات العزل. يحمل كل صف في كل جدول tenant_id. تضمن سياسة RLS المطبقة على كل جدول ألا تتمكن جلسة PostgreSQL المتصلة للمستأجر أ من قراءة صفوف المستأجر ب ماديًا.

ALTER TABLE organisms ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation ON organisms USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
الشكل 1: سياسة RLS في PostgreSQL — تُقارن عمود tenant_id بمتغير الجلسة.

تقرأ الدالة current_setting متغير جلسة في PostgreSQL. يضبط هذا المتغير مجمّع الاتصالات لحظة مصادقة المستأجر. لا يمكن لأي استعلام تطبيقي تعديله — فهو للقراءة فقط من جانب التطبيق. وهذه الطبقة منيعة دون وصول مستخدم فائق (superuser) في PostgreSQL.

2.2 مخطط لكل مستأجر (الطبقة 2)

إضافةً إلى RLS، يملك كل مستأجر مخططًا منطقيًا مخصصًا — ليس مخطط PostgreSQL بمعنى CREATE SCHEMA، بل إسقاط بيانات مقيد. تُصفّى العروض المُجسّدة والفهارس الجزئية والتسلسلات وفقًا لـ tenant_id. لا يستطيع المستأجر تعداد المستأجرين الآخرين، لأن جدول tenants نفسه محمي بـ RLS.

تمنع هذه الطبقة هجمات الاستدلال: حتى لو تمكّن مستأجر من قياس زمن تنفيذ استعلام (هجوم توقيت)، تضمن الفهارس الجزئية ألا تُمسح بيانات المستأجرين الآخرين أبدًا.

2.3 القيود والمحفزات (الطبقة 3)

تستخدم طبقة PostgreSQL الثالثة قيود CHECK ومحفزات BEFORE INSERT/UPDATE لمنع كتابة بيانات تنتهك العزل:

ALTER TABLE organisms ADD CONSTRAINT chk_tenant_owns CHECK (tenant_id IS NOT NULL AND tenant_id = current_setting('app.current_tenant_id')::uuid);
الشكل 2: قيد CHECK يمنع الكتابة عبر المستأجرين.

يقفل محفز إضافي أي محاولة لتعديل عمود 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).

Authorization: Bearer eyJ...tenant_id:"a1b2c3d4-..."...
الشكل 3: ترويسة مصادقة Cockpit — JWT يحوي tenant_id.

يتحقق وسيط nginx من JWT قبل توجيه الطلب. تُرفض محاولة الوصول إلى client-b.odata.fr باستخدام JWT للمستأجر أ على مستوى الوكيل العكسي — قبل أن يصل الطلب إلى واجهة API أصلًا. ويشكّل النطاق نفسه حدودًا للعزل: لا يستطيع مستأجر تخمين النطاق الفرعي لمستأجر آخر (فالأسماء هي UUIDs أو معرّفات مبهمة).

4.2 DNS wildcard وNATS المُقسَّم بمساحات الأسماء (الطبقة 8)

تعمل الطبقة 8 على مستوى الاتصال بين الخدمات:

DNS wildcard. يشير السجل *.odata.fr إلى البنية التحتية. يُحل كل نطاق فرعي، لكن خادم التطبيق يصفّي النطاقات غير المسجلة. لا يستطيع مستأجر إنشاء نطاق فرعي اعتباطي — فسجل DNS خاضع لسيطرة البنية التحتية.

NATS المُقسَّم بمساحات الأسماء. يستخدم ناقل رسائل NATS موضوعات مسبوقة ببادئة المستأجر:

tenant.a1b2c3d4.nova.scan.start tenant.a1b2c3d4.spina.sign tenant.e5f6g7h8.nova.scan.start
الشكل 4: موضوعات NATS ببادئة المستأجر. تقيّد قوائم ACL الوصول حسب البادئة.

تُضبط قوائم 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 المنافذ العامة (المعرَّضة)

المنفذالبروتوكولالخدمةالمبرر
22TCPSSHوصول إداري
80TCPHTTP (nginx)إعادة توجيه HTTPS + ACME
443TCP/UDPHTTPS (nginx)وكيل عكسي، HTTP/3 QUIC
5060UDPSIP (FreeSWITCH)اتصالات VoIP
5080UDPSIP (FreeSWITCH)اتصالات VoIP

5.2 المنافذ الداخلية (ربط 127.0.0.1)

المنفذالخدمةالمستأجرالدور
5432PostgreSQLمشترك (RLS)قاعدة البيانات الرئيسية
6379Redisمشترك (ببادئة)الذاكرة المؤقتة والجلسات
4222NATSمشترك (بمساحات أسماء)ناقل الرسائل
5090–5099نسخ NOVAلكل مستأجرمسح الشبكة
5100–5109واجهة NOVA APIلكل مستأجرواجهة REST لـ NOVA
5110–5119عمال SPINAلكل مستأجرالتوقيع/الختم الزمني
8300واجهة API الرئيسيةمشترك (RLS)واجهة FastAPI
8400–8409عمال Cockpitلكل مستأجرواجهة الويب Cockpit
9090Cockpit النظامالبنية التحتيةإدارة النظام

5.3 قواعد UFW

ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp ufw allow 80/tcp ufw allow 443 ufw allow 5060/udp ufw allow 5080/udp
الشكل 5: قواعد UFW — 5 منافذ فقط معرَّضة للعموم.

تُحجب جميع المنافذ الأخرى على مستوى الجدار الناري. يضيف الربط 127.0.0.1 حاجزًا ثانيًا: حتى لو عُطّل الجدار الناري، لما أمكن الوصول إلى الخدمات الداخلية من الخارج.

6. التحقق — اختبار اختراق عبر المستأجرين

6.1 بروتوكول الاختبار

أُجري اختبار الاختراق عبر المستأجرين في 23 يوليو 2026. أُنشئ مستأجران للاختبار:

نُفِّذت الاختبارات من سياق المستأجر أ، في محاولة للوصول إلى بيانات المستأجر ب. استخدمت جميع الاختبارات اعتمادات صالحة للمستأجر أ.

6.2 النواقل المُختبَرة

#الناقلالطريقةالنتيجة
1قراءة SQL مباشرةSELECT * FROM organisms (دون مرشح tenant_id)فشل — يعيد RLS صفر صفوف
2تعديل tenant_idUPDATE organisms SET tenant_id = 'e5f6...'فشل — يرفض قيد CHECK
3وصول API عبر المستأجرينGET /api/organisms?tenant_id=e5f6...فشل — تتجاهل API المعامل وتستخدم JWT
4JWT مزوَّرJWT مع tenant_id: "e5f6..." موقّع بمفتاح أفشل — توقيع غير صالح
5وصول Cockpit عبر النطاق بالاتصال بـ tenant-b.odata.fr بJWT للمستأجر أفشل — عدم تطابق النطاق + JWT، 403
6اشتراك NATSnats.sub("tenant.e5f6.*") باعتمادات أفشل — ترفض قائمة ACL الاشتراك
7عملية NOVAالاتصال بمنفذ NOVA للمستأجر بفشل — ربط 127.0.0.1، والجدار الناري يمنع
8مفتاح SPINAمحاولة تحقق بمفتاح المستأجر بفشل — عدم تطابق HMAC
9تعداد DNSمحاولة اكتشاف النطاقات الفرعيةفشل — UUIDs مبهمة، ولا نقل منطقة

6.3 النتيجة

نتيجة اختبار الاختراق عبر المستأجرين
صفر نجاحات عبر تسعة نواقل. حجبت كل طبقة المحاولات التي تعنيها. حجبت الطبقتان 1 (RLS) و2 (القيود) محاولات SQL. وحجبت الطبقة 4 (SPINA) التزوير التشفيري. وحجبت الطبقة 8 (NATS) اعتراض الرسائل. وحجبت الطبقة 9 (الجدار الناري + الربط) الوصول الشبكي المباشر.

لم تُتجاوز أي طبقة. ولم تمكّن أي تركيبة من النواقل من استدلال بيانات بين المستأجرين.

7. لماذا تعدد المستأجرين الكلاسيكي غير كافٍ

7.1 نموذج الطبقة الواحدة

تعتمد معمارية تعدد المستأجرين الكلاسيكية — تلك التي تعتمدها معظم تطبيقات SaaS — على فصل تطبيقي واحد. يضيف التطبيق WHERE tenant_id = ? إلى كل استعلام. يعاني هذا النهج من ثلاثة عيوب بنيوية:

  1. نقطة فشل واحدة. إن نسيان عبارة WHERE في عملية ربط، أو ترحيل مخطط لم يُختبر جيدًا، أو خطأ في ORM يعرّض بيانات جميع المستأجرين.
  2. لا دفاع ضد تصعيد الامتيازات. إن المهاجم الذي يحصل على وصول مدير تطبيقي (عبر حقن SQL أو حشو الاعتمادات أو ثغرة في التبعيات) يتجاوز العزل بالكامل.
  3. لا عزل على مستوى البنية التحتية. قاعدة البيانات والذاكرة المؤقتة وناقل الرسائل — كلها مكونات مشتركة دون حاجز داخلي. فتسريب ذاكرة في 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 نقطة توازن: مشاركة البنية التحتية مع عزل البيانات. يوجه النموذج البيولوجي للوصلات المحكمة هذه المعمارية — فكل طبقة مستقلة ومتكررة وقابلة للتحقق.

تشمل الأعمال المستقبلية:

المراجع

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.

شكر وتقدير. إلى فريق PostgreSQL على أمان مستوى الصف، وإلى مشرفي NATS على تقسيم مساحات الأسماء عبر ACL، وإلى البنية التحتية 0DATA التي صمدت أمام اختبار الاختراق عبر المستأجرين دون أن تتزعزع. العزل ليس ميزة — إنه بنية الكائن الحي ذاتها.