Попитайте едно iOS приложение дали телефонът е във VPN и честният отговор е, че то не може да знае това по начина, който имате предвид. SDK не предоставя флаг за «устройството е в тунел», а частните интерфейси, които биха могли да се доближат, са затворени за публикувани приложения. Можете да наблюдавате собствената конфигурация на приложението, състоянието, прикачено към нея, и един-два косвени намека от мрежовия стек. Всеки отговаря на различен въпрос и повечето счупени проверки идват от това да приемете един от тях за целия отговор.

Митът за единния флаг за VPN

Вярването е, че някъде в SDK има свойство, което съобщава дали устройството е в тунел, по същия начин, по който флагът за достижимост съобщава дали даден хост отговаря. Такова публично свойство не съществува. Дори и да съществуваше, «има тунел» и «моят трафик го използва» са различни твърдения и само второто има значение за повечето приложения.

Именно този пропуск е причината библиотеките, които рекламират едноредов детектор за VPN, да четат нещо крехко, например име на интерфейс или прокси ключ, и да го представят като присъда.

Заредете предпочитанията, преди да се доверите на nil

Споделеният екземпляр на мениджъра съществува веднага щом го поискате, но свойството му за протокол остава nil, докато не завърши callback-ът за зареждане. Затова 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://, което го прави добър пример и лош общ детектор.

Съберете три наблюдения и кажете какво означават

Натрупайте три резултата на практика: конфигурация, която се е заредила и е активирана; състояние на връзката, което не е невалидно; и заявка към адрес, достижим само през тунела. Всяко едно от тях заблуждава само по себе си; заедно те казват какво може да знае приложението, а не какво предполага потребителят.

Запишете резултата като три реда в диагностиката си, а не като един boolean. Когато потребител каже, че VPN е изключен, а приложението ви не е съгласно, трите реда показват кое наблюдение се е разминало, и това е разликата между заявка за поддръжка, по която можете да действате, и такава, която завършва с «при мен работи».

Подобни статии