اكتشاف VPN نشط داخل تطبيق Mac محزوم
لا توجد واجهة برمجية عامة لهذا السؤال، وحيلة اسم الواجهة مجرد استدلال تقريبي. ستة فحوص لتقرر ما ينبغي أن يعتمد عليه تطبيقك فعلاً.
تحتاج إلى شاشة واحدة تتصرف بشكل مختلف عندما يكون النفق قائمًا، ولا يوجد استدعاء يخبرك بذلك. هذا هو قيد الإطلاق: في macOS لا يبلّغ أي إطار عمل عام عما إذا كان VPN عشوائي متصلًا، وفي iOS تعود الحالة إلى التطبيق الذي ثبّت التكوين. تمضي الفحوص أدناه من هذا الحد إلى شيء يمكنك إطلاقه، وأي منها يمكنه إنهاء البحث مبكرًا.
الفحص 1: هل يمكن الإجابة عن السؤال أصلًا؟
يحسم الحجز السؤال قبل أن تفعل ذلك أي واجهة برمجية. لا يمكن لعملية طرف ثالث أن تعدّد امتداد مورّد آخر، ولا يمكنها قراءة تكوين ذلك الامتداد، لذا لا يوجد كائن مدعوم للسؤال عنه.
كل حل بديل يصطدم بالجدار نفسه. قوائم الواجهات، وscutil --nc list وقراءات تكوين النظام المباشرة إما تتطلب استحقاقات يحجبها الحجز أو تعتمد على سلوك لم تعد به Apple قط. إذا كان المخطط يحتاج أحد هذه، فالمخطط هو المشكلة. الميزة المبنية على تفصيل غير موثّق هي تذكرة دعم لها تاريخ تسليم.
الفحص 2: هل يدير تطبيقك النفق بنفسه؟
إذا كان يفعل، فلديك إجابة مدعومة لتكوينك الخاص. حمّل التفضيلات، وعالج الخطأ، ثم اقرأ الحالة واشترك في التغييرات بدلًا من الاستقصاء الدوري:
vpnManager.loadFromPreferences { error in
// handle a load failure before reading status
}
NotificationCenter.default.addObserver(
forName: .NEVPNStatusDidChange,
object: nil,
queue: nil
) { note in
let status = (note.object as? NEVPNConnection)?.status
}كن دقيقًا بشأن ما يعيده هذا: حالة النفق الذي ثبّته أنت. المستخدم الذي يشغّل عميلًا آخر سيظهر كغير متصل، وهذا ليس خطأً في شفرتك. قرّر أي السؤالين تطرحه ميزتك فعلًا قبل أن تبني على الإجابة.
الفحص 3: ماذا سيخبرك الاستدلال التقريبي فعلًا؟
النهج الشائع النسخ يسأل قاموس وكيل النظام عن مدخلاته المحصورة ويقرأ المفاتيح، التي تصادف أنها أسماء واجهات:
let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as NSDictionary?
let scoped = settings?["__SCOPED__"] as? [String: Any]
let names = scoped?.keys ?? []المفتاح الذي يبدأ بـtap، tun، ppp، ipsec أو utun يعني بوجود واجهة محصورة للنفق. مطابقة الاسم كاملًا تفشل فورًا، لأن iOS 12 جاء بـ utun1 وutun2 وبعض الملفات الشخصية تظهر باسم ipsec4 أو ppp0 أو utun0. قارن البادئات بدلًا من ذلك.
ومع ذلك، لا يحدد الاسم أي مالك. ميزات النظام وامتدادات مورّدين آخرين تنشئ أيضًا واجهات utun، ويمكن أن توجد إحداها وهي لا تحمل أيًا من حركة مرورك. اقرأها كتلميح إلى وجود شيء على شكل نفق، لا أكثر. الإيجابية الكاذبة هنا رخيصة إذا كنت تحكم ميزة واحدة فقط، ومكلفة إذا كنت تحكم شاشة تسجيل الدخول.
الفحص 4: هل يمكنك اختبار الوجهة بدلًا من ذلك؟
إذا كان التطبيق يحتاج فقط إلى معرفة ما إذا كانت خدمة داخلية قابلة للوصول، فاختبر تلك الخدمة. مسبار قصير مع مهلة يجيب عن السؤال الذي تعتمد عليه الميزة فعليًا، ويظل يعمل عندما يبدّل المستخدم العميل أو يتغير شكل النفق.
قابلية الوصول ملاحظة عن مسارك. اسم الواجهة استنتاج عن شيء مجاور لمسارك، ولهذا ينتج الاستدلال التقريبي جدالات في تقارير الأخطاء بينما ينتج المسبار أدلة. إذا فشل المسبار بينما يصرّ المستخدم على أن VPN يعمل، فلديك الآن مسار محدد لتصحيحه: تحليل الأسماء أو المسار أو إذن الخدمة.
الفحص 5: هل يمكن للمنصة أن تفرض ما تحتاجه؟
عندما يكون المطلب ضمانًا بأن شيئًا لا يفلت من النفق، فمكان الملف الشخصي هناك، لا الكاشف. تشغيل includeAllNetworks في تكوين نفق كامل على iOS 14 أو أحدث يغيّر سلوك المنصة بدلًا من مطالبة تطبيقك باستنتاجه. العلم موثّق في مرجع NEVPNProtocol.
هذا نوع مختلف من الإجابات: فرض بدلًا من ملاحظة. وهو ينطبق فقط على الملفات الشخصية التي تتحكم بها، لذا لا يساعد تطبيق مستهلك يراقب نفق شخص آخر.
الفحص 6: اجعل الفشل آمنًا وقابلًا للملاحظة
أوقف فقط القدرة التي تحتاج النفق واترك بقية التطبيق قابلًا للاستخدام. الكاشف الذي يخفي الواجهة كلها كلما كان غير متأكد يصنع انقطاعًا لكل من يستخدم نفقًا باسم لم تتوقعه قط. تراجع بدلًا من ذلك إلى السلوك المحافظ: تظل الميزات المحلية تعمل ويُعطَّل فقط الاستدعاء البعيد الذي يحتاج النفق حقًا. هذا الخيار قرار منتج، ويستحق أن يُكتب بجانب الاستدلال التقريبي.
سجّل ما لاحظته: أسماء الواجهات وإصدار المنصة ونتيجة مسبار واحد. هذا يحوّل التقرير التالي من جدال إلى فحص. ثم فضّل إعلانًا مدعومًا حيث يتوفر لديك، لأن تكوينًا مُدارًا يمكنه حمل القصد صراحة وإزالة معظم سبب فحص الأسماء أصلًا.
إذا تركتك الفحوص من 1 إلى 5 بلا إجابة مدعومة، فأطلق المسبار وسمِّ النتيجة بصدق. إشارة بذل أفضل جهد موثّقة قرار منتج أفضل من واجهة برمجية خاصة تتعطل في الإصدار التالي.