স্যান্ডবক্সড Mac অ্যাপে সক্রিয় VPN শনাক্ত করা
এই প্রশ্নের কোনো পাবলিক API নেই, আর ইন্টারফেস-নামের কৌশলটি কেবল একটি হিউরিস্টিক। আপনার অ্যাপের আসলে কীসের উপর নির্ভর করা উচিত, তা ঠিক করার ছয়টি পরীক্ষা।
টানেল চালু থাকলে একটি স্ক্রিনকে আলাদা আচরণ করতে হবে, অথচ সেটি আপনাকে জানানোর কোনো কল নেই। এটাই শিপিং সীমাবদ্ধতা: macOS-এ কোনো পাবলিক ফ্রেমওয়ার্ক জানায় না কোনো নির্বিচার VPN সংযুক্ত কি না, আর iOS-এ স্ট্যাটাসটি সেই অ্যাপের, যে কনফিগারেশনটি ইনস্টল করেছে। নিচের পরীক্ষাগুলো সেই সীমা থেকে এমন কিছু পর্যন্ত নিয়ে যায় যা আপনি শিপ করতে পারেন, এবং এগুলোর যেকোনোটি অনুসন্ধান আগেই শেষ করতে পারে।
পরীক্ষা 1: প্রশ্নটির উত্তর আদৌ দেওয়া সম্ভব?
স্যান্ডবক্সিং যেকোনো API-এর আগেই প্রশ্নটির নিষ্পত্তি করে। তৃতীয় পক্ষের প্রক্রিয়া অন্য বিক্রেতার এক্সটেনশন গণনা করতে পারে না, এবং সেই এক্সটেনশনের কনফিগারেশনও পড়তে পারে না, তাই জিজ্ঞাসা করার মতো কোনো সমর্থিত অবজেক্ট নেই।
প্রতিটি বাইপাস একই দেয়ালে ধাক্কা খায়। ইন্টারফেস তালিকা, 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 পর্যন্ত পরীক্ষাগুলো আপনাকে সমর্থিত উত্তর ছাড়া রেখে দেয়, তবে প্রোবটি শিপ করুন এবং ফলাফলটি সৎভাবে লেবেল করুন। নথিভুক্ত সর্বোচ্চ-প্রচেষ্টার সংকেত পরের রিলিজে ভেঙে পড়া একটি প্রাইভেট API-এর চেয়ে ভালো পণ্য-সিদ্ধান্ত।