Χτίστε μια οθόνη VPN μέσα σε μια εφαρμογή iOS και η πρώτη έκπληξη είναι ότι η λίστα πρωτοκόλλων στην εφαρμογή Ρυθμίσεις δεν είναι η λίστα του API. Το πλαίσιο Network Extension επιτρέπει στην εφαρμογή σας να δημιουργήσει μία προσωπική διαμόρφωση VPN, που ανήκει σε αυτή την εφαρμογή, και δέχεται μόνο λίγα αντικείμενα πρωτοκόλλου. Όλα τα υπόλοιπα που περιμένουν οι άνθρωποι, από L2TP μέχρι ένα κατεβασμένο προφίλ, βρίσκονται έξω από αυτή την επιφάνεια ή είναι ιδιωτικά της Apple. Οι αποτυχίες που ακολουθούν συνήθως δεν είναι σφάλματα· είναι το API που αρνείται μια εργασία που δεν του δόθηκε ποτέ.

Ο μύθος: το API δεν είναι συντάκτης Ρυθμίσεων

Η πεποίθηση είναι ότι, αφού το iOS μπορεί να διαμορφώνει προφίλ IKEv1, IKEv2, L2TP και IPsec, μια εφαρμογή μπορεί να δημιουργήσει οποιοδήποτε από αυτά προγραμματιστικά. Δεν μπορεί. Το πλαίσιο εκθέτει ακριβώς μία υποδοχή διαμόρφωσης στην εφαρμογή που το καλεί, και αυτή η υποδοχή δέχεται ένα μικρό σύνολο δημόσιων κλάσεων πρωτοκόλλου. Όλα τα υπόλοιπα που περιμένουν οι άνθρωποι, από L2TP μέχρι ένα κατεβασμένο προφίλ, βρίσκονται έξω από αυτή την επιφάνεια ή είναι ιδιωτικά της Apple.

Οι αποτυχίες που ακολουθούν συνήθως δεν είναι σφάλματα. Είναι το API που αρνείται μια εργασία που δεν του δόθηκε ποτέ, και η λύση είναι να σχεδιάσετε την οθόνη γύρω από αυτό που κατέχει το API.

Τρία αντικείμενα πρωτοκόλλου και εκείνα που δεν υπάρχουν

Οι επιλογές σας είναι IKEv1 μέσω NEVPNProtocolIPSec, IKEv2 μέσω NEVPNProtocolIKEv2 και NETunnelProviderProtocol αν διανέμετε δική σας επέκταση τούνελ πακέτων. Η αναφορά του NEVPNManager απαριθμεί τα αποδεκτά αντικείμενα πρωτοκόλλου. Τα L2TP και PPTP δεν εμφανίζονται ποτέ σε αυτή τη λίστα, γιατί η Apple δεν δημοσίευσε κλάσεις γι’ αυτά. Η προσπάθεια καθενός τελειώνει κατά την αποθήκευση με σφάλμα ή, χειρότερα, με διαμόρφωση που το σύστημα αρνείται σιωπηλά να χρησιμοποιήσει.

Ο κώδικας για υπολογιστές ακολουθεί άλλους κανόνες. Στο macOS, το SCNetworkInterfaceCreateWithInterface στοιβάζει έναν τύπο διεπαφής όπως L2TP πάνω από IPv4 και τον προσαρτά σε μια υπηρεσία δικτύου, και το networksetup -connectpppoeservice ξεκινά το αποτέλεσμα. Απαιτούνται δικαιώματα διαχειριστή και ένα βοηθητικό εργαλείο, γιατί το κοινό μυστικό και ο κωδικός πηγαίνουν στην κλειδοθήκη του συστήματος. Μεταφέρετε αυτόν τον σχεδιασμό στο iOS και τίποτα δεν μεταγλωττίζεται.

Περάστε αναφορά κλειδοθήκης, όχι τον κωδικό

Καμία από τις κλάσεις IKE δεν δέχεται κωδικό ως κείμενο. Οι δύο ιδιότητες passwordReference και sharedSecretReference θέλουν μια μόνιμη αναφορά κλειδοθήκης, την οποία παίρνετε από το SecItemCopyMatching ζητώντας το kSecReturnPersistentRef. Η μετάδοση των δεδομένων του στοιχείου ή η βίαιη εισαγωγή συμβολοσειράς στο πεδίο παράγει αποτυχία αποθήκευσης ή σύνδεση με κενά διαπιστευτήρια. Η αναφορά είναι τόσο ανθεκτική όσο το στοιχείο κλειδοθήκης πίσω της, γι’ αυτό το στοιχείο πρέπει να υπάρχει πριν συναρμολογηθεί η διαμόρφωση. Δημιουργήστε το στην ίδια συναλλαγή με την αποθήκευση και αφαιρείτε μια ολόκληρη κατηγορία σφαλμάτων σειράς.

Ο έλεγχος ταυτότητας με πιστοποιητικό ακολουθεί άλλη διαδρομή: identityData συν identityDataPassword για ένα blob PKCS#12. Η διανομή αυτού του blob μέσα στο πακέτο της εφαρμογής είναι συνήθεια από δείγμα κώδικα και όχι απόφαση διανομής, γιατί ο κωδικός ταξιδεύει μαζί του και κάθε αντίγραφο της εφαρμογής φέρει την ίδια ταυτότητα.

Η άδεια και η διαθεσιμότητα καθορίζουν τα πάντα

Ο διαχειριστής μπορεί να μην υπάρχει καθόλου, και ο λόγος είναι η προετοιμασία. Το αναγνωριστικό της εφαρμογής σας χρειάζεται τη δυνατότητα Network Extension μαζί με την άδεια προσωπικού VPN, και το προφίλ που υπογράφει το build πρέπει να φέρει και τα δύο.

Παραλείψτε το και το κοινό στιγμιότυπο επιστρέφει nil, ή η αποθήκευση αποτυγχάνει με σφάλμα που δεν αναφέρει ποτέ την άδεια. Η διαθεσιμότητα είναι η άλλη πύλη. Στοχεύστε σε κάτι παλαιότερο από iOS 8 και το σύμβολο λείπει κατά την εκτέλεση, οπότε η αποτυχία είναι κατάρρευση ή διαχειριστής με τιμή nil και όχι διαχειριστής χωρίς διαμόρφωση. Ελέγξτε το περιβάλλον εκτέλεσης και την άδεια πριν αποσφαλματώσετε το γράφημα αντικειμένων.

Φορτώστε, αλλάξτε, αποθηκεύστε και μετά προσέξτε τη σειρά κατά παραγγελία

Αντιμετωπίστε τον κύκλο ζωής ως φόρτωση, αλλαγή, αποθήκευση και μην παραλείψετε ποτέ τη φόρτωση. Μέχρι να ολοκληρωθεί το loadFromPreferences, ο διαχειριστής δεν κρατά τίποτα και το αντικείμενο πρωτοκόλλου δεν μπορεί να διαβαστεί ή να αντικατασταθεί.

Μια δεύτερη αποθήκευση αντικαθιστά τη διαμόρφωση αντί να προσθέτει άλλη, οπότε μια μισοτελειωμένη αποθήκευση μπορεί να καταστρέψει ένα προφίλ που δούλευε. Οι κανόνες κατά παραγγελία σχηματίζουν ένα διατεταγμένο πίνακα, και αυτή η σειρά είναι η πολιτική. Βάλτε κανόνα σύνδεσης από παντού πριν από τον κανόνα αποσύνδεσης και μια χειροκίνητη αποσύνδεση ακολουθείται από άμεση επανασύνδεση, που μοιάζει με ελάττωμα αλλά ακολουθεί την τεκμηριωμένη αξιολόγηση.

Μετακινήστε τον κανόνα αποσύνδεσης μπροστά όταν η ενέργεια του χρήστη πρέπει να κερδίσει. Ό,τι μένει έξω από τον έλεγχο της εφαρμογής έχει την ίδια σημασία. Οι διαδρομές έρχονται από το τούνελ ή από την πολιτική του διακομιστή και όχι από μια προτίμηση που ορίζετε, με τον πάροχο τούνελ πακέτων να τις αναφέρει όταν ξεκινά. Η εφαρμογή δεν μπορεί να απαριθμήσει ή να επεξεργαστεί προφίλ που εγκατέστησαν άλλες εφαρμογές ή προφίλ διαμόρφωσης, οπότε μην υπόσχεστε οθόνη που δείχνει κάθε VPN στη συσκευή.

Σχετικά άρθρα