Ви треба еден екран што се однесува поинаку кога тунелот е активен, а нема повик што ви го кажува тоа. Тоа е ограничувањето при испорака: на macOS ниту една јавна рамка не известува дали е поврзан произволен VPN, а на iOS статусот и припаѓа на апликацијата што ја инсталирала конфигурацијата. Проверките подолу водат од таа граница до нешто што можете да го испорачате, и секоја од нив може рано да ја заврши потрагата.

Проверка 1: дали воопшто може да се одговори на прашањето?

Sandbox го решава прашањето пред кој било API. Процес на трета страна не може да го наброи продолжувањето на друг добавувач и не може да ја прочита ниту конфигурацијата на тоа продолжување, затоа нема поддржан објект што може да се праша.

Секое заобиколување удира во истиот ѕид. Листите на интерфејси, scutil --nc list и директното читање на системската конфигурација или бараат дозволи што sandbox ги задржува или зависат од однесување што 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 што се крши во следното издание.

Поврзани статии