هل iPhone على VPN؟ ما يمكن لتطبيق iOS أن يراه فعلاً
لا يوجد علم VPN واحد في SDK الخاص بـ iOS. يمكن للتطبيق أن يلاحظ إعداداته الخاصة وإشعار حالة ولقطة وكيل محدودة النطاق، لا أكثر.
إذا سألت تطبيق iOS عمّا إذا كان الهاتف على VPN، فالإجابة الصادقة هي أنه لا يستطيع المعرفة بالطريقة التي تقصدها. لا يكشف SDK أي علم يدل على أن «الجهاز داخل نفق»، والواجهات الخاصة التي قد تقترب من ذلك مغلقة أمام التطبيقات التي تُنشر. يمكنك ملاحظة إعدادات تطبيقك الخاصة، والحالة المرتبطة بها، وتلميح أو تلميحين غير مباشرين من حزمة الشبكة. كل واحد منها يجيب عن سؤال مختلف، ومعظم الفحوص المعطوبة تأتي من اعتبار أحدها هو الجواب الكامل.
أسطورة علم VPN الواحد
الاعتقاد السائد هو أن في مكان ما داخل SDK خاصيةً تُبلّغ عمّا إذا كان الجهاز داخل نفق، بالطريقة التي يُبلّغ بها علم قابلية الوصول عن استجابة مضيف. لا توجد خاصية عامة بهذا الشكل. وحتى لو وُجدت، فإن «وجود نفق» و«استخدام حركة المرور الخاصة بي له» ادّعاءان مختلفان، والثاني وحده هو المهم لمعظم التطبيقات.
هذه الفجوة هي سبب ميل المكتبات التي تعلن عن كاشف VPN من سطر واحد إلى قراءة شيء هش، مثل اسم واجهة أو مفتاح وكيل، وتقديمه على أنه حكم نهائي.
حمّل التفضيلات قبل أن تثق بقيمة nil
توجد نسخة المدير المشتركة بمجرد أن تطلبها، لكن خاصية البروتوكول فيها تبقى nil حتى يكتمل رد نداء التحميل. لذا فإن قيمة nil للبروتوكول تعني «لم يُحمَّل بعد» بقدر ما تعني «غير مثبَّت»، على الأقل. نفّذ القراءة داخل كتلة الإكمال، وبعدها فقط قرّر: كائن بروتوكول موجود مع تشغيل علم التمكين هو شكل «مثبَّت».
توجد إشارة ثانية على كائن الاتصال: الحالة غير الصالحة، التي يبلّغ عنها النظام عندما لا يكون لدى هذا التطبيق أي إعداد مثبَّت. الحالة غير الصالحة مع قيمة nil للبروتوكول بعد تحميل مكتمل تعني غياباً حقيقياً، لا سباق توقيت.
تغييرات الاتصال تصل كإشعارات
المعالِجات التي تُمرَّر إلى load و save تُبلّغ عمّا حدث للإعداد، لا عمّا يفعله النفق. انتظار واحد منها ليُطلق عند الاتصال سباق لا يُحلّ أبداً. راقب إشعار تغيير الحالة بدلاً من ذلك، واقرأ القيمة الحالية لكائن الاتصال عند وصوله.
بمجرد تثبيت إعداد، تمرّ حالة الاتصال بتسلسل قصير: غير متصل، جارٍ الاتصال، متصل، إعادة تأكيد، جارٍ قطع الاتصال. «متصل» يصف النفق لا الخادم الذي خلفه، لذا ليس دليلاً على أن حركة المرور تتدفق. كما يمكن لـ On-demand رفع نفق بينما التطبيق معلَّق، وعندها يصل الإشعار قبل أن يكون لديك ما تحدّثه.
لقطة الوكيل محدودة النطاق تلميح لا حكم
يستطيع CFNetwork أن يمنح التطبيق إعدادات الوكيل الحالية للنظام، وداخل تلك النتيجة قاموس محدود النطاق مفتاحه اسم الواجهة. رؤية اسم يبدأ بـ tun أو utun أو ppp أو ipsec أو tap تلميح إلى وجود نفق. يبقى الأمر لقطة لما يستطيع هذا التطبيق رؤيته، لا تصريحاً عن المسار الذي تسلكه الحزم.
يختلف المزوّدون في التسمية، لذا فغياب البادئة لا يثبت شيئاً، وقد توجد واجهة دون أن تحمل أي حركة. وقابلية الوصول أضعف من ذلك: نجاح طلب إلى عنوان خاص يُظهر أن المسار عمل لذلك الطلب في تلك اللحظة، لا أن VPN مثبَّت.
المحاكي يستعير الـ Mac، والتطبيقات الأخرى تبقى غير مرئية
لا يملك المحاكي حزمة شبكة خاصة به؛ كل اتصال يجريه هو اتصال الـ Mac. لذا فإن VPN يعمل على الـ Mac المضيف يكون ساري المفعول بالفعل بالنسبة للتطبيق المحاكى، وإعدادات المحاكي نفسه لا تُظهر شيئاً. إذا ارتفع النفق بعد بدء المحاكي، فإعادة تشغيله عادةً أسرع من تنقيح التطبيق. والمضيف على منفذ غير قياسي يحتاج إلى ذلك المنفذ في عنوان URL، أو إلى تحويل محلي مثل socat TCP-LISTEN:12345,fork TCP:host:12345.
لن تُعدّد واجهات API العامة ملفات تعريف VPN التي تنتمي إلى تطبيقات أخرى أو إلى ملفات تعريف الإعداد. لتطبيق واحد معروف، يكون فحص مخطط URL عبر canOpenURL هو الحيلة المحمولة، ومنذ iOS 9 يجب الإعلان عن المخطط المستعلم عنه في Info.plist الخاص بك؛ وإن تركته فسيعيد الاستدعاء false. يستجيب OpenVPN Connect على openvpn://، وهذا مثال جيد وكاشف عام ضعيف.
اجمع ثلاث ملاحظات وقل ما تعنيه
اجمع ثلاث نتائج في الممارسة: إعداد حُمِّل ومُمكَّن، وحالة اتصال ليست غير صالحة، وطلب إلى عنوان لا يمكن الوصول إليه إلا عبر النفق. كل واحدة منها مضللة وحدها؛ ومعاً تقول ما يمكن للتطبيق معرفته بدلاً مما يفترضه المستخدم.
اكتب النتيجة ثلاثة أسطر في تشخيصاتك، لا قيمة منطقية واحدة. عندما يقول مستخدم إن VPN مغلق بينما يخالفه تطبيقك، تُظهر الأسطر الثلاثة أي ملاحظة انحرفت، وهذا هو الفرق بين تذكرة دعم يمكنك التصرف بشأنها وتذكرة تنتهي بـ «يعمل عندي».