شخصان يطرحان السؤال نفسه ويحصلان على جوابين متعارضين، لأنهما يقفان في مكانين مختلفين. أحدهما فتح شاشة إعدادات VPN في النظام ويعدل قائمة تطبيقات. والآخر يكتب VpnService.Builder.addDisallowedApplication() في محرر. كلاهما يسميه مرشح VPN لكل تطبيق. واحد فقط منهما يملك التحكم الذي يصفه، ولا أحد منهما يحجب شيئا.

ابدأ من الشاشة التي يراها المستخدم

افتح الإعدادات، وجد مدخل VPN، وانظر إلى الاتصال النشط فعلا. إذا قدم العميل قائمة لكل تطبيق، فتلك القائمة تخص نفق العميل نفسه. لا تنشر المنصة واجهة برمجة عامة تسمح لتطبيق غير معني بقراءة اختيار تطبيقات VPN آخر أو تعديله، لذا لا يستطيع تطبيق ثان إصلاح تلك القائمة للمستخدم.

هذا أول تفرع في الشرح. إذا لم يكن في VPN المثبت هذا الإعداد، فليس هناك ما يلتف حوله بالبرمجة: الميزة غائبة عن المنتج الذي يملك النفق. وإن كان موجودا، فالإصلاح الصحيح في تلك الشاشة، يقوم به من يستطيع فتحها.

تابع الحزمة إلى داخل النفق

حين يبني تطبيقك نفقا، فإنه ينشئ واجهة TUN ويعلن أي تطبيقات يدخل ترافيكها إليها. تحدث نداءات العضوية قبل إنشاء الواجهة، وبعد ذلك تكون مجموعة القواعد ثابتة لتلك الجلسة:

val builder = VpnService.Builder()
builder.addAddress("10.8.0.2", 32)
builder.addRoute("0.0.0.0", 0)
builder.addDisallowedApplication("com.example.bypass")
val tun = builder.establish()   // membership decided here

تنطبق تلك النداءات على النفق الذي أنشأه تطبيقك للتو ولا على غيره. ليست سياسة على مستوى الجهاز، ولا تبقى لعملاء آخرين، ولا تستطيع الوصول إلى VPN شخص آخر. وحين يفشل نداء builder لأن الحزمة لا يمكن حلها، لا تنشأ الواجهة أبدا، وهذا فشل نظيف لا صامت.

لماذا بدا الاستثناء كأنه حجب

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

العمل خلف هذا الانعكاس ليس علامة إعداد. تقرأ حزم IP من واصف النفق، وتقرر لكل تدفق، ثم تمررها عبر مقبس محمي أو تسقطها. كل ما تفشل في معالجته يتوقف ببساطة، ولهذا يبدو نفق نصف مكتمل كشبكة معطلة لا كمرشح عامل. إن كان هدفك الحجب، فخصص ميزانية لمعالجة الحزم وخدمة أمامية وسياسة مكتوبة للترافيك الذي لا تستطيع تصنيفه.

ما الذي ينكسر حين تبنيه بنفسك

يسمح Android عموما بنفق VPN نشط واحد في الوقت نفسه، لذا يتنافس نفق الترشيح ونفق الخصوصية على المقعد نفسه ما لم يدعم المنتجان التسلسل. يغيّر VPN الدائم مع حجب الاتصالات نمط الفشل بطريقة تهم هنا: الترافيك الذي لا يستطيع دخول النفق يُسقط بدل إرساله مباشرة، وهو ما يريده تصميم منع التسرب وما لا تتوقعه جلسة تصحيح.

ظهور الحزم هو الفخ الثاني. قد يفشل حل اسم حزمة تطبيق بـNameNotFoundException، وفي إصدارات Android الأحدث تعتمد مجموعة الحزم التي تراها على الاستعلامات التي أعلنتها. تعامل مع الاستثناء بدل افتراض أن كل اسم يُحل، وأعد قراءة القائمة عند تثبيت التطبيقات أو إزالتها بدل تخزينها للأبد.

تضيف الأجهزة المُدارة مالكا ثالثا. يمكن لسياسة تنقل مؤسسية تعيين VPN لكل تطبيق أو ملف دائم، ولا يستطيع تطبيق عادي تجاوزها. تحقق مما إذا كان الجهاز مُدارا قبل تصحيح شفرتك، لأنه في تلك الحالة قد لا تكون القائمة التي تحاول تغييرها قابلة للتعديل من أي شخص يحمل الهاتف.

اختبره بتطبيق تتحكم به

لا تختبر بالتطبيق الذي تحاول ترشيحه. استخدم تطبيقا ثانيا يمكنك ملاحظة سلوكه الشبكي، وتحقق مما إذا كان ترافيكه يخرج عبر نفقك بينما لا يخرج ترافيك الهدف. إذا بقي الاثنان في الداخل فالسياسة تعمل والهدف مستثنى؛ وإذا لم يخرج أي منهما فالنفق نفسه خاطئ وقائمة التطبيقات ليست المشكلة.

ثم قرر أي ثلاثة أشياء تبنيها فعلا. نفق لكل تطبيق هو واجهة builder، والقائمة جزء من ملفك. جدار ناري للجهاز هو معالجة الحزم بالإضافة إلى دورة حياة يمكنك الدفاع عنها. تغيير VPN شخص آخر ليس مسارا مدعوما على الإطلاق، والجواب الصادق هناك أن الإعداد يخص ذلك المنتج.

مقالات ذات صلة