نموذج التهديد
تسمّي هذه الوثيقة خصوم URnetwork وتقول ماذا يفعل النظام وماذا لا يفعل حيال كل واحد منهم. وهي مكتوبة كي تُهاجَم. وحيث تكون الخاصية مشروطة، فالشرطُ في الجملة نفسها؛ وحيث يكون الأمر قصداً تصميمياً لا يُنفّذه الكود المشحون بعد، فهو موسوم بأنه قصد تصميمي، لا خاصية. ويسبق القسمَ 1 ملخصٌ للقراء الذين لن يقرأوا السجل كاملاً.
والمعيارُ المرجعي هو شرح Tor نفسها للهجمات التي لا يهزمها التوجيه البصلي: فالخصمُ الذي يراقب طرفَي دائرة يستطيع ربطهما بالتوقيت، وTor تقول ذلك علناً. وURnetwork لا تشحن أي حركة تمويه ولا أي حشو، فالأمر نفسه صحيح هنا، والقسمُ 8 يقوله بلا تليين.
حالة الضمان، تُذكر مرة واحدة وتنطبق على كل ما دونها. لا يوجد تدقيق مستقل للبروتوكول ولا لمحرك الاتصال ولا لكود خوادم المشغّل — وهي الطبقة التي تقوم عليها ادعاءات الخصوصية. وهناك تقييمان خارجيان من 2025 يغطيان سطوحاً أخرى: اختبار اختراق مستقل من طرف ثالث لتطبيق الويب وواجهة API (25 أبريل – 5 مايو 2025، باعتمادات، ويدوي، وفق OWASP Top 10 إضافةً إلى مراجعة لضوابط ASVS)، وتقييم Leviathan Security Group بمستوى MASA AL2 لتطبيق Android (أُنجز في 23 مايو 2025)، وقد اجتازه، وتحدّد Leviathan نفسها نطاقه بأنه «ليس تقييماً أمنياً شاملاً ولا اختبار اختراق وافياً». ولم يفحص أي منهما التسجيل ولا الاحتفاظ بالبيانات ولا مسار البيانات ولا البروتوكول. ومن ثمّ فكلُّ ادّعاء في هذه الوثيقة ادّعاءٌ عن مصدر قابل للقراءة، يستطيع أي أحد فحصه ولم يفحصه أحدٌ خارج المشروع كاملاً بعد.
كيف تقرأ الاستشهادات
تستشهد الادّعاءات بصيغة path:line في مقابل أشجار العمل عند /Users/brien/urnetwork/{connect,sdk,server,proxy,extension} بتاريخ 2026-08-07. وأرقامُ الأسطر تنزاح؛ أما المعرّفات فلا. وحيث تثبتت نتيجةٌ في تمريرة تحقق من الكود سابقة، فهي تستشهد بـreview/verified/ARCHITECTURE.md أو بـreview/verified/PRIVACY-ENFORCEMENT.md، وكلاهما يحمل العُرف نفسه.
وتُستعمل ثلاثة أوسمة عن قصد:
- خاصية — الكودُ ينفّذها، والمهاجمُ الذي يسيطر على الأطراف الأخرى لا يزال عاجزاً عن انتهاكها.
- انضباط — الكودُ يختار ألا يفعل شيئاً هو قادر على فعله. وتغييرٌ في النشر أو رقعةٌ من سطر واحد قد يعكسه.
- قصد تصميمي — التصميمُ يقول إن هذا هو الهدف؛ والكودُ المشحون لا ينفّذه بعد.
الملخص
هذا القسم للقراء الذين لن يقرأوا السجل كاملاً. وكلُّ جملة فيه يسندها قسمٌ مرقَّم أدناه أو بيانُ الضمان أعلاه.
ما هو النظام. URnetwork شبكةُ خصوصية يُرحّل فيها الأعضاء حركةَ بيانات أعضاء آخرين. والمسارُ هو: أنت ← الموسّع ← المشغّل ← المزوّد ← الإنترنت. وقسمةُ الثقة بين طرفَي ترحيل: المشغّل، الذي يعرف من أنت، والمزوّد، الذي يرى إلى أين تذهب حركةُ بياناتك.
الخاصيتان، ولكل منهما نطاقها. على المسار المُرحَّل لا يتلقى المزوّد أبداً عنوان IP المصدري الحقيقي الخاص بك؛ ولا يغيّر ذلك أي إعداد ولا أي إصدار مزوّد (§2). والمشغّلُ لا يستطيع قراءة الجلسة المختومة بين العميل والمزوّد، وهي تُشحن مفعّلة افتراضياً على التطبيقات الأصلية الخمسة (Android وiOS وmacOS وWindows وLinux) باسم تشفير ما بعد الكم (Post Quantum Encryption) (§2.1). ولا جلسة مختومة في امتداد المتصفح — فجهازُ عميله يعمل داخل المشغّل، الذي يقوم مقام نقطة ترجمة بين البروتوكولات، فلا يمكن أن يوجد ختم هناك (§2.4).
عيبا السلامة — واحدٌ مُصلَح وواحدٌ مفتوح. كان الختم يفشل مفتوحاً في صمت في كل الأوضاع. أُصلح في 2026-08-10: فمع تفعيل تشفير ما بعد الكم يعمل العميل بالفشل المغلق، ويرفض إرسال بيانات التطبيقات نصاً صريحاً أو قبولها بدل أن يتدهور إليها (§2.2). ومع إيقاف المفتاح لا يزال السلوك الانتهازي القديم سارياً، ولا يبلّغ أي تطبيق في أيٍّ من الوضعين أيُّ الأمرين حدث. ولا يزال مفتوحاً: هل يستطيع المشغّل استبدال مفتاح مزوّد؟ اليوم: نعم (§7.4)، فسرّيةُ الختم تصمد في وجه مشغّل سلبي ومهاجمٍ على المسار يجرّد الغلاف، لا في وجه مشغّل مستعدّ لتأليف مفتاح زائف. والبندان 8 و9 من verify/BEFORELAUNCH.md يتتبّعانهما معاً؛ ويصف القسمان §2.2 و§7.4 الحال الراهنة.
ما لا يدافع النظام ضده. الخصمُ الذي يراقب شبكة وصولك والمزوّدين الذين يحملون حركة بياناتك معاً يستطيع ربط الطرفين بالحجم والتوقيت (§8.1). والمراقبُ السلبي العالمي خارج النطاق كلياً (§8.3). وURnetwork لا تشحن حشواً ولا حركة تمويه ولا خلطاً؛ والقسمُ 11 هو القائمة الكاملة.
الضمان. لا يوجد تدقيق مستقل للبروتوكول ولا لمحرك الاتصال ولا لكود خوادم المشغّل؛ وهناك تقييمان خارجيان من 2025 يغطيان سطوحاً أخرى: اختبارُ اختراق لتطبيق الويب وواجهة API، وتقييمُ Leviathan Security Group بمستوى MASA AL2 لتطبيق Android، وقد اجتازه.
أين يسكن التفصيل. يعرّف القسمان 1 و2 الأطرافَ وأوضاعَ الاتصال الثلاثة وما يراه كل طرف في كل وضع. وتتناول الأقسام من 3 إلى 5 كل خصم على حدة: مزوّد خبيث، ومراقب شبكة، والمشغّل. ويغطي القسمان 6 و7 المزوّدين الذين يشغّلهم المشغّل، والتواطؤ، واستبدال مفاتيح المزوّدين. وتغطي الأقسام من 8 إلى 12 ربطَ الحركة، ومعرّفات الأجهزة، والمطالب القانونية، وقائمةَ ما لا يدافع النظام ضده، وما تعذّر على هذه الوثيقة إثباته. ويقول القسم 13 أين تُبلَّغ الثغرات والتصحيحات.
1. الأطراف
| الطرف | يشغّله | الموضع |
|---|---|---|
| العميل | المستخدم | التطبيق أو نسخة SDK؛ وعلى مسارَي المتصفح والبروكسي يعمل على خوادم المشغّل بدلاً من ذلك (§2.4) |
| موزّع حمل المدخل | المشغّل | nginx؛ يختم عنوان العميل الملاحَظ في X-UR-Forwarded-For (xops/gitops-unused/gitops-prod/urnetwork/connect/ingress.yaml:9 — وهو بيان المدخل الوحيد في الشجرة، ودليلُه اسمه gitops-unused، فقد لا يصف الإنتاج؛ §12) |
| خدمة الاتصال | المشغّل | عمليةٌ أو عمليتان على مضيفين مختلفين، يجمعهما اتصالُ تبادل داخلي (server/connect/resident.go:2310-2327). وليست «خادم ترحيل» |
| واجهة API / مستوى التحكم | المشغّل | المصادقة، واكتشاف المزوّدين وترتيبهم، والعقود، وبحثُ المفتاح العام (server/api/api.go) |
| المزوّد | أي عضو | يتلقى الحزم المُرحَّلة ويطلب الوجهة من اتصاله هو (connect/ip.go:3932 RemoteUserNatProvider ← LocalUserNat) |
| الموسّع | أي متطوع | الساقُ الأولى في المسار: مرحّلُ تمرير TLS على عنوان مستقل. يحمل الجلسة بين العميل والمنصة من دون أن تنتهي عنده، فهو يرى عنوان الاتصال ولا يستطيع فك التشفير (connect/net_extender.go:51-55، connect/extender/extender.go:57-61) |
| محلِّلات DoH | Cloudflare وGoogle وQuad9 وOpenDNS | مسارُ التطبيق يحلّ DNS عبر HTTPS خلال النفق إلى واحد من هذه الأربعة (connect/net_http_doh.go:150-155) |
| معالِجات الدفع | Stripe وApple وGoogle وSolana/Circle | يحملون الهوية الحقيقية للحسابات المدفوعة؛ والمشغّل يخزّن مفاتيح الوصل (server/db_migrations.go:1712-1719، :4640، :2350-2356) |
والمشغّلُ هو BringYour, Inc.، وهي شركة في ولاية ديلاوير بعنوان بريدي في سان فرانسيسكو (docs/legal/ur.xyz/terms.md:16,25؛ docs/legal/terms.md:269-271). ويغطي القسم 10 ما يعنيه ذلك للإجراءات القانونية.
2. الأوضاع الثلاثة، وما يراه كل طرف
هذا الجدول هو المرجع وهو مطابق لـOVERVIEW.md. وكلُّ ما عداه في هذه الوثيقة هو الآلية خلفه.
| الوضع | ما يراه المشغّل | ما يراه المزوّد | الافتراضي والتوافر |
|---|---|---|---|
| مُرحَّل مختوم | اتصال الحساب/المصدر، والاقتران بالمزوّد، والنص المشفّر مع التوقيت/الحجم | حركة الوجهات، ومعرّف الجهاز/العقد، وليس عنوان IP المصدري الحقيقي | الافتراضي الأصلي، جاهز من العلبة؛ التطبيقات الأصلية وحدها؛ انظر §2.2 |
| مُرحَّل قياسي | اتصال الحساب/المصدر، والاقتران بالمزوّد، والوجهات الداخلية وبايتات الحزم | حركة الوجهات، ومعرّف الجهاز/العقد، وليس عنوان IP المصدري الحقيقي | مسارا المتصفح والبروكسي (§2.4)، أو عند إيقاف الختم؛ ومع تفعيل الختم يُتخطّى المزوّد الذي يتعذّر الختم معه بدل أن يُخدَم هنا (§2.2) |
| مباشر | دور أقل في الترحيل | عنوان IP المصدري الحقيقي وحركة الوجهات | يُفعَّل يدوياً، بتعطيل الإخفاء القوي للهوية (§2.3) |
وتتبع ذلك عبارتان غير متناظرتين، وهما ليستا على القوة نفسها:
عمى المزوّد عن الهوية خاصية، وهي غير مشروطة على المسارين المُرحَّلين معاً. فنقطةُ الدخول الواردة عند المزوّد تأخذ معرّفات لا عنواناً أبداً: فدالة RemoteUserNatProvider.Receive مُوسَّطة بـTransferPath من ثلاثة معرّفات بطول 16 بايت (connect/ip.go:4298-4303؛ connect/connect.go:45-49). ولا يحمل أي protobuf للنقل عنوانَ عميل ولا مدينة ولا دولة — فبحثُ grep في connect/protocol/*.proto عن location|city|country|region لا يعيد شيئاً (review/verified/ARCHITECTURE.md §1.3). ولا يوجد إعداد يوقف هذا على مسار مُرحَّل، ولا يستطيع أي إصدار مزوّد الحصول على عنوان لا يُرسَل إليه أصلاً.
عمى المشغّل عن المحتوى افتراضيٌّ لا إعداد — فوق آلية بقي بها عيب واحد. وللآلية اسم: تشفير ما بعد الكم، وهو عنصر تحكم في درج الاتصال بتطبيقات Android وiOS وmacOS وWindows وLinux، يختم جلسةً من طرف إلى طرف بين عميلك والمزوّد (§2.1). والمشروطُ لم يعد هو أن يجد المستخدمُ المفتاح، ولم يعد منذ 2026-08-10 هو أن يكون الختم قد أخفق في القيام في صمت: فمع تفعيل المفتاح، الاتصالُ الذي يتعذّر ختمه لا يحمل أي حركة تطبيقات إطلاقاً بدل أن يحملها في العلن (§2.2). والذي يبقى مشروطاً هو أن يكون المشغّل، الذي يخدم مفاتيح المزوّدين التي يُفحص الختم في مقابلها، يخدمها بأمانة (§7.4). اقرأ ذلك قبل أن تعوّل على هذه الخاصية؛ فهو غير ظاهر للمستخدم.
الافتراضي عند الإطلاق: مُفعَّل. حكم مالك المنتج في 2026-08-07 بأن الجلسة المختومة تُشحن مفعّلة، فصار عمى المشغّل هو الافتراضي لا اختياراً على المستخدم أن يتخذه. وهذه الوثيقة مكتوبة في مقابل حال الإطلاق تلك؛ وفي وقت الكتابة لا يزال الكود يفترض الإيقاف (البند 7 من verify/BEFORELAUNCH.md).
وتلك الفجوة صارت تهمّ في اتجاه أكثر مما كانت تهمّ من قبل. فلأن بوابة الفشل المغلق مربوطة بهذا المفتاح نفسه، صار تفعيل الافتراضي الآن ينشر ضماناً حقيقياً إلى كل مستخدم بدل أن يوسّع مدى إخفاق صامت وحسب — وهو عكسُ ما حذّر منه هذا القسم حين كان الختم يستطيع أن يفشل مفتوحاً في كل الأوضاع. وما لا يزال الافتراضي عاجزاً عن إصلاحه هو §7.4، وهي خاصية في الختم نفسه: فالختمُ المفعَّل افتراضياً والذي يستطيع المشغّل أن يضع آلةً في وسطه لا يحمي إلا من مشغّل سلبي.
وامتداد المتصفح بلا أي جلسة مختومة إطلاقاً (extension/src/utils/auth-params.ts:33، performance_profile: null). وذلك حدُّ نطاق لا افتراضيٌّ، وحكمُ الإطلاق لا يغيّره.
وحيثما غاب الختم — نقاط نهاية المتصفح والبروكسي (§2.4)، والتطبيقات الأصلية عند إيقاف الختم (§2.2) — يُنهي المشغّل بروتوكول TLS/QUIC الخاص بالعميل ويُرحّل حزم IP نصاً صريحاً (connect/protocol/ip.proto:9-16). وهو يختار ألا يحلّل إلا ترويسة التوجيه — فـFilteredTransferFrame لا يحتوي إلا مسار النقل (connect/protocol/transfer.proto:85-87؛ connect/transfer.go:1500-1509) — وذلك انضباط، لا حاجزٌ تشفيري.
2.1 ما هو الختم، بدقة
جلسةُ TLS 1.3 مباشرةً بين العميل والمزوّد، محمولةً بوصفها أُطر تحكم عادية عبر المشغّل نفسه (connect/transfer_encrypt.go:44-51). وتبادلُ المفاتيح هو الهجين X25519MLKEM768، مع X25519 التقليدي احتياطاً (connect/transfer_encrypt.go:373-381,406)؛ وAEAD هو AES-256-GCM على مفتاح مُصدَّر بطول 32 بايت (:285-297)؛ والهويات Ed25519 (:892-897)، فعبارةُ «ما بعد الكم» تخص تبادل المفاتيح وحده. وTLS المتبادل مطلوب، وتُفحص شهادةُ النِّد عند طبقة التسلسل في مقابل التزام العقد لا عبر منظومة TLS (:388-406).
2.2 فشلٌ مغلق حين تطلبه، وفشلٌ مفتوح حين لا تطلبه
تحديث 2026-08-10. كان هذا القسم يقول إن الختم يفشل مفتوحاً في صمت وإنه لا يوجد خيار للفشل المغلق. لم يعد ذلك صحيحاً، وهذا التغيير أهمُّ تقسية في تاريخ هذه الوثيقة — فقد أغلق مسار الخفض في الاتجاهين معاً. وما يلي هو السلوك الراهن مقروءاً من المصدر.
لا يزال التشفير خاصية ثنائية القيمة: Cipher() != nil، ولا تزال الشفرة المعدومة تعني أن المصافحة لم تكتمل: فمصافحةٌ فاشلة، أو إثباتُ هوية فاشل، أو عقدٌ لم يحمل مفتاح النِّد العام أبداً — كلُّها تتركها معدومة. ولا يزال فشلُ إثبات الهوية غير قاتل عند طبقة الجلسة — فالجلسة «تُترك بلا مصادقة» (connect/transfer_encrypt.go:1977) لا تُهدَم.
والذي تغيّر هو ما يحدث بعد ذلك. فهناك الآن ثلاثة أوضاع (connect/transfer_encrypt.go، EncryptionMode):
| الوضع | السلوك |
|---|---|
EncryptionModeOff | القيمة الصفرية. طبقةُ الجلسة خاملة، وكلُّ شيء نصاً صريحاً. |
EncryptionModeOpportunistic | يختم متى قامت جلسة، ونصاً صريحاً حتى ذلك الحين — أو دائماً إن لم تقم أبداً. وهو السلوك التاريخي. |
EncryptionModeRequired | لا يكشف بيانات التطبيقات نصاً صريحاً أبداً، لا إلى ندٍّ تُتوقَّع معه جلسة ولا منه. |
وتحت وضع EncryptionModeRequired يُفرَض الضمان عند أربع نقاط:
- بوابةُ دخول الإرسال (
connect/transfer.go:2796). فحزمةُ التطبيق تنتظر الشفرة ضمن مهلة المستدعي ثم تُرفَض بلا إرسال — ولا تُخفَّض أبداً — بخطأ مُصنَّفErrEncryptionRequiredNotEstablished. - صمّامُ الإرسال الاحتياطي (
connect/transfer.go:4125). فالإطارُ الذي يبلغ الكاتبَ بلا شفرة يُرفَض بدل أن يُكتَب، وهو ما يغطي السباق الضيق حين تُهدَم جلسة بين وضع الإطار في الطابور وكتابته. - بوابةُ الاستقبال (
connect/transfer.go:5844). فإطارُ تطبيقٍ يأتي نصاً صريحاً من ندٍّ تُتوقَّع معه جلسة يُسقَط ويُدوَّن — وهذا هو النصف الأهم، لأنه يغلق الخفض حين يجرّد المهاجمُ الغلاف ويكون المتلقي لولا ذلك سيقبل النص الصريح. ويُقَرّ الإطار ثم يُهمَل بدل أن يُترك بلا إقرار، إذ حجبُ الإقرار يفتح ثغرة في التسلسل المرتَّب ويُعلِق الطرفين كليهما. - التصفيةُ المسبقة للمرشَّحين (
connect/ip_remote_multi_client.go،EncryptionCapabilityPrefilter). فمرشَّحُ النافذة الذي تقول عنه واجهةُ مفاتيح المنصة خارج النطاق إنه لم ينشر مفتاح هوية قط يُفشَّل فوراً، إذ لا يستطيع أبداً أن يكمل المصافحة. وهي لا تعجّل إلا فشلاً مؤكداً؛ ولا تقبل مرشَّحاً أبداً.
وأُطرُ التحكم في المصافحة، والإقرارات، وأندادُ مستوى التحكم مستثناةٌ بحكم التصميم — فالبوابة تغطي حمولة التطبيقات، لا السقالة التي تُمهّد لها.
والوضعُ الذي تحصل عليه يحدده مفتاح تشفير ما بعد الكم. فحين يكون مفعّلاً يعمل عميلُ المستهلك بوضع EncryptionModeRequired (connect/ip_remote_multi_client.go:9186-9197): فالمزوّدُ الذي يتعذّر عليه إقامةُ جلسة لا يحمل لك أي حركة تطبيقات إطلاقاً، بدل أن يحملها في العلن. والكلفةُ المعلنة هي التوافر، وقد قُبلت عن قصد. أما المزوّدون فيعملون بوضع EncryptionModeOpportunistic (sdk/device_local_provider.go:98) كي يستطيع المزوّد الواحد أن يخدم المستهلكين المختومين وغير المختومين معاً؛ وذلك خيارُ توافق على جانب المستجيب ولا يضعف ضمان البادئ.
وماذا يعني هذا للمفتاح. فمع تفعيل تشفير ما بعد الكم لم يعد الختم يفشل مفتوحاً: بل يفشل مغلقاً، وبصوت عالٍ، عند الإرسال والاستقبال معاً. ومع إيقافه يظل السلوكُ الانتهازي الموصوف في النسخ الأسبق من هذا القسم سارياً بتمامه — فقد تجري الحركة نصاً صريحاً إن لم تقم جلسة أبداً، ولا شيء يخبر المستخدم. فالعبارةُ الأمينة إذن مشروطة، والافتراضيُّ يهمّ: انظر فقرة الافتراضي عند الإطلاق في §2.
والسلوكُ مغطّى باختبارات، لا بتعليقات وحدها — TestRequiredEncryptionFailsClosedAgainstPlaintextPeer وTestRequiredGateNonBlockingSendRefusesPreCipher وTestRequiredGateBoundedBudgetRefusesUnsent وTestRequiredSendRefusalTypedErrorAndEvent وTestRequiredContractFreeWithoutKeySourceFailsClosed.
وتعليقٌ واحد قديم ينبغي تجاهله أثناء التدقيق: فترويسةُ completeHandshake عند connect/transfer_encrypt.go:1650-1654 لا تزال تؤكّد بإطلاق أن «الحركة التالية تجري نصاً صريحاً». وذلك صحيح في وضعَي Off وOpportunistic وحدهما؛ أما البوابات أعلاه فتَجُبُّه تحت Required. والتعليقُ سابقٌ للإصلاح.
ولا يزال مفتوحاً: لا يستطيع المستخدم أن يرى أيَّ وضع حصل عليه اتصالٌ بعينه. فلا يوجد في أي تطبيق مؤشرٌ لكل اتصال يبيّن أهو مختوم أم لا. والإشاراتُ الوحيدة أسطرُ سجل الجهاز — peer identity proof verified — cipher is now usable (connect/transfer_encrypt.go:1954) عند النجاح، وErrorf عند الفشل، وحدثُ NotifyRequiredSendBlocked حين ترفض البوابةُ. أما SDK فتكشف خطّافَ تغيير، فالقطعةُ الناقصة هي واجهة المستخدم لا السباكة.
2.3 الوضع المباشر
إيقافُ الإخفاء القوي للهوية يضبط AllowDirect، وتعليقُ حقله نفسه يقول: // setting this to true exposes the real source IP to the provider (sdk/sdk.go:710-711). ويُجبَر التدفق على مجرى ندٍّ لند (connect/ip_remote_multi_client_probe.go:1176-1178) عبر قناة بيانات WebRTC/ICE (connect/transport_p2p_webrtc.go:986)، وICE يعني أن كلتا النقطتين تعرف عنوان الأخرى. والافتراضيُّ هو الإيقاف — فملفُّ أداء معدوم يعطي القيمة false (connect/ip_remote_multi_client.go:1861-1863؛ sdk/local_state.go:607-616).
وحالتان مُجبَرتان: الأنداد على الشبكة نفسها (أجهزتك أنت) يُسمح لهم بالمباشر دائماً (connect/ip_remote_multi_client.go:1822-1825)، والأجهزةُ المستضافة تُجبره على الإيقاف (sdk/device_local.go:1516-1533). ولاحظ أن الوضع المباشر يزيح المشغّل عن مسار البيانات وحده. فالعقودُ واختيارُ المزوّدين ورسائلُ التحكم لا تزال تمر عبر المنصة، فيظل المشغّل يعرف أي مزوّد استخدمت وكم بايت تحرك.
2.4 المسار الذي لا يغطيه الجدول: نقاط نهاية المتصفح والبروكسي
على امتداد المتصفح، وتطبيق الويب، ونقاط نهاية HTTPS/SOCKS5/WireGuard، يشغّل المشغّلُ العميل. فالامتدادُ يهيّئ جهاز بروكسي على جانب الخادم (extension/src/utils/auth-params.ts:22-36، enable_socks/enable_http) ويُوجَّه المتصفح إلى نقطة نهاية البروكسي لدى المشغّل — بـHTTPS CONNECT افتراضياً (extension/src/bridge/background.ts:220؛ extension/src/utils/proxy-manager.ts:264). ونسخةُ SDK التي تفتح العقود وتحمل نافذة المزوّدين تعمل في server/proxy، لا على جهاز المستخدم.
ولهذا لا يمكن أن توجد جلسة مختومة على هذه المنصات، بحكم المعمارية لا بحكم جهد هندسي لم يُبذل بعد. فالجلسةُ المختومة بين العميل والمزوّد، وضمانُها يتوقف على أن تعيش نقطةُ العميل على جهاز المستخدم نفسه. والمتصفحُ أو عميلُ البروكسي العادي يتكلم بروتوكوله هو (HTTPS CONNECT أو SOCKS5 أو WireGuard) ولا يستطيع تشغيل محرك الشبكة، فيشغّل المشغّل جهازَ العميل عن بُعد ويقوم مقام نقطة الترجمة بين البروتوكولين. وأي ختم يُتفاوض عليه من ذلك الجهاز البعيد سيبدأ داخل المشغّل — وهو الطرف الذي وُجد الختم ليُعميه. وقد قبل التنفيذُ هذه المقايضة عن قصد: فهذه السطوح موجودة للتيسير على منصات وبروتوكولات لا تستطيع استضافة العميل الكامل، ويجب ألا تصفها الوثائق بأنها مختومة.
والنتائج، مذكورةً بصراحة:
- عمى المزوّد عن الهوية لا يزال قائماً — فالمزوّد لا يزال يتلقى معرّفات فقط.
- وعمى المشغّل لا وجود له على هذا المسار بأي صورة. فالمشغّل يُنهي اتصال البروكسي، ويتلقى مضيف الوجهة من CONNECT، ويحمل مفاتيح العميل.
- والجهازُ المستضاف لا يركّب أي مُجمِّع لترقية DNS (
server/proxy/proxy_device.go:556،SetUpgradeMuxSettings(nil))، فـDoH داخل النفق في مسار التطبيق (§3.2) لا ينطبق هنا.
والذي يقوم مقام التشفير على هذا المسار هو انضباط التخزين: فمسارُ بيانات البروكسي لا يسجّل شيئاً على المسارات التي يقودها العميل، واختبارُ انحدار يثبّت ذلك — فـproxy/socks5_nolog_test.go، وفيه TestClientDrivenTrafficNeverLogs، يؤكّد انعدام أسطر السجل عبر الحالات المشوَّهة والمفرطة الحجم وغير القابلة للطلب. وتحفّظان أمينان: دافعُ الاختبار المعلن هو حجبُ الخدمة بتضخيم السجلات لا الخصوصية، ومعالِجُ التعافي من الذعر يسجّل عنوان عميل (proxy/socks5_server.go:128-131). انظر review/verified/PRIVACY-ENFORCEMENT.md §2.2.
3. الخصم: مزوّد خبيث
داخل النطاق، ومفترَض. يستطيع أي أحد أن يزوّد. ولا يوجد تصديق ولا رهن ولا فحص هوية ولا مقاومة لهجمات Sybil على مشاركة المزوّدين — فالبحثُ عبر أشجار server وconnect وsdk عن sybil|kyc|attestation لا يعيد شيئاً ذا صلة. والمزوّدُ يشغّل كوداً مفتوح المصدر على عتاد يسيطر عليه، فافترض أنه يشغّل إصداراً معدَّلاً.
ما يراه. كلَّ ما تراه شركةُ الإنترنت عن الحركة التي يحملها: عنوانَ الوجهة ومنفذها، وأحجامَ الحزم وتوقيتها، واسمَ SNI في TLS حيث يرسله العميل صريحاً. وهو يتلقى حزم IP خاماً ويطلبها بنفسه (connect/protocol/ip.proto:9-16؛ connect/ip.go LocalUserNat). ويرى أيضاً client_id المحمول بوصفه SourceId للعقد (connect/protocol/transfer.pb.go:1779؛ server/controller/connect_controller.go:461-463) — وهو معرّفٌ لكل خانة في النافذة لا يستطيع حلَّه إلى حساب إلا المشغّل، وليس device_id أبداً، إذ لا حقل له على السلك. وعمرُه، والأشياءُ العديدة التي تبقى فعلاً عبر الجلسات، في §9.
ما يستطيع فعله.
- HTTP نصاً صريحاً: قراءته وتعديله. المنفذ 80 يُمرَّر إلى الخروج من دون تغيير افتراضياً — فـ
HttpUpgradeUnencryptedهو الوضع الافتراضي (connect/ip_mux_upgrade.go:38-47). والمزوّدُ في موضع نقطة Wi-Fi معادية لأي حركة ليست مشفّرة في ذاتها. وHTTPS يحمي محتوى التطبيق من المزوّد؛ ولا شيء في URnetwork يضيف طبقة ثانية فوق TLS الخاص بالوجهة نفسها. - إسقاط الحركة أو تأخيرها أو تعطيلها انتقائياً. المزوّدُ الذي يُقرّ باستلام الحركة ولا يعيد شيئاً يُوسم ثقباً أسود ويُزال (
connect/ip_remote_multi_client.go:37-54)، فالمنعُ يُكتشف ويُلتفّ حوله — لكن الكشف إحصائي، والحركةُ التي رآها قبل الإزالة قد رُئيت بالفعل. - الكذب في الأداء لاجتذاب الحركة. الترتيبُ يستخدم زمن الاستجابة ومعدل النقل المقيسين (
server/model/network_client_location_model.go:2430-2447)، والقياسُ للمشغّل لا تقريرٌ ذاتي من المزوّد، فهذا محدود — لكنه مدخلُ ترتيب لا ضابطَ سلامة. - ربطُ التدفقات داخل رؤيته هو. التثبيتُ لكل موقع يثبّت موقعاً على مزوّد واحد (
connect/ip_remote_multi_client.go:1234-1240)، فيرى المزوّد الواحد شريحةً متماسكة من تصفح عميل واحد للمواقع التي يحملها.
ما لا يستطيع فعله بلا مساعدة. معرفةَ عنوانك الحقيقي على مسار مُرحَّل، أو معرفةَ حسابك أو بريدك الإلكتروني، أو نسبةَ client_id إلى شخص. فتلك تتطلب المشغّل (§5).
3.1 ماذا تقيّد طبقة ip_security وماذا لا تقيّد
طبقةُ ip_security في محرك الاتصال تعمل على خروج المزوّد نفسه وعلى جهاز المستخدم نفسه، لا مركزياً عند المشغّل أبداً — فحقلا المشغّل IngressSecurityPolicyGenerator/EgressSecurityPolicyGenerator موجودان لكن لا يُسنَدان ولا يُقرآن أبداً (server/connect/resident.go:263-264؛ review/verified/PRIVACY-ENFORCEMENT.md §4.1). وهي تحجب تواقيع BitTorrent ومشاركة الملفات، والبروتوكولات المبهمة غير القياسية، والوجهات المدرجة في قوائم السمعة، وحركةَ أنماط الهجوم، وتفعل ذلك على أساس رقيق عن قصد: خماسيةُ التدفق إضافةً إلى بادئة حمولة محدودة بـ8 حزم / 512 بايت.
وجداولُ السمعة مولَّدة لا مصونة يدوياً. فـconnect/security وconnect/blocker يجمّعان تغذيات استخبارات تهديد عامة — abuse.ch Feodo Tracker لمراكز قيادة شبكات البوت، وSpamhaus DROP وDROPv6، وEmerging Threats للعناوين المخترَقة، وBlocklist.de، وCINS Army، وTweetFeed، وViriBack، وBruteForceBlocker — في جداول نطاقات محزومة (46,789 نطاق IPv4 في لقطة 2026-08-05؛ وترويسةُ connect/ip_security_cfaa_block.go تحمل قائمة التغذيات والإسناد). وخطُّ إصدار البناء يعيد توليد الجدولين من التغذيات الحية (build/all/run.sh، خطوة CONNECT_IP_UPDATE)، فكلُّ إصدار يشحن لقطة حالية، والعميلُ المحدَّث يحجب أحدث فضاء عناوين مُدرَج. واللقطةُ تشيخ مع البناء المثبَّت؛ فالقوائم تتحدث مع كل إصدار، لا عبر الأثير.
وحدُّ بادئة الحمولة عند connect/ip_security_dmca.go:117-119، مع مسح اسم الخادم من مفتاح التدفق (:366,386,424) والعدّادات مفتاحُها (version, protocol, port) وحقلُ IP فيها لا يُفعَّل أبداً (connect/ip_security.go:554,604-624).
إنها ضابطُ سلامة للمزوّدين الأمناء، لا ضابطَ أمان في وجه المعادين منهم. فهي تقيّد ما يحمله إلى الخارج اتصالُ المزوّد. ولا تفعل شيئاً حيال ما يفعله المزوّد بالحركة التي يحملها فعلاً، وهي تعمل في عملية يملكها المزوّد، وإصدارٌ معدَّل يستطيع تعطيلها. فلا تقرأها حداً على مزوّد خبيث.
وتفصيلٌ واحد في التبليغ مكانه هنا لأنه قناةُ بيانات وصفية. فتطابقُ توقيع BitTorrent يعيد Incident، وهو يستدعي ReportAbuse (connect/ip.go:4481-4487)، فيرسل إطار تحكم PeerAudit إلى المشغّل يحمل معرّف جهاز النِّد وقيمة منطقية — بلا وجهة ولا نطاق ولا محتويات (connect/transfer.go:870-876,6653-6683). وليس لدى المشغّل معالِجٌ لذلك النوع من الرسائل اليوم، فلا يُخزَّن شيء عند الاستلام (server/controller/connect_controller.go:236-250؛ وبحثُ grep على مستوى المستودع عن PeerAudit في server يعيد صفر نتيجة). وذلك انضباط على بُعد جملة case واحدة من التغير. أما إسقاطات البروتوكولات المبهمة المشفّرة فصامتة بلا أي تبليغ (connect/ip_security_dmca.go:483-486).
3.2 نظام أسماء النطاقات
على مسار التطبيق وSDK، يُعترض DNS العادي على المنفذ 53 في UDP وTCP ويُحلّ عبر DoH داخل النفق (connect/ip_mux_upgrade.go:120-148، مركَّبٌ افتراضياً عند sdk/device_local.go:1120)، إلى Cloudflare أو Google أو Quad9 أو OpenDNS (connect/net_http_doh.go:150-155). فيرى المزوّد إذن اتصال HTTPS بمحلِّل عام، لا الاستعلام. وحدّان أمينان:
- نافذةُ تسريب DNS عند البدء موثَّقة في المصدر. فبينما لا يزال DoH داخل النفق يقوم، يُسابَق الاستعلام أمام محلِّل عبر خروج المضيف المحلي، «على حساب تسريب DNS وجيز أثناء البدء» (
connect/ip_mux_upgrade.go:120-126,78-92). وشبكتُك المحلية وشركةُ الإنترنت تستطيعان رؤية تلك الاستعلامات. - نقطةُ نهاية WireGuard تسلّم العميل محلِّلاً عاماً ثابتاً،
DNS = 1.1.1.1(server/model/network_client_proxy_model.go:760)، والمنفذ 53 يُمرَّر بلا فحص من سياسة الأمان (connect/ip_security_cfaa.go:113). وعلى ذلك المسار تعبر استعلاماتُ DNS المزوّدَ نصاً صريحاً، ويستطيع المزوّد قراءتها والإجابة عنها.
ومحلِّلات DoH الأربعة أطرافٌ ثالثة ترى استعلامات تصل من عنوان خروج مزوّد، غير مربوطة بحسابك. وذلك اعتمادٌ حقيقي وهو غير قابل للتصفير: فلا بد لأحد أن يجيب عن DNS.
4. الخصم: مراقب شبكة
أربعةُ مواضع، من الأضعف إلى الأقوى.
شبكتك المحلية وشركة الإنترنت. يريان أنك تتصل بـconnect.bringyour.com عبر TLS/QUIC، أو بموسّع، مع الأحجام والتوقيتات. ولا يريان الوجهات داخل النفق، إلا في نافذة DNS الموثَّقة عند البدء أعلاه. وحيث تُحجب المنصة، تظهر الموسّعات بوصفها خدمات عادية على منافذ مصدَّقة ويبدّل العملاء شخصياتها مع تجزئة عشوائية (connect/net_extender_profiles.go:14-30,50-57)، ويوجد نقلٌ بهيئة DNS للشبكات التي لا يفلت منها إلا DNS (connect/transport_pt.go:18-45). وهذه آلياتٌ لعبور جدران الحماية المحلية والإقليمية، مرتَّبة دون وسائل النقل المباشرة (connect/transport.go:541-546). وهي ليست دفاعات ضد تحليل الحركة، ولا ينبغي أن تُوصف بذلك أبداً.
مشغّل موسّع. يستطيع أي أحد تشغيل واحد، والتطبيقُ يقبل عنوان IP يُدخَل يدوياً، ولا يُشترط توقيع افتراضياً (connect/extender/extender.go:57-61). والموسّعُ هو نِدّ TCP، فهو يرى عنوان IP الخاص بالمستخدم المتصل، ولا يستطيع فك تشفير ما يمرّره، لأن جلسة TLS تجري خلاله إلى المنصة بدل أن تنتهي عنده (connect/net_extender.go:51-55). فساقُ الموسّع تضع إذن في المسار مراقباً لعنوانك عند القفزة الأولى ليس هو المشغّل. وتلك هي المقايضة التي يعقدها التصميم كي يوصلك عبر الحجب، ويستحق حجمُها الدقة: فساقُ الموسّع لا تضيف تشفيراً ولا مجهولية — إنها تعرف ما تعرفه شركةُ الإنترنت لديك أصلاً ولا شيء أكثر. وفي العميل المشحون تُسابَق وسائلُ النقل المباشرة أولاً وتتوسع طالباتُ الموسّعات حين تفشل تلك (connect/net_http.go:675)؛ والعميلُ المضبوط بموسّعات مخصصة يستخدمها طريقه الوحيد (connect/net_http.go:357,469).
مراقبُ طرف واحد. مراقبةُ جانب العميل وحده تعطي «هذا المستخدم متصل بـURnetwork» وملفَّ بايتات وتوقيت. ومراقبةُ خروج مزوّد وحده تعطي الوجهات وملفَّ بايتات وتوقيت بلا هوية مرتبطة.
مراقبُ الطرفين. انظر §8. وهو الخصم الذي لا تهزمه URnetwork.
5. الخصم: المشغّل
المشغّل يصادق العملاء، ويختار المزوّدين ويرتّبهم، ويحرّر العقود، ويوزّع المفاتيح العامة، ويحمل الحزم على المسارات المُرحَّلة. وافترض في هذا القسم أنه معادٍ أو مُكرَه.
ما يراه، بلا أي جهد إضافي: حسابك؛ وعنوانك لحظة اتصالك؛ ومدينة/منطقة/دولة مشتقة من ذلك العنوان ببحث محلي في قاعدة بيانات — فـserver/ip.go:201 يفتح ملفَّ mmdb/ip-ipinfo.mmdb المضمَّن من القرص، وip.go لا يجري أي نداء شبكي من أي نوع، فلا يُسلَّم العنوان أبداً إلى خدمة تحديد موقع جغرافي — ومحفوظة لكل اتصال (server/model/network_client_location_model.go:1392-1414)؛ وأي المزوّدين خدموك؛ وعددَ البايتات؛ وعلى المسار القياسي، عناوينَ الوجهات وبايتات الحزم داخل النفق — وإن كانت تلك عادةً داخل HTTPS الخاص بالوجهة نفسها أصلاً.
ما يخزّنه. سجلاتُ الاتصال والمصادقة تحفظ تجزئة أحادية الاتجاه بمفتاح لكتلة /29 المحيطة (في IPv4) أو /56 (في IPv6) بدل العنوان (server/ip.go:46-67). ودقةٌ تهمّ المدقّق: إنه pepper واحد على مستوى العملية كلها من الخزنة، محفوظٌ في الذاكرة مرة واحدة، بلا ملح لكل صف وبلا أي آلية تدوير في المستودع كله (server/ip.go:40-44)؛ وفضاءُ مفاتيح IPv4 هو 2^29 كتلة، فمن يملك الـpepper يستطيع عكسها بالقوة الغاشمة. وسرّيةُ الـpepper هي الخاصية الأمنية كلها. ونظامُ /verify الفرعي يستخدم /48 لـIPv6 لا /56 (server/ip.go:74-85؛ server/model/verify_model.go:111). ومنفذُ المصدر يُخزَّن صريحاً إلى جانب التجزئة (server/db_migrations.go:1934). وصفُّ تدقيق إنشاء الحساب يسجّل التجزئة المفلفلة والمنفذ، ولا يسجّل أبداً ip:port الخام (server/model/network_model.go:961-975)، وصفوفُ التدقيق تُزال بعد 180 يوماً (server/model/audit_model.go:984، مجدولةً عند server/taskworker/taskworker.go:57,253).
ما لا وجود له أصلاً كي يُخزَّن. لا تظهر أي وجهة ولا مضيف ولا URL ولا SNI ولا منفذ ولا نطاق في أي موضع من سجل النقل — فبحثُ grep في ملف الترحيل الكامل عن تلك المصطلحات يعيد صفر نتيجة (review/verified/PRIVACY-ENFORCEMENT.md §1.2). وتسجيلُ HTTP يمر عبر قائمة سماح من خمس ترويسات بالضبط (server/http_log.go:15-29)، مثبَّتة باختبار. ولا يحمل أي مقياس Prometheus عنواناً ولا مضيفاً ولا وجهة ولا منفذاً ولا معرّف عميل؛ ومن 39 مقياساً معلَناً ثلاثةٌ فقط موسومة وكلُّ وسم منها تعدادٌ محدود (review/verified/PRIVACY-ENFORCEMENT.md §2.5). ورفعُ سجلات تبويب الدعم يُصرَّف إلى io.Discard (server/controller/log_file_controller.go:13-16,76)؛ ولا يبقى إلا البيانات الوصفية.
5.1 إلى متى يُحتفَظ بأي من ذلك، وإلى أين يذهب
الاحتفاظُ تفرضه عملياتُ كنس مجدولة في server/taskworker، لا سياسةٌ. والنوافذُ أدناه مقروءة من الثوابت التي تستدعيها تلك العمليات، وهي أقصر مما قد يتوقعه قارئُ سياسة الخصوصية — وهي سياسةٌ لا تنص على أي مدة احتفاظ إطلاقاً.
| البيانات | مدة الاحتفاظ | موضع الإنفاذ |
|---|---|---|
| صفوف الاتصالات، وما يتعلق بها لكل اتصال من مدينة/منطقة/دولة وزمن استجابة وسرعة | 8 ساعات | taskworker/work/network_client_work.go:84؛ والحذفُ يتتالى إلى network_client_location في العبارة نفسها (model/network_client_model.go:2295-2320) |
| عميل أعلى مستوى خامل (لا مصادقة ولا اتصال) ← يوسَم غير نشط | 30 يوماً | TopLevelClientIdleExpiration (model/network_client_model.go:2289) |
| عميل غير نشط ← حذف قاطع، مع التتاليات | 30 يوماً أخرى | NetworkClientReapAfterDeactivate (:2269) |
| فالجهاز غير المستخدَم إذن، من أوله إلى آخره | نحو 60 يوماً | النافذتان متسلسلتان |
| العقود المكتملة | 7 أيام | taskworker/work/subscription_work.go:161 |
| صفوف التدقيق | 180 يوماً | model/audit_model.go:984 |
ملاحظتان تهمّان المدقّق. نافذةُ الخمول شُدّدت من 90 يوماً إلى 30 في 2026-07-18؛ والثابتُ يحمل مسوّغه بنفسه، وتعليقٌ قديم عند taskworker/work/network_client_work.go:83 ما يزال يقول 90، وهو المصدرُ الأرجح لذلك الرقم إن صادفته في موضع آخر. وRemoveLocationLookupResults مجدولةٌ في كل دورة لكنها بلا أي مفعول (no-op) — فجسمُها ونداؤها إلى النموذج كلاهما مُعلَّق كتعليق، ولا وجود لجدول كهذا أصلاً. إنها بقيةٌ أثرية من الكود، لا بياناتٌ لم تُكنَس؛ فموقعُ كل اتصال يُحذف مع صف الاتصال أعلاه.
تحديدُ الموقع الجغرافي لا يغادر الآلة أبداً. فبحثُ المدينة/المنطقة/الدولة يقرأ ملفَّ mmdb/ip-ipinfo.mmdb المضمَّن من القرص المحلي (server/ip.go:201)، وip.go لا يتضمن أي عميل HTTP ولا يجري أي نداء شبكي. فلا يُرسَل أي عنوان إلى خدمة تحديد موقع جغرافي، ولا تُشارَك أي معلومات شخصية مع أي طرف ثالث. والأطرافُ الثالثة الوحيدة في جدول الأطراف في هذه الوثيقة تحوز بياناتٍ يسلّمها المستخدم إليها مباشرةً باختياره ذلك المسار: محلِّلات DoH التي تصلها استعلاماتُ DNS الخاصة بالمستخدم نفسه عبر النفق، ومعالِجات الدفع التي يسجّل عندها ليُفوتَر.
ثغرات معروفة في موقف «لا نسجّل عنوانك»، غير مقيَّدة بمستوى الإسهاب. يبني server/http.go:415,455 كائنَ http.Server بلا ErrorLog، فتكتب مكتبةُ Go القياسية http: TLS handshake error from إلى مخرج stderr في الإنتاج عند كل اتصال نصف مفتوح — وهي الثغرة نفسها التي يغلقها proxy/http.go:176,250 بـErrorLog: discardLog. وSNI الذي يزوّده العميل يُسجَّل عند مستوى ERROR (server/tls.go:98,195)، وعنوانُ متصل خام عند server/proxy/proxy_device.go:274، وهويةُ نِدّ WireGuard عند server/proxy/server.go:699. وحتى تُصلَح تلك، لا يكون «نحن لا نسجّل عنوان IP الخاص بك أبداً» ادّعاءً تستطيع URnetwork أن تقوله، وهذه الوثيقة لا تقوله. التفصيل الكامل: review/verified/PRIVACY-ENFORCEMENT.md §2.4.
ما يتحكم فيه المشغّل ويسهل إغفاله. اكتشافُ المزوّدين على جانب المشغّل كلياً: فـFindProviders2 هي نقطة النهاية الحية الوحيدة (server/api/api.go:67)، والمنصةُ تسجّل درجات المرشحين وترتّبهم (server/model/network_client_location_model.go:2250-2254,2430-2447)، والعميلُ يأخذ المجموعة المرتّبة التي تُعطى له. والضابطُ الوحيد على جانب المستهلك قائمةُ حجب مواقع (server/api/api.go:73-75). ولا سبيل لدى العميل للتحقق من أن المزوّدين المعروضين عليه مستقلون بعضهم عن بعض أو عن المشغّل.
6. المزوّدون الذين يشغّلهم المشغّل، والتواطؤ بين المشغّل والمزوّد
6.1 هل يستطيع المشغّل تشغيل مزوّدين؟
نعم، ولا شيء في النظام يسم ذلك أو يمنعه. فالتزويدُ مفتوح لأي أحد بلا تصديق ولا رهن، ولا يوجد في الكود أي مفهوم لمزوّد من الطرف الأول أو رسمي أو مملوك للمشغّل — فالبحوثُ عبر server وconnect وsdk عن مثل هذا المفهوم لا تعيد شيئاً. والمزوّدُ الذي يشغّله المشغّل لا يمكن تمييزه عن مزوّد عضو.
ومع نقطة §5 بأن المشغّل يرتّب مجموعة المزوّدين ويعيدها، يعني هذا أن المشغّل يستطيع، من حيث المبدأ، وضع مزوّديه هو في نافذة مستخدم. ولا يوجد فحصُ تنوّع على جانب العميل، ولا تصديقٌ على الاستقلال، ولا قياسٌ منشور للأسطول من طرف خارجي. والموازناتُ الموجودة حقيقية لكنها جزئية: فالنافذة تحمل عدة مزوّدين في آن واحد — نافذةُ جودة من 2–6 (بحدّ أقصى صارم 12) ونافذةُ سرعة من 1–2 (بحدّ أقصى صارم 4)، وكلتاهما حيّة في الملف الافتراضي (connect/ip_remote_multi_client.go:138-158) — والمزوّدون يُزالون على إحصاءات غير صحية، وكشفِ الثقب الأسود، وفشلِ النبض، وتدويرِ عمر القناة (:37-54، :610-616). وتلك تحدّ كم يرى أيُّ مزوّد واحد. لكنها لا تحدّ مجموعةً من المزوّدين يختارها طرفٌ واحد.
6.2 ماذا يعيد المشغّل والمزوّد بناءه معاً، بحسب كل وضع
افترض أن المشغّل ومزوّداً أو أكثر في نافذتك يتشاركون ما يحمله كلٌّ منهم.
| مُرحَّل قياسي | مُرحَّل مختوم | مباشر | |
|---|---|---|---|
| هويتك (الحساب، والبريد الإلكتروني/المحفظة/الدفع) | المشغّل | المشغّل | المشغّل |
| عنوانك الحقيقي لحظة الاتصال | المشغّل | المشغّل | المشغّل، ومعه المزوّد مباشرةً |
| الوجهات التي زرتها | المشغّل (الحزم الداخلية) ومعه المزوّد | المزوّد وحده | المزوّد |
| الرابط بين الاثنين | بديهي — فطرفٌ واحد يحمل الأمرين أصلاً | العقد: audit_contract_event يقرن هوية العميل والمزوّد لكل عقد (server/db_migrations.go:234-251) | بديهي |
| النتيجة | نسبةٌ كاملة للتصفح لكل ما حمله المزوّدون المتواطئون | نسبةٌ كاملة للتصفح لكل ما حمله المزوّدون المتواطئون | نسبةٌ كاملة للتصفح، ومع ذلك يعرف المزوّد عنوانك بلا معونة |
الخلاصة الأمينة: الجلسة المختومة لا تدافع ضد التواطؤ بين المشغّل والمزوّد. فهي تزيل قدرة المشغّل المستقلة على قراءة حركة بياناتك؛ ولا تمنع مزوّداً يرى وجهاتك أصلاً من تسليمها إلى مشغّل يعرف من أنت أصلاً. وسجلُّ العقد الذي يصل الاثنين ليس تسريباً — إنه المحاسبة التي تقوم عليها الشبكة.
والذي يشتريه الختم أمام هذا الخصم هو حدُّ نطاق: فمع تفعيله، لا تحتوي رؤيةُ المشغّل نفسه أي وجهات، فيتطلب التواطؤُ تعاونَ المزوّدين المعيّنين الذين حملوا الحركة المعيّنة، في وقت حملها، بدل استعلام عن سجلات يحملها المشغّل وحده. وذلك فرقٌ ذو معنى في الجهد وفي ما يستطيع الإفصاحُ المُكرَه بلوغه بأثر رجعي (§10). وهو ليس حصانة، ولا يمنح الحصانةَ أيُّ ترتيب لثلاثة أطراف يختار فيه أحدُهم الآخرين.
الجواب البنيوي في التصميم، وهو غير منشور في الشبكة. يدعم بروتوكولُ السلك والعميلُ سَلسلة وسطاء مزوّدين إضافيين — MaxMultihopLength = 8 (connect/connect.go:13,214-233)، وIntermediaryIds في CreateContract (connect/protocol/transfer.pb.go:1516)، وقبولٌ عند العميل في connect/ip_remote_multi_client_api.go:296-312، وسباكةٌ عند الخادم في server/controller/connect_controller.go:560. ونقطةُ نهاية الاكتشاف الحية لا تملأ الحقل أبداً — فـFindProvidersProvider يُبنى في موضعين بالضبط ولا يضبطه أيٌّ منهما (server/model/network_client_location_model.go:3186-3190,3296-3303) — فالشبكةُ المشحونة تُسند سلاسل بطول واحد. فسَلسلةُ المزوّدين قدرةٌ في البروتوكول لا خاصيةٌ في النشر، واقتباسُ الرقم 8 بوصفه عددَ قفزات مضلِّل.
7. مفاتيح هوية المزوّدين، وهل يستطيع المشغّل استبدال واحد منها
هذا هو القسم الأجدر بالهجوم، لأن الجواب مزعج والمصدرُ نفسه يقول ذلك.
7.1 الإصدار والربط
كلُّ connect.Client — أي عميلُ المزوّد، وكلُّ عميل من عملاء نافذتك — يحمل زوج مفاتيح Ed25519 مولَّداً داخل العملية بـClientKeyManager (connect/transfer_key.go:76-100، وهو استدعاءُ ed25519.GenerateKey الوحيد في الأشجار الثلاث). وهو طويلُ العمر حيث تُحفظ البذرة وتُعاد قراءتها، وذلك هو عميل المزوّد، وطازجٌ لكل عملية حيث لا تُحفظ، وذلك هو عملاء النافذة؛ ويغطي §9 الفرق ولماذا يهمّ. والنصفُ الخاص لا يغادر العملية أبداً؛ وبذرةٌ بحجم خاطئ خطأُ بناءٍ قاطع لا هويةٌ طازجة صامتة (:84-94). والنصفُ العام يُنشر إلى المنصة في رسالة تحكم ClientKey (connect/protocol/transfer.proto:501-513) ويُخزَّن على جانب الخادم في Redis عند ckey_ بلا انتهاء صلاحية — وRedis هو مصدر الحقيقة، ولا يوجد جدول SQL (server/model/network_client_key_model.go:14-59).
فالربطُ إذن هو client_id → public key، والمشغّلُ يصدر client_id ويحمل الخريطة. ولا يوجد مرساة خارجية: فالمعرّفات لا تُشتق من المفاتيح، ولا يوجد سجلُّ شفافية ولا DHT. والبديلان كلاهما مسجَّلان في التصميم بوصفهما دُرسا وأُجّلا (connect/DESIGNNOTES.md §3.7، «البدائل المؤجَّلة»).
7.2 التدوير والإبطال
إعادةُ النشر تكتب فوق القديم — فتعليقُ SetClientKey نفسه يقول: «مفتاحُه client_id (التدوير يكتب فوقه)» (server/controller/connect_controller.go:810-813). ويُحذف المدخل حين يُقلَّم معرّفُ العميل (network_client_key_model.go:61-71، ويُستدعى من RemoveDisconnectedNetworkClients). ولا يوجد تدوير مجدول، ولا انتهاء صلاحية، ولا قائمة إبطال. وعميلُ المزوّد يحفظ مادة مفتاحه ويعيد قراءتها، فهويته مستقرة عبر إعادات التشغيل (sdk/device_local.go:2874-2889,2926-2935؛ sdk/local_state.go:418-461) — وعلى Android، مستقرة عن قصد عبر مسح الخروج التلقائي من الحساب كذلك (§9.2). والعميلُ الذي لا بذرة محفوظة له يولّد هوية طازجة عند كل بدء عملية، وهو ما يفعله عملاء نافذتك. وتغييراتُ المفاتيح في منتصف الجلسة مرفوضة: فـSetPeerClientPublicKey أولُ كتابة تفوز، والمفتاحُ اللاحق المختلف يُسجَّل ويُتجاهَل (connect/transfer_encrypt.go:1787-1816).
7.3 التحقق، والدفاعان
- الدفاع 1، ربطُ الشهادة الموقَّع. يوقّع المزوّد سلسلةَ شهادات TLS العابرة الخاصة به بمفتاح Ed25519 وينشر الاثنين (
connect/protocol/transfer.proto:486-498). وتُرفق المنصةُ السلسلةَ والتوقيعَ ومفتاحَ المزوّد العام بكل عقد يسمّي ذلك المزوّد (:340-368،:388-406). ولا يقبل العميلُ السلسلة إلا إذا تحقّق التوقيع تحت مفتاح المزوّد العام، ثم يفحص الشهادة المقدَّمة في المصافحة في مقابل السلسلة المقبولة (connect/transfer.go:3930-3934,4006-4018). - الدفاع 2، إثباتُ الهوية داخل المصافحة. بعد مصافحة TLS يوقّع كلُّ جانب مخرجَ المصدِّر بحسب RFC 5705 تحت الوسم
urnetwork-sequence-identity-proofويرسله بوصفهEncryptedControl(connect/protocol/transfer.proto:460-476). ويُحجب AEAD عن مسار التغليف حتى يتحقق إثباتُ النِّد (connect/transfer_encrypt.go:1492-1498،:1719-1756)، فمن يعترض في الوسط وينهي TLS على ساق ويعيد المصافحة على الأخرى يُنتج مصدِّرَين غير متطابقين ولا يستطيع تزوير التوقيع.
والدفاعان كلاهما يتحققان في مقابل peerClientPublicKey — وتلك القيمة مأخوذة من العقد الذي حرّرته المنصة (connect/transfer.go:6119-6129؛ connect/transfer_encrypt.go:1780-1791).
7.4 هل يستطيع المشغّل استبدال مفتاح مزوّد؟ اليوم: نعم.
بصراحة: المشغّلُ الذي يستبدل الشهادة، وتوقيعَ الشهادة، وdestination_client_public_key في تناسق واحد يهزم الدفاعين معاً ويستطيع أن يضع آلةً في وسط جلسة مختومة. وملاحظاتُ التصميم تقول ذلك بكلمات المستودع نفسه (connect/DESIGNNOTES.md §3.7): «ثغرةٌ متبقية: المنصةُ التي تستبدل الشهادة + التوقيع + destination_client_public_key في تناسق واحد لا تزال تفوز على جانب ربط الشهادة؛ والحركةُ الحاسمة هي تغذية SetPeerClientPublicKey من البحث خارج النطاق بدل العقد. وذلك الفحصُ المتقاطع اليوم للتسجيل فقط.»
والحركةُ الحاسمة المقصودة موجودة ومربوطة، لكنها لا تفعل شيئاً. فمسارٌ غير مصادَق عليه GET /key/ يخدم المفتاح المنشور (server/api/api.go:123-124؛ server/controller/connect_controller.go:826-849)، وSDK المشحونة تركّب جالباً لكل جلسة في مقابله لكل عميل نافذة ولكل عميل مزوّد (sdk/device_local_provider.go:398-420، يُبلَغ من sdk/device_local.go:3434 ومن :90). وعند أول ضبط للمفتاح يجلب العميلُ مفتاح النِّد خارج النطاق ويقارن. وعند عدم التطابق يسجّل:
CONTRACT vs FETCHED peer client public key MISMATCH for <peerId>
— possible platform MITM (today: log only, contract value still trusted)(connect/transfer_encrypt.go:1871-1876). ويستمر الوثوقُ بالمفتاح الذي يزوّده العقد (:520-525، :1839-1849). وترقيةُ السجل إلى رفض موصوفةٌ في تعليق الإعدادات وفي ملاحظات التصميم معاً بأنها خطوةُ التقسية التالية — وذلك قصد تصميمي، لا خاصيةً مشحونة.
وثلاثُ دقائق أخرى ينبغي للمدقّق أن يمسك بها:
- القناة خارج النطاق خارجُ نطاقٍ بالنسبة إلى خط أنابيب العقود، لا بالنسبة إلى المشغّل. فالجلبُ يذهب إلى مضيف واجهة API نفسه لدى المشغّل (
sdk/device_local_provider.go:404) ويقرأ Redis نفسه الذي يكتب فيه محرّرُ العقد. وحتى بعد أن يصير السجلُّ رفضاً، يمسك الفحصُ مشغّلاً غير متسق بين اثنتين من قنواته هو، لا مشغّلاً متسقاً. وإغلاقُ ذلك يتطلب مرساةً لا يتحكم فيها المشغّل — معرّفاتٍ مشتقة من المفاتيح أو سجلَّ شفافية، وكلاهما مسجَّل بوصفه مؤجَّلاً. - الإغفال لا يقلّ فعاليةً عن الاستبدال، وهو أهدأ. فالتحقق من الشهادة يُتخطّى بلا تثبيت حين تكون المجموعة الموثوقة فارغة، ومنه حين تحمل العقودُ حقل
ProvideTlsCertificateفارغاً (connect/transfer.go:4010-4016)، وإثباتُ الهوية لا يمكن التحقق منه إطلاقاً حين يغيب مفتاح النِّد العام (connect/transfer_encrypt.go:1706-1708). وفي الحالين لا تصير الشفرة صالحة للاستعمال أبداً وتجري الحركة نصاً صريحاً (§2.2) بلا أي إشارة يراها المستخدم. فالمشغّلُ الذي يريد قراءة حركة مستخدم بعينه والمفتاحُ مفعَّل لا يحتاج إلى تزوير أي شيء؛ يحتاج إلى إغفال حقل. - أصالةُ العقد مرساتُها المشغّل كذلك. فالمزوّد يتحقق من HMAC العقد بمفتاح سرّ تزويد يولّده المزوّد وينشره إلى المنصة (
server/controller/connect_controller.go:768-779؛sdk/device_local.go:2866-2872). والمشغّلُ يحمل نسخة منه، وهو ما يتيح له تحرير العقود أصلاً. وذلك متوقَّع من سلطة محاسبة، لكنه يعني أن «العقد أصيل» ليست عبارةً مستقلة عن المشغّل.
ماذا يقوّض هذا وماذا لا يقوّض. إنه لا يمسّ عمى المزوّد عن الهوية، فذاك لا يتوقف على أي توزيع مفاتيح. لكنه يعني أن عمى المشغّل عن المحتوى، على المسار المختوم، يقوم حالياً على أن يوزّع المشغّلُ المفاتيح بأمانة — وتلك خاصيةُ سياسة وراءها آليةٌ تشفيرية مبنيةٌ في معظمها، لا خاصيةً تصمد بعدُ في وجه مشغّل معادٍ. وأي وثيقة من وثائق URnetwork تصف الجلسة المختومة بأنها تجعل عمى المشغّل غير مشروط فهي تبالغ، وهذه الوثيقة تنسخ تلك الصياغة.
8. التوقيت وربط الحركة، والمراقب السلبي العالمي
8.1 لا توجد دفاعات ضد تحليل الحركة. ولا واحد.
لا تشحن URnetwork أي حركة تمويه، ولا حشواً، ولا خلطاً، ولا تأخيرَ تجميع، ولا تشكيلاً للحركة على بيانات المستخدم. وقد فُحص هذا فحصاً مستوفياً عبر connect وsdk وserver:
- لا يوجد في أي موضع أي مولّد لحركة زائفة أو خادعة أو صورية أو تمويهية.
- وAEAD حافظٌ للطول بالبناء: فطولُ النص المشفّر هو nonce + النص الصريح + الوسم (
connect/transfer_encrypt.go:305,340). ولا يحمل أي protobuf فيconnect/protocol/حقلَ حشو، والتأطيرُ بادئةُ طول مجرَّدة من 4 بايتات (connect/message_framer.go:28-31). - والدمجُ على جانب الإرسال بلا تأخير صراحةً: «لا يوجد انتظارُ تجميع: فالتسلسل لا يأخذ Pack ثانية إلا وهي مصطفّة أصلاً» (
connect/transfer.go:387-392). وكلُّjitterفي الأشجار تذبذبُ تراجعٍ في إعادة الاتصال أو توزيعٌ لعمر القناة، لا تشكيلاً للحركة. وضغطُ الإقرارات (connect/transfer.go:272) يؤخّر الإقرارات وحدها، لخفض حجم رسائل الترحيل. - والموضعُ الوحيد الذي تُنظَّم فيه سرعة حركة المستخدم أصلاً هو حدُّ
WritePacketsPerSecondفي النقل بهيئة DNS (connect/transport_pt.go:63,232-246)، وهو موجود ليكون لطيفاً بالمحلِّلات وينطبق على أقل أوضاع النقل تفضيلاً وحده. واستعلاماتُ «الضخ» الخاملة فيه بطول متميّز عن الحاملة للبيانات، فهو لا يخفي حجماً ولا معدلاً.
ولذلك: الخصمُ الذي يراقب الحركة الداخلة إلى جهازك والحركة الخارجة من المزوّدين الذين يحملونها يستطيع ربط الاثنين بالحجم والتوقيت. وURnetwork لا تدافع ضد ذلك الخصم. وهذه هي العبارة نفسها التي تقولها Tor عن الربط من طرف إلى طرف، وهي تنطبق هنا بهامش أقل، لأن هدف تصميم URnetwork هو انخفاض زمن الاستجابة — وهو بالضبط ما يجعل الربط أيسر. فمسارٌ بأربع سيقان محدودُ زمن الاستجابة مقايضةٌ مقصودة أمام تأخير شبكة الخلط المضاف، وهذا هو الجانب الذي يدفعه المستخدم من تلك المقايضة. وعدُّ ساق الموسّع لا يغيّر ذلك: فتلك القفزة تمرّر الجلسة المشفّرة إلى المشغّل من دون أن تنتهي عندها، فهي لا تضيف طبقةً يقشرها المراقب ولا تأخيراً يضيّعك فيه.
وأمران يُخلط بينهما وبين الدفاعات أحياناً وليسا كذلك. فالموسّعاتُ ووسائلُ النقل المشكَّلة (connect/net_resilient.go:112-215، connect/transport_pt.go:18-45) تستهدف الحجب المبني على الفحص العميق للحزم، والطبقةُ المرِنة تعطّل نفسها بمجرد قيام المجرى (net_resilient.go:102,146-161) — فهي لا تمسّ سجلات طور البيانات أبداً. ومخازنُ تذاكر جلسات TLS لا تُشارَك عن قصد بين مسارات الخروج كي لا يستطيع خادمٌ ربطها عبر تذكرة مستهلَكة (connect/net_tls.go:38-42,99-103)؛ وذلك عدمُ قابلية التذاكر للربط، لا تحليلَ حركة.
ولا شيء في المصدر يقرّ بربط الحركة بوصفه حداً: فالبحث عن traffic analysis وtiming correlation وtraffic correlation وglobal adversary عبر الأشجار الثلاث كلها يعيد صفر نتيجة. ونموذجُ التهديد داخل المستودع (connect/DESIGNNOTES.md §3.7) كله عن اعتراض المشغّل في الوسط. وهذه الوثيقة هي أول موضع تُكتب فيه الثغرة.
8.2 نافذة المزوّدين المتعددين ليست آلية مضادة للربط
تخرج الحركةُ عادةً عبر عدة مزوّدين في آن واحد — بين ثلاثة وثمانية شائعاً عبر النافذتين — والتثبيتُ لكل موقع يُبقي موقعاً معيّناً على مزوّد واحد (connect/ip_remote_multi_client.go:138-158,1234-1240). وذلك يحدّ فعلاً كم يرى أيُّ مخرج واحد. لكن مسوّغ تصميم النافذة في المصدر هو الموثوقية من أوله إلى آخره — تخفيفُ الوجهات السيئة، وإعادةُ التحجيم الموزونة بالصحة، وكشفُ الثقب الأسود (:27-52) — والتعليقُ الوحيد الذي يقول «ألفةٌ أقل أكثرُ خصوصية» يجلس على ClientAffinityTimeout، وهو مقبضٌ مُعلَّق كتعليق (:587-591، ومرة أخرى في الافتراضيات عند :220)، بينما يُشحن DestinationAffinity بقيمة true لأسباب موثوقية (:270). فتعددُ هوية الخروج فائدةٌ حقيقية ومن العدل ادّعاؤها؛ أما ادّعاؤها بوصفها دفاعاً مصمَّماً ضد الربط فلا يسنده الكود.
8.3 المراقب السلبي العالمي: خارج النطاق
الخصمُ السلبي العالمي — القادر على مراقبة حصة كبيرة من وصلات الإنترنت في آن واحد — خارج النطاق، وURnetwork لا توفّر أي دفاع ضده. فمع انعدام الحشو وانعدام حركة التمويه، يربط ذلك الخصمُ التدفقات عبر المرحّل والمزوّدين مباشرةً. وهذا هو الموقف نفسه الذي تتخذه Tor، وخلافاً لـTor، لا تضيف URnetwork حتى تأخيراً لكل قفزة يرفع الكلفة.
والمختلفُ فعلاً، والجدير بالذكر من دون تضخيمه: أن مجموعة الخروج جمهورٌ متبدّل من اتصالات سكنية مستقلة لا نطاقاتُ عناوين منشورة لمشغّل واحد، فعلى الخصم أن يراقب مجموعة أوسع ومتحركة من النقاط ليغطي مستخدماً واحداً، ولا يمكن تعدادُ تلك النقاط من قائمة خوادم. وذلك يرفع الكلفة. ولا يغيّر النتيجة لخصم يستطيع أصلاً رؤية الطرفين.
9. معرّفات الأجهزة وقابلية الربط
9.1 ما يستطيع المزوّد ملاحظته عنك
قيمةُ SourceId في العقد معرّفُ عميل لكل خانة في النافذة، لا جهازك. فـStoredContract.SourceId هو client_id للمتصل المصادَق عليه (server/controller/connect_controller.go:461-463؛ ويحلّله المزوّد عند connect/transfer.go:6088-6106). والمولّدُ يسكّ معرّف عميل ورمز jwt ومعرّف نسخة طازجة لكل دخول نافذة ويزيلها عند التفكيك — والمصدرُ يقول ذلك مباشرةً: «يسكّ مولّدُ الـapi معرّفَ عميل منصة عابراً (مع معرّف نسخة طازج) لكل دخول نافذة ويزيله عند التفكيك» (connect/ip_remote_multi_client_identity.go:10-15؛ ويُسكّ عند connect/ip_remote_multi_client_api.go:326-345، ويُطلَق عند :410,473).
لكن تلك الهويات يُعاد استعمالها عن قصد حتى أربع ساعات، على كل مسار — لا على المستضاف وحده. فالجهاز يركّب مخزن هوية محلياً خاصاً به ما لم يكن مستضافاً (sdk/device_local.go:1204-1208)، وهويةُ النافذة المخزَّنة تُعاد أمام الوجهة نفسها حتى تبيت: windowIdentitiesStaleAfter = 4 * time.Hour (sdk/window_identity_store.go:44-52). والغرضُ إبقاء تدفقات NAT لدى مزوّد حيّة عبر إعادة تشغيل (connect/ip_remote_multi_client_identity.go:17-23). والكلفةُ أن المزوّد يستطيع أن يرى SourceId نفسه يظهر منك مرة أخرى عبر إعادات تشغيل التطبيق داخل تلك النافذة. قل أربع ساعات، لا «عابر».
ومفتاحُ هوية العميل Ed25519 طازجٌ لكل عميل نافذة، على مسار الخروج. فإعداداتُ عميل النافذة تُبنى من DefaultClientSettingsWithBufferSize طازجة (sdk/device_local.go:3434-3437)، وهي لا تحمل ClientKeySeed (connect/transfer.go:166-183)، فيولّد ClientKeyManager زوجَ مفاتيح جديداً (connect/transfer_key.go:96). واللقطةُ المحفوظة للنافذة تخزّن معرّف العميل ورمز jwt ومعرّف النسخة فقط — بلا بذرة مفتاح (sdk/window_identity_store.go:46-52)، فالهويةُ المستعادة تنشر مفتاحاً جديداً. ومع إيقاف تشفير ما بعد الكم، لا يُقدَّم أي إثبات هوية إطلاقاً (connect/ip_remote_multi_client.go:9149-9157).
وعنوانُ مصدر النفق لكل جلسة ومنخفض العشوائية. فـSDK تُسند لواجهة TUN عنوان RFC1918 عشوائياً — «عنوان 10.x.y.h عشوائي (بحسب RFC1918، وبهيئة DHCP)» (sdk/device_local.go:566-571,1070-1090) — يُولَّد بثُماني مضيف بين 2 و254 على أصغر 10.a.b.0/24 غير متعارض (connect/tun.go:323-348). ويُحسب في المُنشئ ولا يُحفظ أبداً، فهو يتغير مع كل جلسة. والمزوّدُ يراه فعلاً: فهو حقلُ المصدر في كل حزمة منفَّقة، والمزوّدُ يبني حالة NAT على مفتاحه (connect/ip.go:742,1009-1020,1151). ونحو 253 قيمة بصمةٌ ضعيفة لكل جلسة، لا معرّفاً عبر الجلسات.
9.2 مفتاح هوية دور المزوّد دائم
إن كنت تشارك اتصالك أيضاً، فعميلُ المزوّد لديك يحمل زوج مفاتيح Ed25519 طويل العمر تُحفظ بذرته في التخزين المحلي (sdk/local_state.go:418-461، .device_local_key_material، وبصيغة JSON client_key_seed؛ ويُطبَّق عند sdk/device_local_key_material.go:54-70). وخلافاً لعملاء النافذة، يُحفَظ ذلك المفتاح عن قصد عبر مسح الخروج التلقائي من الحساب — وتعليقُ Android صريح: «امسح حالة مصادقة بائتة أو جزئية من دون تدوير هوية الجهاز. فمادةُ مفتاح الهوية مرتبطة بالجهاز، لا بالجلسة» (android/.../MainApplication.kt:636-647). فتجديدُ الرمز، والتعافي من المصادقة الجزئية، وإعادةُ تسجيل الدخول بعد 30 يوماً من الخمول، تنتج كلها client_id جديداً وdevice_id جديداً بينما يبقى مفتاح Ed25519 العام كما هو. ولا يدوّره إلا خروجُ المستخدم الصريح من الحساب (sdk/local_state.go:639-644).
وذلك المفتاح منشور، ومختوم في كل عقد يسمّي هذا العميل وجهةً (server/controller/connect_controller.go:413-415,468)، وقابل للقراءة من أي أحد: فـGET /key/ غير مصادَق عليه بحكم التصميم (server/api/api.go:123-124؛ server/controller/connect_controller.go:826-829). فيستطيع أي طرف — لا مزوّدٌ خدمته أنت وحده — أن يحلّ أي معرّف عميل إلى مفتاحه العام وأن يجمّع معرّفات العملاء التي تتشارك مفتاحاً واحداً. وبالنسبة لحساب مزوّد، ذلك مقبضٌ دائم عبر الجلسات وعبر client_id وعبر device_id. وهذه كلفةٌ حقيقية للتزويد، وهي غير موثَّقة في أي موضع آخر من هذه المجموعة.
9.3 عند المشغّل، كل شيء يترابط
client_idلا يُبطَل أبداً. وتعليقُ الكود نفسه: «معرّفات العملاء عناوين فريدة عالمياً تعادل IPv6 / ولا تُبطَل أبداً بعد تخصيصها، حفاظاً على الأمان وعلى سجلات التدقيق» (server/model/network_client_model.go:64-67). والعميلُ الأعلى مستوى يُعطَّل بعد 30 يوماً من الخمول (TopLevelClientIdleExpiration،:2289) ويُحذف حذفاً قاطعاً بعد 30 يوماً من ذلك (NetworkClientReapAfterDeactivate،:2269)، متتالياً إلى صف الجهاز وإلىckeyفي Redis (:2537).device_idهو لكل تسجيل دخول، لا لكل عتاد ولا لكل تثبيت: فيُسكّ واحد طازج مع كل عميل أعلى مستوى (:332-352)، والكودُ يشير إلى ما ينتج عن ذلك من «تبدّل هوية (device_id طازج لكل تسجيل دخول)» (:2280). وعملاءُ النافذة يرثونه (:356-380) ولا يُرسَل إلى مزوّد أبداً.- ورمزُ الشبكة رمزُ JWT مدته 24 ساعة (
server/jwt/by_jwt.go:35-37,188)، تجدّده SDK عند منتصف عمره — نحو 12 ساعة — مع تذبذب (sdk/device_token_manager.go:107-124,165). وتجديدُ الرمز لا يدوّر معرّف العميل؛ فالمطالبة نفسها يُعاد سكّها (server/model/network_client_model.go:102-125). - و
audit_contract_eventيسجّل هوية العميل والمزوّد لكل عقد (server/db_migrations.go:234-251). وclient_reliabilityيصل تجزئةَ كتلة العنوان بمفتاح مباشرةً بمعرّف عميل، لكل كتلة: فالمفتاحُ الأساسي الأصلي ذو الأعمدة الأربعة (server/db_migrations.go:2083-2106) اختُصر لاحقاً إلى(block_number, client_address_hash, client_id)(:2191-2195)، والجدولُ المقسَّم الحي يستخدم الثلاثة نفسها (server/model/network_client_reliability_partition_model.go:194-195)، مع بقاءnetwork_idحمولةَ فهرس (:63,631-634). والاحتفاظُ 30 يوماً (server/model/network_client_reliability_model.go:42,687-721؛ الأقسامُ اليومية تُسقط كاملة). - و
network_client.auth_timeآخرُ ظهور دائم يُحتفظ به 30 يوماً (server/model/network_client_model.go:2269,2289)؛ وصفوفُ الاتصالات المقطوعة تُقلَّم عند 8 ساعات (server/taskworker/work/network_client_work.go:85). - والمعرّفاتُ على مستوى الحساب، عند المشغّل وحده: بريدٌ إلكتروني أو هاتف صريحاً في
network_user.user_auth، ورمزُ JWT الكامل لمزوّد الهوية الخارجي في تسجيلات الدخول بـSSO، ومعرّفاتٌ صريحة عند كل محاولة تسجيل دخول فيuser_auth_attempt، وعناوينُ محافظ، وصفوفُ دفع، وحافّةُ إحالة دائمةnetwork_referralتقول من دعا من، وصفوفُaudit_provider_eventتحمل نصوصاً حرفية للدولة والمنطقة والمدينة في مقابلnetwork_idوdevice_id، غير مرتبطة بتقليم الاتصالات عند 8 ساعات (review/verified/PRIVACY-ENFORCEMENT.md§1.4). - و
User-Agentتسجّله قائمةُ السماح ذات الترويسات الخمس (server/http_log.go:15-29). وهو المدخل الوحيد بين الخمسة الذي يشكّل سطح بصمات.
9.4 جسر WireGuard يربطك عبر المزوّدين
يُخصَّص لكل عميل WireGuard عنوانُ نفق خاص ثابت من مجمّع مخلوط من 10,000,000 عنوان RFC1918 (server/model/network_client_proxy_model.go:1034,1038-1118)، يُكتب في الإعداد بوصفه عنوان الواجهة (:756-771)، وهو لا يُسوَّى قبل الخروج — فتعليقُ FIXME في المصدر نفسه يقول: «حالياً عنوان ipv4 للعميل يُمرَّر إلى مزوّدي الخروج / وهذا يمكن أن يتيح تتبّع عنوان ipv4 واحد لعميل عبر عدة مزوّدين» (proxy/wg.go:23-25). وهو عنوان خاص لا عنوانك الحقيقي، والموقعُ الوجهة لا يراه أبداً. لكن كل مزوّد في نافذتك يرى عنوان المصدر نفسه، فـتستطيع المزوّدات المتواطئة أن تعرف أن تلك التدفقات تخص عميلاً واحداً — وهي بالضبط الخاصية التي توفّرها نافذةُ المزوّدين المتعددين لولا ذلك. ومع المحلِّل الثابت 1.1.1.1 (§3.2) وغيابِ الجلسة المختومة على ذلك المسار، يكون جسرُ WireGuard أقلَّ الطرق خصوصيةً لاستخدام الشبكة. والتطبيقاتُ وSDK هي الأكثر خصوصية.
10. المطالب القانونية
الاختصاص القضائي. BringYour, Inc. شركةٌ في ولاية ديلاوير (docs/legal/ur.xyz/terms.md:16,25) بعنوان بريدي في سان فرانسيسكو (docs/legal/terms.md:269-271). وتضع شروطُ ur.io القانون الحاكم ومقر التقاضي في مقاطعة هاريس بولاية تكساس (docs/legal/terms.md:315-321)؛ وتضع شروطُ ur.xyz ديلاوير (ur.xyz/terms.md:223-229). وكلُّ ذلك أمريكي، وكلُّه في متناول الإجراءات الإلزامية الأمريكية، بما فيها إجراءٌ يصل مع أمر بمنع الإفصاح. وتنص الشروط على أن المشغّل «قد يراقب المعلومات ويفصح عنها حيث يُلزَم بذلك بحكم القانون أو بأمر حكومي» (docs/legal/terms.md:204-206).
ماذا يبلغ طلبٌ على المشغّل. بترتيب تنازلي في قوة كشف الهوية: من هو الحساب — بريدٌ إلكتروني أو هاتف صريحاً، ورمزُ JWT لمزوّد الهوية الخارجي في تسجيلات الدخول بـSSO، وعناوينُ المحافظ، وسجلاتُ الدفع التي ترتبط بهوية حقيقية عبر Stripe أو Apple أو Google Play أو tx_signature على السلسلة؛ ومتى اتصل ومن أي مدينة، لكل اتصال؛ وأي المزوّدين استخدم وكم بايت؛ وتجزئةٌ بمفتاح لكتلة /29 أو /56 التي اتصل منها، مع منفذ المصدر صريحاً. والأطرافُ الثالثة تحمل أكثر: فمعالِجات الدفع المسمّاة في §1 تحمل هويةً لا يخزّنها المشغّل أبداً، وtx_signature في Solana يُحلّ إلى محفظة على سلسلة عامة.
ماذا لا يبلغ الطلب، لأنه غير موجود. لا يحتوي سجلُّ النقل أي حقل وجهة ولا مضيف ولا URL ولا SNI ولا منفذ ولا نطاق في أي موضع (review/verified/PRIVACY-ENFORCEMENT.md §1.2). وسجلاتُ الدعم المرفوعة تُتلَف عند الاستلام. ولا يوجد سجلُّ تصفح يُقدَّم، على أي مسار، مختوماً كان أو غير مختوم — وهذه أقوى خاصية بنيوية في هذه الوثيقة، وهي قائمة سواء أحسن أحدٌ التصرف أم لم يحسن.
ماذا يبلغ الطلب استشرافاً. كلُّ ما سبق عن سجلات مخزَّنة. أما الطلبُ الذي يُكرِه على سلوك مستقبلي فأمرٌ آخر، و§7.4 هو موضع عضّه: فالمشغّلُ المُكرَه على اعتراض مستخدم بعينه يستطيع اليوم أن يستبدل مادة مفاتيح مزوّد أو يغفلها ويقرأ حركة ذلك المستخدم حتى مع تفعيل تشفير ما بعد الكم، ولا تكون الإشارةُ الوحيدة إلا سطر سجل على الجهاز. فالجلسةُ المختومة ترفع كلفة الإفصاح بأثر رجعي. وهي لا تقاوم، في صورتها الحالية، مشغّلاً مُكرَهاً من الآن فصاعداً.
حذف الحساب جزئي. فـRemoveNetwork قائمةُ حذف مكتوبة يدوياً، لا تتالياً في قاعدة البيانات (server/model/account_model.go:108-260). وهي تزيل صفوف network_user وسجلاتِ مصادقتها (كلمة المرور، وSSO، والمحفظة، وعبارة الاستعادة)، وصفَّ network ومدخلَ فهرس الاسم، وتجدول إلغاء اشتراك Stripe. وهي لا تحذف account_payment ولا stripe_customer ولا apple_subscription_transaction ولا صفوف solana_payment_intent المكتملة ولا network_referral ولا صفوف الأجهزة ولا صفوف التدقيق؛ فتلك تشيخ على جداولها الخاصة — أحداثُ التدقيق عند 180 يوماً (server/model/audit_model.go:984,1018) — أو، للمدفوعات المكتملة على السلسلة، لا تشيخ إطلاقاً (server/model/solana_payment_intent_model.go:386-400 لا يحذف إلا النوايا التي tx_signature فيها معدوم). والحذفُ يكتب صفاً أيضاً: حدثَ AuditEventTypeNetworkDeleted مفتاحُه network_id المحذوف (account_model.go:255-257). وعبارةُ سياسة الخصوصية «حذف حسابهم والمعلومات الشخصية المرتبطة به» (docs/legal/privacy.md:69) أوسع مما يفعله الكود.
لا توجد شمعة إنذار، ولا تقرير شفافية، ولا إجراء منشور لإنفاذ القانون. وقد تحقّق غيابُ ذلك عبر docs/ وعبر مصدر موقع ur.io. والمؤشرُ الوحيد إلى الإجراءات القانونية في أي موضع يوجّه من يبلّغ إجراءً إلى الحصول على الوكيل المسجَّل في ديلاوير من شعبة الشركات بولاية ديلاوير (docs/legal/ur.xyz/terms.md:262)؛ و[email protected] نطاقُه بلاغات الثغرات (docs/legal/vdp.md:42) و[email protected] هو عنوان الإشعارات التعاقدية العام. ووثائقُ مقارنة URnetwork نفسها تقرّ بهذا أصلاً أمام منافسين ينشرون واحدة، وهذه الوثيقة تكرّره بدل تليينه.
سياسة الخصوصية صامتة حيث ينبغي أن تكون محدَّدة. فهي تنص على أن «كل المعلومات الشخصية التي نجمعها من المستخدمين وعنهم محصورة في عنوان البريد الإلكتروني أو رقم الهاتف» وأن الجمع يحدث «منك مباشرةً حين تقدّمها» (docs/legal/privacy.md:29-37).
مسودةٌ سابقة من هذا القسم سمّت ذلك وصفاً ناقصاً بحجة أن الكود يخزّن فئات أكثر مما تسمّيه السياسة. وقد سُحب ذلك التأطير في 2026-08-09 بوصفه خاطئاً. فكلُّ ما تجرده هذه الوثيقة عدا ذلك إما بياناتُ حساب ينشئها المستخدم بالتسجيل أو بالدفع (فمفتاحُ الوصل مع Stripe موجود لأن أحداً وافق على أن يُفوتَر)، وإما ليس معلومات شخصية أصلاً: منفذُ مصدر، وتجزئةُ كتلة بمفتاح لا يعكسها المشغّل. أما هل يمكن من حيث المبدأ أن يعكس تجزئةً بمفتاح حائزُها نفسُه فذلك تحفّظ هندسي حقيقي — §5 يذكره، والتدويرُ الغائب ضعفٌ حقيقي — لكن قيمةً لا يبحث عنها أحد ليست فئةً من المعلومات الشخصية قصّرت السياسةُ في إعلانها.
أما ما ينقص السياسةَ فعلاً فمختلفٌ وأضيق: لا مدة احتفاظ، ولا بيان تسجيل، ولا قسم عن إنفاذ القانون أو الإفصاح الحكومي. فالكلماتُ الاحتفاظ والسجل وعنوان IP وأمر الإحضار والإجراء القانوني لا تظهر فيها. وذلك مهم لأن انضباط الاحتفاظ موجودٌ في الكود وأقوى مما تدّعيه السياسة — و§5.1 يعرض النوافذ المتحقَّق منها. فقارئُ السياسة اليوم لا يستطيع أن يُلزم المشغّل بأيٍّ منها.
11. ما لا تدافع URnetwork ضده
ثلاثةُ أمور قائمة، ويستحق ذكرها قبل القائمة التالية، كي تُقرأ القائمةُ حداً لا حكماً. فعلى مسار مُرحَّل لا يعرف المزوّد أبداً من أنت، ولا يغيّر ذلك أي إعداد ولا أي إصدار مزوّد (§2). ولا يوجد حقل وجهة ولا مضيف ولا URL ولا SNI ولا منفذ ولا نطاق في أي موضع من سجل النقل، فلا يوجد سجلُّ تصفح يُكرَه على تقديمه أو يُسرَّب أو يُباع (§5 و§10). وكلُّ ادّعاء من هذه الادعاءات قابل للقراءة في مصدر عام، ولهذا تستطيع هذه الوثيقة أن تكون محددة في إخفاقاتها هي.
وكلُّ ما دون ذلك إخفاق. مذكورٌ بلا مواربة؛ وكلُّ بند مشروح أعلاه.
- الربط بالتوقيت وبتحليل الحركة من طرف إلى طرف. لا حشو، ولا حركة تمويه، ولا خلط. والخصمُ الذي يراقب شبكة وصولك والمزوّدين الذين يحملون حركتك يستطيع ربطهما. §8.1.
- خصمٌ سلبي عالمي. خارج النطاق كلياً. §8.3.
- التواطؤ بين المشغّل والمزوّد. المشغّل يعرف من أنت، والمزوّد يعرف إلى أين ذهبت، وسجلُّ العقد يصلهما. والختمُ يضيّق ما يحمله المشغّل وحده؛ لكنه لا يكسر الوصل. §6.2.
- مشغّلٌ مُكرَه أو معادٍ يستبدل مادة مفاتيح مزوّد أو يغفلها. فاليوم الفحصُ المتقاطع الذي كان سيمسك ذلك يسجّل ويتابع. §7.4.
- الخفضُ الصامت للجلسة المختومة — مع إيقاف تشفير ما بعد الكم. ففي ذلك الوضع يتراجع أيُّ إخفاق (في المصافحة، أو في إثبات الهوية، أو بمفتاح مفقود) إلى النص الصريح بلا أي إشارة يراها المستخدم. وأُصلح للوضع الذي يطلبه، في 2026-08-10: فمع تفعيل المفتاح يعمل العميل بالفشل المغلق ويرفض إرسال بيانات التطبيقات نصاً صريحاً أو قبولها. والذي يبقى في الوضعين معاً هو المؤشر الغائب — فلا تطبيق يبيّن أمختومٌ اتصالٌ بعينه أم لا. §2.2.
- مزوّدٌ خبيث يعبث بالحركة غير المشفّرة. فـHTTP نصاً صريحاً يُمرَّر من دون تغيير؛ والمزوّد في موضع نقطة اتصال معادية. §3.
- اختراق الطرف. البرمجيات الخبيثة، أو نظامُ تشغيل مخترَق، أو امتدادُ متصفح معادٍ، أو أيُّ شخص بجهازك غير المقفل. ولا شيء في منتج شبكي يعالج هذا.
- التعرّف من جانب الوجهة. فملفات تعريف الارتباط، وتسجيلات الدخول، وبصمُ المتصفح، وسلوكُ الحساب، تعرّفك للمواقع التي تزورها بغضّ النظر عن كيفية وصول الحزم. وتغييرُ عنوان خروجك لا يجعلك مجهولاً لخدمة تسجّل الدخول إليها.
- هوية قناة الدفع. فالبطاقاتُ وقنواتُ متاجر التطبيقات تضع هويتك لدى المعالِج وإن كان المشغّل لا يخزّنها. وUSDC على السلسلة تترك
tx_signatureعاماً. - مزوّدو Sybil. يستطيع أي أحد أن يزوّد، بلا تصديق ولا رهن. ويستطيع طرفٌ واحد تشغيل مزوّدين كثر، ومنهم المشغّل.
- غيابُ الختم على مسارَي المتصفح والبروكسي. فامتدادُ المتصفح بلا إعداد لتشفير ما بعد الكم، وعلى تلك المسارات يشغّل المشغّلُ العميل. §2.4.
- قابلية الربط عبر المزوّدين على جسر WireGuard. عنوانُ نفق ثابت واحد عبر كل مزوّد في نافذتك. §9.4.
- مقبضُ هوية دائم لكل من يزوّد أيضاً. فمفتاحُ Ed25519 لعميل المزوّد يبقى بعد تدوير معرّف العميل ومعرّف الجهاز بحكم التصميم، و
GET /key/غير مصادَق عليه، فيستطيع أي طرف تجميع معرّفات العملاء التي تتشارك مفتاحاً. §9.2. - الحركةُ التي تراها الشبكة المحلية أثناء نافذة DNS عند البدء. موثَّقة في المصدر بوصفها كلفةً مقبولة. §3.2.
- أيُّ شيء كان تدقيقٌ من طرف ثالث سيجده. فلم يُجرَ أي تدقيق على البروتوكول ولا على كود الخادم.
12. ما تعذّر على هذه الوثيقة إثباته
الادّعاءُ غير المثبَت في نموذج تهديد ادّعاءٌ لا ينبغي أن يكون في الوثائق كذلك. وهذه مفتوحة.
- ماذا يسجّل موزّع حمل المدخل. إعدادُ ترويسات nginx في الشجرة (
xops/.../connect/ingress.yaml:9)، وخدمةُ الاتصال تحدّ المعدل على عنوان مجزَّأ (server/connect/transport_rate_limit.go:65-80)، لكن إعدادَ سجل الوصول الخاص بـnginx لم يُدقَّق. وأيُّ عبارة شاملة بأننا «لا نحتفظ بعنوانك» تتوقف عليه. - هل تبلغ أسطرُ السجل غير المقيَّدة الحاملة للعنوان ولـSNI في §5 تخزيناً دائماً. فهي تُكتب إلى stderr؛ وأين يذهب stderr في الإنتاج، وكم يُحفظ، سؤالٌ يخص النشر لا تستطيع مراجعةُ المصدر هذه الإجابة عنه. والمُتتبِّعُ في المراقبة يكشط فعلاً أنماط
ip:portمن أسطر السجل ويعيد بثّها في نتائج (server/monitor/tailer.go:136,328,333)، وذلك دليلٌ على أن بعض تلك الأسطر على الأقل تقرؤها أنظمة تحتفظ بها. - هل يعيد جهازُ البروكسي على جانب خادم WireGuard كتابةَ مصدر الحزمة قبل تسليم الحزم إلى المزوّدين. فعنوانُ النفق الثابت ورؤيةُ المشغّل للنقطة العامة الحقيقية (
server/proxy/wg_handoff.go:56-67) كلاهما متحقَّق منه؛ أما المسارُ الكامل عبرserver/proxy/proxy_device.goوOpenProxyDeviceفلم يُقرأ من طرف إلى طرف (review/verified/ARCHITECTURE.md، البند 3 غير القابل للتحقق). - هل يمكن أن يحدث حلُّ الأسماء على مسار المتصفح محلياً أبداً. فالامتدادُ يضبط بروكسي HTTPS CONNECT افتراضياً، وهو يحلّ عن بُعد، وحلُّ أسماء SOCKS يمر عبر طالب DoH في النفق (
connect/tun.go:1155-1175). ولم يُختبر سلوكُ DNS للبروكسي في كل متصفح تحت كل إعداد. - الإسهابُ الفعلي في الإنتاج.
BY_LOG_Vقيمته الافتراضية 0 (server/env.go:41-49)، وهذا يكبت تسجيل الوجهات المقيَّد بـV(1)على العميل والخادم — لكن بيان النشر الوحيد في الشجرة يضبطه على2(xops/gitops-unused/.../api/deployment.yaml:47-48)، في دليل اسمهgitops-unused. فعامِل الإسهاب بوصفه علماً في وقت التشغيل، لا ضماناً بنيوياً أبداً. - استقلالُ الأسطول. ينشر المشغّل أعداد المدن والدول الحية من تجميعه هو على المزوّدين المتصلين حالياً والصالحين (
server/model/network_client_location_model.go:1607-1641)، والموقعُ يشتقّه المشغّل من الاتصال الذي يلاحظه بدل أن يعلنه المزوّد (review/verified/ARCHITECTURE.md§6.4). لكن لم يقس أي طرف مستقل الأسطول من الخارج، ولا شيء يتحقق من أن المزوّدين المعروضين على عميل بعينه مستقلون بعضهم عن بعض أو عن المشغّل. فالآليةُ قابلة للفحص في المصدر؛ أما الجمهور فليس قابلاً للفحص من طرف ثالث اليوم. - ربطُ مفتاح الهوية عند إنشاء الحساب. ينص التصميم على توقّع أن «يُسجَّل ربطُ (ClientId، المفتاح العام) عند إنشاء الحساب» (
connect/transfer_key.go:20-30). أما المشحون فعميلٌ ينشر مفتاحه إلى Redis يتحكم فيه المشغّل، ويُخدَم مرة أخرى من واجهة API يتحكم فيها المشغّل. وهل يوجد تسجيلٌ أقوى تشغيلياً لم يمكن إثباته من المصدر؛ فافترض أنه لا يوجد. - هل يستخدم كلُّ مسار إرسال في الجهاز عميلَ نافذة. فالكيُّ العابر لمسار النافذة متحقَّق منه (§9.1). والعميلُ الأعلى مستوى في الجهاز يحمل البذرة الدائمة ويفعّل التشفير بلا شرط (
sdk/device_local_provider.go:90-98)، فأيُّ إرسال يركب العميل الأعلى مستوى — علاقاتُ أنداد الشبكة، ومساراتُ العودة المرافقة — يُوقَّع بالمفتاح المستقر ويحملclient_idالأعلى مستوى المستقر. ولم تُعدَّد تلك المسارات تعداداً مستوفياً. فاقرأ «معرّفات الخروج عابرة» على أنها محصورة بمسار عميل النافذة. - هل يُملأ
RolesوPrincipalأبداً لعملاء المستهلكين العاديين. فهما نصّان يُسنِدهما المشغّل ويُختمان في بايتات العقد الموقَّعة ولا يُضبطان إلا لـProvideMode_Network(connect/protocol/transfer.proto:408-415؛server/controller/connect_controller.go:474-481). ولم يُعثر على دليل على أن التطبيقات تملؤهما، ولم يُدقَّق كلُّ مستدعٍ. ولو مُلئا يوماً لحركة المستهلكين لصارا معرّفَين عبر الجلسات من الدرجة الأولى مرئيَّين للمزوّد. - بقاءُ مادة المفاتيح على المضيفات غير المحمولة. لا يُشار إلى
ClientKeySeedإلا منsdk/local_state.goوsdk/device_local_key_material.goوsdk/device_local.goوsdk/cgo/. والمضيفاتُ التي لا تستدعي تلك تحصل على مفتاح طازج لكل عملية؛ ولم يُتحقق من سلوك Linux وWindows والامتداد وبروكسي الخادم كلٍّ على حدة. - هل مقر التقاضي في تكساس في شروط ur.io مقصود، مع كيان في ديلاوير، وعنوان في كاليفورنيا، ومقر تقاضٍ في ديلاوير في شروط ur.xyz. ولا وثيقة في الشجرة تشرحه. وهذا سؤال للمستشار القانوني، لا نتيجةً.
13. التبليغ
الثغرات: [email protected] وسياسةُ الإفصاح على ur.io/vdp. والتصحيحاتُ على هذه الوثيقة، ومنها الاعتراض على أي حكم فيها، مرحَّبٌ بها بالطريق نفسه — فنتيجةٌ مستقلة تناقض ادّعاءً هنا أنفعُ من الادّعاء.