يحمي بروتوكول أمان طبقة النقل TLS 1.3 سرية حزم البيانات ضد محاولات التنصت عبر الشبكات الوسيطة. ومع ذلك، تبقى ثغرة جوهرية على مستوى البيانات الوصفية (Metadata): يرى الخادم الوجهة دائماً وبشكل مباشر عنوان IP المصدر الخاص بالعميل.

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

ولا تقدم الخوادم الوكيلة التقليدية (مثل بروكسي HTTP أو وسطاء SOCKS5) سوى نقل نقطة المراقبة: حيث يصبح مشغل البروكسي قادراً على رؤية عنوان IP والوجهة المستهدفة في آن واحد. ولحل هذه المعضلة دون الاعتماد على جهة ثقة مركزية، اعتمدت هيئة IETF المعيار RFC 9458 (Oblivious HTTP - OHTTP)، مدعوماً بالمعيارين RFC 9180 (Hybrid Public Key Encryption - HPKE) وRFC 9292 (Binary HTTP).

+--------------------------------------------------------------------------+
|                  هيكلية بروتوكول RFC 9458 OBLIVIOUS HTTP                 |
+--------------------------------------------------------------------------+
|                                                                          |
|    +------------+        1. طلب مشفر بالكامل (HPKE)       +------------+ |
|    |            | --------------------------------------> |   خادم     | |
|    |   العميل   | <-------------------------------------- |  الترحيل   | |
|    | (المتصفح / |        4. استجابة مشفرة (HPKE)          |  (Relay)   | |
|    | وكيل AI)   |                                         +------------+ |
|    +------------+                                               |        |
|          |                                            2. تمرير  |3. إرسال|
|          | (عنوان IP العميل ظاهر لخادم الترحيل فقط)   الكتلة    |الرد    |
|          | (البيانات مشفرة بمفتاح الخادم الهدف)       المشفرة   |المشفر  |
|          |                                                      v        |
|          |                                                +------------+ |
|          +----------------------------------------------> |   الخادم   | |
|                 (حدود التشفير الشامل من طرف إلى طرف)      |   الهدف    | |
|                 الهدف يفك تشفير البيانات عبر HPKE         |  (Target)  | |
|                 الهدف يرى عنوان IP الخاص بالوسيط فقط      +------------+ |
|                                                                          |
+--------------------------------------------------------------------------+

الركائز التشفيرية: نظام HPKE وهيكلية Binary HTTP

يقوم بروتوكول RFC 9458 على مبدأ حاسم يقضي بعدم التواطؤ بين كيانين مستقلين في البنية التحتية: خادم الترحيل (Relay) والخادم الهدف (Target). يتولى خادم الترحيل تمرير الكتل المشفرة دون امتلاك القدرة على فكها؛ بينما يعالج الخادم الهدف البيانات دون أن يعرف عنوان IP الخاص بالعميل.

وتعتمد هذه الحماية على مكونين تقنيين أساسيين:

1. الإطارات الثنائية للرسائل (RFC 9292)

تتألف طلبات HTTP التقليدية من أسطر نصية وحقول ترويسة متباينة. وفي بيئة OHTTP، يتم تحويل الطلب بكامل تفاصيله — الطريقة، المسار، الترويسات، وحمولة البيانات — إلى مصفوفة بايتات ثنائية مدمجة وثابتة وفق معيار RFC 9292 (BHTTP):

+--------------------+--------------------------------+--------------------+
| حقول التحكم بالإطار| الترويسات المفهرسة             | حمولة البيانات     |
| (GET /api/v1/query)| (Host: target.example.com ...) | (بيانات ثنائية)    |
+--------------------+--------------------------------+--------------------+

يزيل هذا التحويل الثنائي أي غموض تركيبي في طبقة النقل قبل بدء العمليات الرياضية التشفيرية.

2. التشفير الهجين بالمفتاح العام (HPKE, RFC 9180)

لحماية الطلب الثنائي من اطلاع خادم الترحيل، يشفر العميل الرسالة باستخدام إعدادات المفتاح العام للخادم الهدف. وينشر الخادم الهدف إعدادات OHTTP تتضمن:

  • key_id: معرّف بطول بايت واحد لتمييز الإصدارات أثناء تدوير المفاتيح؛
  • kem_id: آلية تغليف المفاتيح (0x0020 لمنحنى Curve25519)؛
  • kdf_id: دالة اشتقاق المفاتيح (0x0001 لـ HKDF-SHA256)؛
  • aead_id: خوارزمية التشفير المقترن بالمصادقة (0x0001 لـ AES-128-GCM أو 0x0003 لـ ChaCha20-Poly1305)؛
  • public_key: بايتات المفتاح العام للخادم الهدف.

وفي النمط الأساسي لمعيار HPKE، ينشئ العميل زوج مفاتيح مؤقت $(sk_E, pk_E)$، ويشتق سراً مشتركاً مع المفتاح العام $pk_T$ للخادم الهدف:

$$ ext{SharedSecret} = ext{DH}(sk_E, pk_T)$$

وعبر خوارزمية HKDF، يشتق العميل مفتاح التشفير $K_{ ext{req}}$ وقيمة التهيئة $N_{ ext{req}}$:

$$(K_{ ext{req}}, N_{ ext{req}}) = ext{KeyDerivation}( ext{SharedSecret}, ext{info})$$

ويتم إحكام إغلاق الطلب الثنائي داخل النص المشفر $C_{ ext{req}}$:

$$C_{ ext{req}} = ext{Seal}(K_{ ext{req}}, N_{ ext{req}}, ext{aad}, ext{BinaryHTTPRequest})$$

يحمل الطلب المرسل إلى الوسيط نوع الوسائط message/ohttp-req بالهيكل التالي: [KeyID (1 بايت)] || [KEM (2 بايت)] || [KDF (2 بايت)] || [AEAD (2 بايت)] || [enc (32 بايت)] || [النص المشفر]

ولأن المفتاح الخاص المقابل لـ $pk_T$ موجود لدى الخادم الهدف حصراً، لا يستطيع خادم الترحيل قراءة الرسالة أو العبث بها دون التسبب في فشل مصادقة AEAD التشفيرية.

+--------------------------------------------------------------------------+
|                         نطاق رؤية البيانات في الشبكة                     |
+--------------------------------------------------------------------------+
| الطرف       | يرى عنوان IP الحقيقي؟ | يقرأ محتوى الطلب؟ | يقرأ الاستجابة؟|
+-------------+-----------------------+-------------------+----------------+
| مزود الخدمة | نعم                   | لا (نفق TLS)      | لا             |
| خادم الترحيل| نعم (أو IP الـ VPN)   | لا (تشفير HPKE)   | لا             |
| الخادم الهدف| لا (يرى IP الوسيط)    | نعم (طلب مفكوك)   | نعم            |
+--------------------------------------------------------------------------+

دورة عمل جلسة Oblivious HTTP

تمر دورة الطلب والاستجابة بخمس مراحل محددة:

  1. جلب مفاتيح التشفير: يحصل العميل على مفاتيح OHTTP الخاصة بالهدف عبر سجلات DNS HTTPS أو نقاط الاستعلام المعتمدة.
  2. التغليف التشفيري: يترجم العميل الطلب إلى صيغة BHTTP، وينشئ سياق HPKE المؤقت، ثم يقفل البيانات داخل كتلة message/ohttp-req.
  3. التمرير عبر الوسيط: يرسل العميل الحزمة إلى الوسيط بطلب HTTPS POST /relay. ينهي الوسيط جلسة TLS الخاصة بالعميل، ويزيل ترويسات IP، ويعيد إرسال الحزمة المشفرة إلى الهدف في اتصال مستقل.
  4. فك التشفير والمعالجة: يطابق الهدف key_id، ويفك تغليف enc لاسترجاع السر المشترك، ثم يستخرج طلب Binary HTTP لمعالجته (مثل استعلام نموذج ذكاء اصطناعي).
  5. تغليف الرد: يشتق الهدف مفتاح استجابة $K_{ ext{res}}$ من سياق HPKE نفسه، ويشفر النتيجة في كتلة message/ohttp-res، ليعيدها الوسيط إلى العميل لفكها محلياً.

التكامل مع تقنية RiceGuard وأنفاق الشبكة L3

على الرغم من عمل OHTTP في طبقة التطبيقات (L7)، فإن دمجه مع أنفاق الطبقة الثالثة (L3) عبر بروتوكول RiceGuard في VPNRice يوفر حماية مضاعفة:

  1. إلغاء مخاطر تصنيف الهوية عند الوسيط: عند التوجيه عبر RiceGuard، يرى خادم الترحيل عنوان IP صادراً من بوابات VPN مشتركة بدلاً من عنوان المنزل، مما يحول دون ربط النشاط بأي اشتراك مدني.
  2. منع تسريبات طلبات DNS: تجري عمليات الاستعلام عن أسماء النطاقات للوسيط والهدف داخل نطاق الشبكة المعزول لبروتوكول RiceGuard.
  3. تأمين وكلاء الذكاء الاصطناعي المستقلين: يمكن للبرمجيات الذكية التي تنفذ استدعاءات خارجية للأدوات (Tool-Calling) تمرير بياناتها عبر OHTTP فوق RiceGuard، مما يمنع شركات نماذج الذكاء الاصطناعي من الاحتفاظ بسجلات لعناوين المستخدمين.

نموذج برمجي للعميل بلغة Go

يوضح الكود التالي آلية تشفير وتغليف طلب Binary HTTP وفق معيار RFC 9458:

package main

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"io"
	"net/http"

	"github.com/cloudflare/circl/hpke"
)

type OHTTPEncapsulator struct {
	suite    hpke.Suite
	targetPK hpke.PublicKey
	keyID    uint8
}

func NewOHTTPEncapsulator(keyID uint8, kemID hpke.KEM, kdfID hpke.KDF, aeadID hpke.AEAD, rawPubKey []byte) (*OHTTPEncapsulator, error) {
	suite := hpke.NewSuite(kemID, kdfID, aeadID)
	pk, err := suite.KEM().Scheme().UnmarshalBinaryPublicKey(rawPubKey)
	if err != nil {
		return nil, fmt.Errorf("فشل تحليل المفتاح العام: %w", err)
	}
	return &OHTTPEncapsulator{
		suite:    suite,
		targetPK: pk,
		keyID:    keyID,
	}, nil
}

// EncapsulateRequest يغلف رسالة BHTTP داخل كتلة message/ohttp-req
func (oe *OHTTPEncapsulator) EncapsulateRequest(bhttpReq []byte) ([]byte, hpke.Context, error) {
	sender, err := oe.suite.NewSender(oe.targetPK, []byte("message/bhttp request"))
	if err != nil {
		return nil, nil, fmt.Errorf("فشل إنشاء مرسل HPKE: %w", err)
	}

	enc, ctx, err := sender.Setup(rand.Reader)
	if err != nil {
		return nil, nil, fmt.Errorf("فشل تهيئة سياق HPKE: %w", err)
	}

	ciphertext, err := ctx.Seal(nil, bhttpReq)
	if err != nil {
		return nil, nil, fmt.Errorf("فشل إحكام إغلاق البيانات: %w", err)
	}

	var buf bytes.Buffer
	buf.WriteByte(oe.keyID)
	buf.Write([]byte{0x00, 0x20}) // DHKEM(X25519, HKDF-SHA256)
	buf.Write([]byte{0x00, 0x01}) // HKDF-SHA256
	buf.Write([]byte{0x00, 0x01}) // AES-128-GCM
	buf.Write(enc)
	buf.Write(ciphertext)

	return buf.Bytes(), ctx, nil
}

func SendToRelay(relayURL string, targetURL string, ohttpPayload []byte) ([]byte, error) {
	req, err := http.NewRequest("POST", relayURL, bytes.NewReader(ohttpPayload))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "message/ohttp-req")
	req.Header.Set("Target", targetURL)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("فشل إرسال الطلب إلى الوسيط: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("رفض خادم الترحيل الطلب: كود HTTP %d", resp.StatusCode)
	}

	return io.ReadAll(resp.Body)
}

الموازنات التقنية والآفاق المستقبلية

يتطلب تشغيل RFC 9458 مراعاة العوامل التشغيلية التالية:

  • فروق زمن الانتقال (Latency): يضيف المسار عبر خادمين (العميل $ o$ الوسيط $ o$ الهدف) زمناً إضافياً يقارب 20–45 ملي ثانية. ولذا يعد البروتوكول مثالياً لخدمات API والذكاء الاصطناعي والقياسات البعيدة بدلاً من التصفح التفاعلي السريع.
  • إدارة التخزين المؤقت (Caching): تعتمد شبكات CDN على رؤية مسار الرابط للتخزين المؤقت. ونظراً لكون حزم OHTTP معماة كلياً، فإن الكاش الوسيط يتطلب دمج وسوم خاصة.
  • استقلالية الإدارة: تفقد الهيكلية قيمتها في حال خضوع الوسيط والهدف لإدارة جهة واحدة. ويعد الفصل المؤسسي بينهما شرطاً لا يقبل المساومة.

يؤكد معيار RFC 9458 Oblivious HTTP أن حفظ خصوصية البيانات في العصر الرقمي أمر ممكن وقابل للتطبيق دون التخلي عن رصانة المعايير المفتوحة.