Du trenger én skjerm som oppfører seg annerledes når tunnelen er oppe, og det finnes ikke noe kall som forteller deg det. Det er utgivelsesbegrensningen: på macOS rapporterer ingen offentlig ramme om en vilkårlig VPN er tilkoblet, og på iOS tilhører statusen appen som installerte konfigurasjonen. Kontrollene nedenfor går fra den grensen til noe du kan utgi, og enhver av dem kan avslutte søket tidlig.

Kontroll 1: kan spørsmålet i det hele tatt besvares?

Sandboxing avgjør spørsmålet før noen API gjør det. En tredjepartsprosess kan ikke ramse opp en annen leverandørs utvidelse, og kan heller ikke lese konfigurasjonen til den utvidelsen, så det finnes ikke noe støttet objekt å spørre.

Enhver omvei møter den samme veggen. Grensesnittlister, scutil --nc list og direkte lesing av systemkonfigurasjonen krever enten rettigheter som sandkassen holder tilbake, eller avhenger av atferd Apple aldri lovet. Hvis planen trenger en av disse, er planen problemet. En funksjon bygget på en udokumentert detalj er en støttebillett med leveringsdato.

Kontroll 2: styrer appen din tunnelen selv?

Hvis den gjør det, har du et støttet svar for din egen konfigurasjon. Last inn innstillingene, håndter feilen, les deretter statusen og abonner på endringer i stedet for å 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 presis på hva dette returnerer: tilstanden til tunnelen du installerte. En bruker som kjører en annen klient vil vises som frakoblet, og det er ikke en feil i koden din. Bestem hvilket av disse to spørsmålene funksjonen din egentlig stiller før du bygger på svaret.

Kontroll 3: hva ville en heuristikk egentlig fortelle deg?

Den mye kopierte tilnærmingen spør systemets proxy-ordbok om dens avgrensede oppføringer og leser nøklene, som tilfeldigvis er grensesnittnavn:

let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as NSDictionary?
let scoped = settings?["__SCOPED__"] as? [String: Any]
let names = scoped?.keys ?? []

En nøkkel som begynner med tap, tun, ppp, ipsec eller utun antyder at det finnes et tunnelavgrenset grensesnitt. Å matche hele navnet feiler med en gang, fordi iOS 12 kom med utun1 og utun2, og noen profiler vises som ipsec4, ppp0 eller utun0. Sammenlign prefikser i stedet.

Likevel identifiserer et navn ingen eier. Systemfunksjoner og andre leverandørers utvidelser lager også utun-grensesnitt, og ett kan eksistere uten å bære noe av trafikken din. Les det som et hint om at noe tunnelformet er i nærheten, ikke mer. En falsk positiv er billig her hvis du bare sperrer én funksjon, og dyr hvis du sperrer innloggingsskjermen.

Kontroll 4: kan du teste destinasjonen i stedet?

Hvis appen bare trenger å vite om en intern tjeneste er tilgjengelig, test den tjenesten. En kort probe med tidsavbrudd svarer på spørsmålet funksjonen faktisk avhenger av, og den fortsetter å virke når brukeren bytter klient eller tunnelen endrer form.

Tilgjengelighet er en observasjon om veien din. Et grensesnittnavn er en slutning om noe som grenser til veien din, og det er derfor heuristikken skaper diskusjoner i feilrapporter mens proben skaper bevis. Hvis proben feiler mens brukeren insisterer på at VPN-en er på, har du nå en konkret vei å feilsøke: navneoppslag, rute eller tjenestetillatelse.

Kontroll 5: kan plattformen håndheve det du trenger?

Når kravet er en garanti for at ingenting slipper ut av tunnelen, hører profilen hjemme der, ikke detektoren. Å slå på includeAllNetworks i en fulltunnelkonfigurasjon på iOS 14 eller nyere endrer plattformens atferd i stedet for å be appen din utlede det. Flagget er dokumentert i NEVPNProtocol-referansen.

Det er en annen type svar: håndheving i stedet for observasjon. Det gjelder også bare profiler du kontrollerer, så det hjelper ikke en forbrukerapp som følger med på noen andres tunnel.

Kontroll 6: gjør feilen trygg og observerbar

Slå bare av den egenskapen som trenger tunnelen, og la resten av appen være brukbar. En detektor som skjuler hele grensesnittet hver gang den er usikker, lager et avbrudd for alle hvis tunnel bruker et navn du aldri forutså. Fall tilbake til den konservative atferden i stedet: lokale funksjoner fortsetter å virke, og bare fjernkallet som virkelig trenger tunnelen, deaktiveres. Det valget er en produktbeslutning, og den fortjener å bli skrevet ned ved siden av heuristikken.

Logg det du observerte: grensesnittnavn, plattformversjon og resultatet av én probe. Det gjør den neste rapporten fra en diskusjon til en kontroll. Foretrekk deretter en støttet erklæring der du har en, fordi en administrert konfigurasjon kan bære hensikten eksplisitt og fjerne mesteparten av grunnen til å inspisere navn i det hele tatt.

Hvis kontrollene 1 til 5 lot deg stå uten et støttet svar, utgi proben og merk resultatet ærlig. Et dokumentert best-effort-signal er en bedre produktbeslutning enn en privat API som bryter i neste utgivelse.

Relaterte artikler