لماذا نوقّع الأوامر البعيدة في المتصفح؟ التفويض وحدود الثقة في Fleetd
شرح توقيع Ed25519 وربط الأهداف ومنع التكرار والصلاحيات وإلغاء المفاتيح في Fleetd v0.3.0، وحدود الثقة في واجهة الإدارة والطرفية.
بعد توصيل الجهاز بلوحة الإدارة، تصبح الخطوة التالية طبيعية: تنفيذ الأوامر من المتصفح. فحص القرص وإعادة تشغيل خدمة وفتح طرفية تجعل إدارة الخوادم والموجّهات أسهل. لكنها تمنح اللوحة القدرة على تغيير تلك الأجهزة؛ وتعطّل المراقبة يختلف كثيرًا في أثره عن اختراق واجهة تنفيذ الأوامر.
تناولت المقالة السابقة الاتصال الصادر والموافقة على الأجهزة والتحقق من هويتها. هنا أنتقل إلى سؤال آخر: إذا كان العميل يعرف الخادم بالفعل، فلماذا يتحقق أيضًا من توقيع المتصفح قبل تنفيذ أمر؟ الشرح مبني على Fleetd v0.3.0، ويشمل افتراضاته وحدوده، خصوصًا مصدر شيفرة الصفحة وما يحدث بعد فتح الطرفية التفاعلية.
تسجيل الدخول لا يمنح صلاحية مطلقة
في التصميم المعتاد، يسجّل المسؤول دخوله، ويجيز الخادم العملية، ثم ينفّذ العميل الرسالة الواردة. بذلك تتركز سلطة التنفيذ في الخادم.
يضيف Fleetd سؤالًا محليًا: هل أجاز هذه العملية مفتاح يثق به هذا الجهاز؟ يبني المتصفح الطلب ويوقّعه، وينقله الخادم، ثم يتحقق العميل وفق إعداداته الخاصة. يظل تسجيل الدخول والتحقق من طرف الاتصال ضروريين؛ فكل طبقة تجيب عن سؤال مختلف.
تأكيد الأجهزة والأمر ← توقيع الطلب في المتصفح
← نقل الطلب ← تحقق العميل من التفويض ← التنفيذ
وصول رسالة عبر اتصال موثّق لا يجعلها مؤهلة للتنفيذ تلقائيًا.
التوقيع يشمل العملية كاملة
توقيع كلمة uptime وحدها لا يحدد الجهاز المستهدف أو وقت السماح أو إمكانية إعادة إرسال الطلب. لذلك يشمل توقيع Fleetd الحقول التالية:
| الحقل | الوظيفة |
|---|---|
v |
إصدار البروتوكول |
id |
تعريف هذا التفويض واكتشاف الطلبات المتكررة |
kind |
تنفيذ أمر أو فتح طرفية |
targets |
بصمات الأجهزة المصرّح لها |
argv أو action |
البرنامج ومعاملاته أو إجراء معرّف محليًا |
issued_at وexpires_at |
الفترة التي يمكن قبول الطلب خلالها |
timeout |
مهلة التنفيذ، مع الالتزام بالحد المحلي للعميل |
تحوّل واجهة الأوامر الحالية النص المدخل إلى ['sh', '-c', input]. عند كتابة uptime يشمل التوقيع الطلب المحتوي على هذه المعاملات. تعمل الأنابيب و&& لأن الواجهة تستدعي الصدفة صراحة.
يحوّل المتصفح الطلب إلى بايتات JSON ويوقّعها باستخدام Ed25519. ويتحقق العميل من البايتات نفسها قبل تحليل JSON. تغيير uptime إلى reboot أو إضافة جهاز مستهدف يُبطل التوقيع القديم. أما إذا احتوى الطلب الأصلي على عدة أجهزة، فالتنفيذ على كل منها مشروع؛ ربط الأهداف يحدد نطاق التفويض ولا يفرض جهازًا واحدًا فقط.
العميل يقرر صلاحية التفويض
يحتفظ كل عميل بقائمة trusted_signers. يجب أن يكون المفتاح العام المرفق بالطلب موجودًا مسبقًا في هذه القائمة. قبول أي مفتاح مرفق سيسمح لأي شخص بإنشاء مفتاح وتفويض أوامره بنفسه.
إضافة إلى التوقيع، يتحقق العميل من نوع الطلب ووجود بصمته ضمن الأهداف والتوقيت والصلاحيات المحلية. كما يرفض حقول JSON غير المعروفة لتقليل اختلاف تفسير الطلب بين الطرفين.
ينشئ المتصفح طلبات صالحة لخمس دقائق. يسمح العميل بانحراف زمني قدره دقيقتان، ويرفض فترة صلاحية معلنة تتجاوز عشر دقائق. الخمس دقائق هي نافذة قبول التفويض وليست مدة تشغيل الأمر؛ فمهلة التنفيذ منفصلة. والتسامح الزمني يعني أن الرفض لا يبدأ حتمًا عند نهاية الدقيقة الخامسة بالضبط. لا بد من ضبط ساعات الطرفين بصورة معقولة.
تحدد هذه الشروط مجتمعة ما إذا كان التفويض الموثوق ينطبق على هذا الجهاز الآن.
منع إعادة الإرسال لا يضمن أثرًا يحدث مرة واحدة
يمكن إعادة إرسال طلب سليم لم يتغير. يولّد المتصفح معرّفًا من 16 بايتًا عشوائيًا، ويسجّله العميل بعد نجاح التفويض ثم يرفض استخدامه مرة أخرى.
يُحفظ السجل في seen.json داخل مجلد الحالة، الافتراضي /var/lib/fleetd. عند الاحتفاظ بالحالة، لا تجعل إعادة تشغيل العملية العادية الطلبات التي ما زالت صالحة قابلة لإعادة الاستخدام. وإذا فشل الحفظ، فلا يتابع العميل التنفيذ.
لكن هذا لا يضمن أن أثر العملية يحدث مرة واحدة بالضبط. يُسجّل المعرّف قبل التحقق من حد التزامن وتشغيل العملية. قد يُستهلك المعرّف ثم لا يبدأ التنفيذ لأن جميع الخانات مشغولة. وفي الاتجاه الآخر، قد يكون الأمر غيّر الجهاز بالفعل قبل انقطاع الاتصال ومنع وصول النتيجة إلى اللوحة.
الضغط على التنفيذ مجددًا ينشئ معرّفًا وتفويضًا جديدين. لا يستطيع العميل معرفة هل تعوّض محاولة فاشلة أم تكرر عملية مكتملة. في ترحيل قواعد البيانات وتغيير الإعدادات والتحديثات، افحص الحالة الفعلية واجعل العمليات قابلة للتكرار دون أثر إضافي متى أمكن. فقدان ملف الحالة أو استرجاع نسخة قديمة من القرص يختلف أيضًا عن إعادة تشغيل العملية المعتادة.
الصلاحيات المحلية تظل ملزمة
| المستوى | ما يقبله العميل |
|---|---|
monitor |
المراقبة فقط؛ رفض الأوامر والطرفيات |
allowlist |
إجراءات محلية محددة مع توقيع موثوق |
full |
أوامر حرة وطلبات طرفية مع توقيع موثوق |
يمكن إبقاء جهاز المراقبة على monitor. ولعدد محدود من مهام الصيانة، تضيق القائمة المحلية نطاق السلطة. مثلًا على جهاز يستخدم systemd ومثبت عليه nginx:
permission: allowlist
allowlist:
nginx-status: [systemctl, is-active, nginx]
هذا جزء من إعدادات الصلاحيات، وتبقى إعدادات الاتصال والمفاتيح الموثوقة مطلوبة. يتضمن الطلب الموقّع action: nginx-status، ويستخرج العميل البرنامج ومعاملاته من إعداداته المحلية. لا يستطيع المرسل إلحاق معاملات حرة، كما يُرفض الجمع بين action وargv.
واجهة v0.3.0 ترسل أوامر صدفة ولا تتضمن قائمة لاختيار الإجراءات المعرّفة. كتابة nginx-status في الحقل لن تستدعي الإجراء السابق على جهاز مقيد بـallowlist. هناك فرق بين دعم البروتوكول وما توفره الواجهة حاليًا.
في طريقة النشر الحالية يعمل العميل بصلاحيات root، وتحصل أوامر full على السلطة المقابلة. لا يكشف التوقيع أمرًا خاطئًا أو مدمرًا. كما أن أمر root المصرّح به يستطيع تعديل إعدادات العميل نفسه. السياسة المحلية تقيد الطلبات غير المصرح بها، ولا تحوّل عملية root المصرّح بها إلى عملية محدودة الصلاحيات.
لمفاتيح المتصفح دورة حياة
ينشئ WebCrypto زوج مفاتيح Ed25519 بمفتاح خاص غير قابل للتصدير، ويُحفظ الزوج في IndexedDB. يرسل التسجيل المعتاد المفتاح العام إلى الخادم، وليس المفتاح الخاص.
الانتقال إلى حاسوب آخر أو مسح بيانات الموقع قد يفقدك القدرة على توقيع طلبات تعرفها الأجهزة الحالية، حتى إن استمر تسجيل الدخول بالعمل. يحتاج المتصفح الجديد إلى مفتاح جديد، وتحتاج الأجهزة إلى الثقة بجزئه العام. تسجيله على الخادم لا يحدّث العملاء الموجودين تلقائيًا.
الإلغاء يجب أن يصل إلى الأجهزة أيضًا. حذف المفتاح من اللوحة لا يسحب الثقة به على الأجهزة المعدّة مسبقًا. يجب إزالته من قوائم trusted_signers وإعادة تشغيل العملاء بمدير الخدمات المناسب.
مفتاح توقيع الإصدارات منفصل. توقيع الأمر يجيز عملية، بينما توقيع الإصدار يثبت مصدر حزمة تحديث العميل. سنتناول دورة التحديث في مقالة مستقلة.
حدّان مهمان للثقة
الخادم يوزع الواجهة أيضًا
كون المفتاح غير قابل للتصدير يمنع واجهات WebCrypto المعتادة من إخراج مادته الخاصة. لكنه لا يمنع شيفرة خبيثة من المصدر نفسه من استدعاء التوقيع باستخدامه.
تُقدّم واجهة Fleetd من الخادم. إذا اختُرق، فقد يرسل JavaScript معدلًا في زيارة لاحقة. تستطيع الصفحة عرض أمر وتوقيع أمر آخر أو إساءة استخدام المفتاح الموجود. ونافذة التأكيد القادمة من الصفحة نفسها لا تقدم دليلًا مستقلًا على سلامتها.
يرفض العميل الطلبات المعدلة التي لا تحمل توقيعًا صالحًا، لكن الثقة بشيفرة الواجهة تبقى افتراضًا أساسيًا. توزيع أداة توقيع منفصلة قد يقلل هذه التبعية. تشير وثيقة التصميم إلى أداة CLI للتوقيع، لكنها غير منفذة في v0.3.0.
التوقيع يغطي فتح الطرفية فقط
فتح الطرفية يتطلب طلبًا موقّعًا من نوع kind: shell وصلاحية محلية full. أما ضغطات المفاتيح اللاحقة فتنتقل في الجلسة القائمة دون توقيع متصفح مستقل لكل إدخال. يستطيع خادم مخترق حقن إدخال في طرفية مفتوحة.
افتح الجلسات عند الحاجة وأغلقها بعد الانتهاء. يسهل عادة مراجعة نطاق أمر واحد واضح أكثر من جلسة تفاعلية مستمرة. توقيع البداية لا يحمي جميع الإدخالات التالية بالطريقة نفسها.
ولا يخفي التوقيع الأوامر أو مخرجاتها. يحمي التشفير بين العميل والخادم المسار الشبكي، لكن الخادم طرف نهائي في الاتصال. ليست هذه سرية شاملة بين المتصفح والعميل تستبعد الخادم.
انظر إلى مسارات الرفض أيضًا
ظهور نتيجة الأمر هو العرض الأبسط، لكن التفويض يحتاج حالات رفض واضحة. تغطي الاختبارات الحالية المحتوى المعدل، والمفاتيح غير الموثوقة، والأهداف الخاطئة، والطلبات المنتهية أو المستقبلية أكثر من اللازم، ونقص الصلاحيات، وتكرار المعرّف بعد إعادة تحميل الحالة المحفوظة.
هذه اختبارات لقواعد محددة تساعد في اكتشاف التراجعات، وليست تدقيقًا أمنيًا شاملًا. ولا تختبر تلقائيًا توزيع واجهة خبيثة أو إدخال الطرفية أو كل بيئات النشر.
القيمة للمستضيف الذاتي هي القدرة على شرح سلسلة التفويض: المفاتيح الموثوقة، والأجهزة المسموح بها، وفترة الصلاحية، والسياسة المحلية، ومعالجة التكرار. واجهة الإجراءات المحددة وأداة التوقيع المستقلة وحماية الطرفيات تظل مجالات تحسين ملموسة.
في المقالة التالية ننتقل إلى النشر: كيف يعمل عميل Go نفسه على خوادم Linux وموجّهات OpenWrt؟
Discussion
Share a question or your experience. Comments appear after moderation. Your email is never displayed publicly. Comment privacy
Loading comments…