Sådan registrerer du en aktiv VPN i en sandboxet Mac-app
Der findes ingen offentlig API til dette spørgsmål, og tricket med interface-navnet er kun en heuristik. Seks kontroller til at afgøre, hvad din app egentlig bør afhænge af.
Du har brug for, at én skærm opfører sig anderledes, når tunnelen er oppe, og der findes ikke noget kald, der fortæller dig det. Det er udgivelsesbegrænsningen: på macOS rapporterer ingen offentlig ramme, om en vilkårlig VPN er forbundet, og på iOS tilhører status den app, der installerede konfigurationen. Kontrollerne nedenfor bevæger sig fra den grænse til noget, du kan udgive, og enhver af dem kan afslutte søgningen tidligt.
Kontrol 1: kan spørgsmålet overhovedet besvares?
Sandboxing afgør spørgsmålet, før nogen API gør det. En tredjepartsproces kan ikke opregne en anden leverandørs udvidelse og kan heller ikke læse den udvidelses konfiguration, så der findes ikke noget understøttet objekt at spørge.
Enhver omvej møder den samme mur. Interface-lister, scutil --nc list og direkte læsninger af systemkonfigurationen kræver enten rettigheder, som sandboxen tilbageholder, eller afhænger af adfærd, som Apple aldrig har lovet. Hvis planen har brug for en af disse, er planen problemet. En funktion bygget på en udokumenteret detalje er en supportbillet med en leveringsdato.
Kontrol 2: styrer din app selv tunnelen?
Hvis den gør, har du et understøttet svar for din egen konfiguration. Indlæs præferencerne, håndtér fejlen, læs derefter status, og abonnér på ændringer i stedet for at polle:
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
}Vær præcis om, hvad dette returnerer: tilstanden af den tunnel, du installerede. En bruger, der kører en anden klient, vises som afbrudt, og det er ikke en fejl i din kode. Beslut, hvilket af de to spørgsmål din funktion egentlig stiller, før du bygger videre på svaret.
Kontrol 3: hvad ville en heuristik egentlig fortælle dig?
Den bredt kopierede tilgang spørger systemets proxy-ordbog om dens scoped-poster og læser nøglerne, som tilfældigvis er interface-navne:
let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as NSDictionary?
let scoped = settings?["__SCOPED__"] as? [String: Any]
let names = scoped?.keys ?? []En nøgle, der begynder med tap, tun, ppp, ipsec eller utun antyder, at der findes et tunnel-scoped interface. At matche hele navnet fejler med det samme, fordi iOS 12 leverede utun1 og utun2, og nogle profiler vises som ipsec4, ppp0 eller utun0. Sammenlign præfikser i stedet.
Alligevel identificerer et navn ingen ejer. Systemfunktioner og andre leverandørers udvidelser opretter også utun-interfaces, og et kan eksistere, mens det ikke bærer noget af din trafik. Læs det som et hint om, at noget tunnelformet er i nærheden, ikke mere. En falsk positiv er billig her, hvis du kun gater én funktion, og dyr, hvis du gater login-skærmen.
Kontrol 4: kan du teste destinationen i stedet?
Hvis appen kun skal vide, om en intern tjeneste kan nås, så test den tjeneste. En kort probe med en timeout besvarer det spørgsmål, som funktionen faktisk afhænger af, og den bliver ved med at virke, når brugeren skifter klient, eller tunnelen skifter form.
Tilgængelighed er en observation om din vej. Et interface-navn er en slutning om noget, der grænser op til din vej, og det er derfor, heuristikken skaber diskussioner i fejlrapporter, mens proben skaber beviser. Hvis proben fejler, mens brugeren insisterer på, at VPN'en er tændt, har du nu en konkret vej at fejlfinde: navneopløsning, rute eller tjenestetilladelse.
Kontrol 5: kan platformen håndhæve det, du har brug for?
Når kravet er en garanti for, at intet undslipper tunnelen, hører profilen til der, ikke detektoren. At slå includeAllNetworks til i en fuldtunnel-konfiguration på iOS 14 eller nyere ændrer platformens adfærd i stedet for at bede din app udlede det. Flaget er dokumenteret i NEVPNProtocol-reference.
Det er en anden slags svar: håndhævelse i stedet for observation. Det gælder også kun for profiler, du kontrollerer, så det hjælper ikke en forbrugerapp, der holder øje med en andens tunnel.
Kontrol 6: gør fejlen sikker og observerbar
Slå kun den funktion fra, der har brug for tunnelen, og lad resten af appen være brugbar. En detektor, der skjuler hele grænsefladen, når den er usikker, skaber et nedbrud for alle, hvis tunnel bruger et navn, du aldrig havde forudset. Fald i stedet tilbage til den konservative adfærd: lokale funktioner bliver ved med at virke, og kun det fjernkald, der virkelig har brug for tunnelen, deaktiveres. Det valg er en produktbeslutning, og den fortjener at blive skrevet ned ved siden af heuristikken.
Log, hvad du observerede: interface-navne, platformversion og resultatet af én probe. Det gør den næste rapport fra en diskussion til en kontrol. Foretræk derefter en understøttet erklæring, hvor du har en, fordi en administreret konfiguration kan bære hensigten eksplicit og fjerne det meste af grunden til at inspicere navne overhovedet.
Hvis kontrollerne 1 til 5 har efterladt dig uden et understøttet svar, så udgiv proben og mærk resultatet ærligt. Et dokumenteret bedste-indsats-signal er en bedre produktbeslutning end en privat API, der brækker ved næste udgivelse.