Om 'n aktiewe VPN in 'n sandbox-Mac-app op te spoor
Daar is geen openbare API vir hierdie vraag nie, en die truuk met die koppelvlaknaam is 'n heuristiek. Ses kontroles om te besluit waarop jou app werklik moet staatmaak.
Jy het een skerm nodig wat anders optree wanneer die tonnel aan is, en daar is geen oproep wat vir jou sê dat dit so is nie. Dit is die versendingsbeperking: op macOS rapporteer geen openbare raamwerk of 'n willekeurige VPN gekoppel is nie, en op iOS behoort die status aan die app wat die konfigurasie geïnstalleer het. Die kontroles hieronder beweeg van daardie beperking na iets wat jy kan verskeep, en enige een van hulle kan die soektog vroeg beëindig.
Kontrole 1: is die vraag hoegenaamd beantwoordbaar?
Sandboxing besleg die vraag voordat enige API dit doen. 'n Derdeparty-proses kan nie 'n ander verskaffer se uitbreiding opsom nie, en dit kan ook nie daardie uitbreiding se konfigurasie lees nie, so daar is geen ondersteunde objek om te vra nie.
Elke omweg loop teen dieselfde muur vas. Koppelvlaklyste, scutil --nc list en direkte stelselkonfigurasie-lesings vereis óf regtighede wat die sandbox weerhou óf hang af van gedrag wat Apple nooit belowe het nie. As die plan een van daardie dinge nodig het, is die plan die probleem. 'n Funksie wat op 'n ongedokumenteerde besonderheid gebou is, is 'n ondersteuningskaartjie met 'n afleweringsdatum.
Kontrole 2: bestuur jou app self die tonnel?
As dit wel doen, het jy 'n ondersteunde antwoord vir jou eie konfigurasie. Laai die voorkeure, hanteer die fout, lees dan die status en teken in op veranderinge in plaas daarvan om te peil:
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
}Wees presies oor wat dit teruggee: die toestand van die tonnel wat jy geïnstalleer het. 'n Gebruiker wat 'n ander kliënt gebruik, sal as ontkoppel wys, en dit is nie 'n fout in jou kode nie. Besluit watter van daardie twee vrae jou funksie eintlik vra voordat jy op die antwoord bou.
Kontrole 3: wat sou 'n heuristiek jou eintlik vertel?
Die wyd gekopieerde benadering vra die stelsel-proksiewoordeboek om sy geskopeerde inskrywings en lees die sleutels, wat toevallig koppelvlakname is:
let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as NSDictionary?
let scoped = settings?["__SCOPED__"] as? [String: Any]
let names = scoped?.keys ?? []'n Sleutel wat met tap, tun, ppp, ipsec of utun begin, impliseer dat 'n tonnelgeskopeerde koppelvlak teenwoordig is. Om die hele naam te pas, misluk dadelik, want iOS 12 het utun1 en utun2 verskeep en sommige profiele verskyn as ipsec4, ppp0 of utun0. Vergelyk eerder voorvoegsels.
Selfs so, 'n naam identifiseer geen eienaar nie. Stelselfunksies en ander verskaffers se uitbreidings skep ook utun-koppelvlakke, en een kan bestaan terwyl dit niks van jou verkeer dra nie. Lees dit as 'n wenk dat iets tonnelvormig daar is, niks sterker nie. 'n Vals positiewe hier is goedkoop as jy net een funksie beheer, en duur as jy die aanmeldskerm beheer.
Kontrole 4: kan jy eerder die bestemming toets?
As die app net moet weet of 'n interne diens bereikbaar is, toets daardie diens. 'n Kort peiling met 'n tydsbeperking beantwoord die vraag waarvan die funksie werklik afhang, en dit bly werk wanneer die gebruiker van kliënt verwissel of die tonnel van vorm verander.
Bereikbaarheid is 'n waarneming oor jou pad. 'n Koppelvlaknaam is 'n afleiding oor iets wat aan jou pad grens, en daarom lewer die heuristiek argumente in foutverslae terwyl die peiling bewyse lewer. As die peiling misluk terwyl die gebruiker daarop aandring dat die VPN aan is, het jy nou 'n spesifieke pad om te ontfout: naamoplossing, roete of diensregte.
Kontrole 5: kan die platform afdwing wat jy nodig het?
Wanneer die vereiste 'n waarborg is dat niks uit die tonnel ontsnap nie, hoort die profiel daar, nie die detektor nie. Om includeAllNetworks in 'n voltonnel-konfigurasie op iOS 14 of later aan te skakel, verander platformgedrag in plaas daarvan om jou app te laat aflei. Die vlag word gedokumenteer in NEVPNProtocol-verwysing.
Dit is 'n ander soort antwoord: afdwinging in plaas van waarneming. Dit geld ook net vir profiele wat jy beheer, so dit help nie 'n verbruikerstoepassing wat iemand anders se tonnel dophou nie.
Kontrole 6: maak die mislukking veilig en waarneembaar
Skakel net die vermoë af wat die tonnel nodig het en laat die res van die app bruikbaar. 'n Detektor wat die hele koppelvlak verberg wanneer dit onseker is, skep 'n onderbreking vir elkeen wie se tonnel 'n naam gebruik wat jy nooit voorsien het nie. Val eerder terug op die konserwatiewe gedrag: plaaslike funksies bly werk en net die afgeleë oproep wat werklik die tonnel nodig het, word gedeaktiveer. Daardie keuse is 'n produkbesluit, en dit verdien om neergeskryf te word langs die heuristiek.
Teken aan wat jy waargeneem het: koppelvlakname, platformweergawe en die resultaat van een peiling. Dit verander die volgende verslag van 'n argument in 'n kontrole. Verkies dan 'n ondersteunde verklaring waar jy een het, want 'n bestuurde konfigurasie kan die bedoeling eksplisiet dra en die meeste rede om name na te gaan heeltemal verwyder.
As kontroles 1 tot 5 jou sonder 'n ondersteunde antwoord gelaat het, verskeep die peiling en benoem die resultaat eerlik. 'n Gedokumenteerde beste-poging-sein is 'n beter produkbesluit as 'n private API wat by die volgende vrystelling breek.