Γιατί η εφαρμογή σας για Android δεν μπορεί να προσθέσει προφίλ VPN συστήματος
Το VpnService φτιάχνει ένα τούνελ που ανήκει στην εφαρμογή σας· δεν μπορεί να προσθέσει ή να επεξεργαστεί τις καταχωρίσεις PPTP, L2TP ή IPsec του τηλεφώνου. Ακολουθήστε το όριο και διαλέξτε τον σωστό δρόμο.
Πατάτε τη γραμμή VPN στις Ρυθμίσεις, βλέπετε ένα προφίλ που εγκατέστησε κάποιος άλλος και αρχίζετε να ψάχνετε την κλήση που προσθέτει ένα. Τέτοια κλήση δεν υπάρχει. Μια εφαρμογή μπορεί να ανοίξει δικό της τούνελ μέσω του VpnService, αλλά οι καταχωρίσεις σε εκείνη τη λίστα ανήκουν στην πλατφόρμα και σε όποιον πελάτη τις δημιούργησε. Το να ξέρετε ακριβώς πού βρίσκεται η γραμμή σας γλιτώνει μια εβδομάδα κυνηγιού κρυφών κλάσεων.
Ξεκινήστε από αυτό που δείχνει η οθόνη Ρυθμίσεων
Η λίστα VPN είναι μητρώο προφίλ που εγκατέστησε το σύστημα ή κάποιος πελάτης κατασκευαστή: PPTP, L2TP/IPsec, IKEv2 και όσες γραμμές έσπρωξε μια εφαρμογή OEM ή ένα MDM. Κάθε γραμμή κουβαλά μια διεύθυνση διακομιστή, διαπιστευτήρια και μια υλοποίηση πρωτοκόλλου που ζει έξω από τη διεργασία σας. Όταν ο χρήστης πατά Σύνδεση εκεί, το τούνελ το σηκώνει ο πελάτης της πλατφόρμας, όχι ο κώδικάς σας. Γι' αυτό η γραμμή επιβιώνει από επανεκκίνηση και γι' αυτό η απεγκατάσταση της εφαρμογής σας δεν την αφαιρεί ποτέ.
Από τη μεριά του χρήστη η λίστα μοιάζει με επιφάνεια API, ένα μέρος όπου η προσθήκη VPN θα έπρεπε να απέχει ένα intent. Δεν είναι. Τα μόνα δημόσια σημεία εισόδου που την αγγίζουν είναι intents πλοήγησης, και ό,τι γράφει σε αυτήν ανήκει στην πλατφόρμα ή σε ένα προνομιούχο στοιχείο.
Πρακτική συνέπεια: αν ένα κείμενο υποστήριξης λέει στους χρήστες να προσθέσουν το προφίλ στις Ρυθμίσεις, η εφαρμογή σας δεν είναι καθόλου μέρος αυτής της ροής.
Τι σας δίνει πραγματικά το VpnService
Το VpnService και το VpnService.Builder περιγράφουν ένα τούνελ που ανήκει στην εφαρμογή σας. Προσθέτετε διευθύνσεις, διαδρομές, διακομιστές DNS και ένα MTU, περιορίζετε την κίνηση με addAllowedApplication() ή addDisallowedApplication() και μετά το establish() επιστρέφει ένα ParcelFileDescriptor για διεπαφή TUN. Από εκεί και πέρα η εφαρμογή διαβάζει πακέτα IP και γράφει απαντήσεις, που σημαίνει ότι το πρωτόκολλο είναι δικό σας να το υλοποιήσετε ή να το ενσωματώσετε: OpenVPN, WireGuard, μια δική σας μεταφορά.
Τίποτα σε αυτή την αλληλουχία δεν μιλά PPTP, L2TP/IPsec ή IKEv2. Το Builder δεν έχει διακόπτη που να λέει χρησιμοποίησε τον πελάτη L2TP του συστήματος, και δεν υπάρχει callback που σας αφήνει να οδηγήσετε ένα προφίλ που ανήκει ήδη στην πλατφόρμα. Αυτό είναι το πραγματικό όριο, και είναι όριο σχεδίασης, όχι κενό αδειών.
Άρα μια εφαρμογή μπορεί απολύτως να είναι πελάτης VPN στο Android. Απλώς δεν μπορεί να είναι διαχειριστής για τους πελάτες που έρχονται με το τηλέφωνο.
Ο διάλογος συγκατάθεσης δεν είναι διακόσμηση
Επειδή το τούνελ σας μπορεί να συλλάβει την κίνηση άλλων εφαρμογών, το σύστημα κάνει τον χρήστη να το εγκρίνει ρητά. Το prepare() επιστρέφει ένα Intent που πρέπει να εκκινήσετε, η έγκριση δένεται με το πακέτο σας, και όσο το τούνελ είναι ενεργό η γραμμή κατάστασης δείχνει μόνιμη ένδειξη. Ένα δεύτερο VPN που ανεβαίνει απενεργοποιεί το πρώτο, αφού το Android τρέχει ένα ενεργό VPN τη φορά.
Ο κανόνας του ενός ενεργού μπερδεύει κόσμο στις δοκιμές. Σηκώνετε το τούνελ σας ενώ είναι συνδεδεμένος ένας εταιρικός πελάτης και συμπεραίνετε ότι ο κώδικάς σας είναι χαλασμένος, ενώ η πλατφόρμα απλώς άλλαξε από τον άλλο πελάτη. Οι εγκρίσεις μπορούν να ανακληθούν αργότερα, και το prepare() μπορεί να επιστρέψει null σε συσκευές όπου λείπει η δραστηριότητα συγκατάθεσης, οπότε το establish() πρέπει ακόμα να χειρίζεται αποτυχία.
Κρυφά API και intents ρυθμίσεων
Παλιότερες απαντήσεις δείχνουν σε κλάσεις com.android.internal και διεπαφές AIDL που χρησιμοποιεί ο ενσωματωμένος πελάτης. Δεν είναι στο SDK, αλλάζουν μεταξύ εκδόσεων χωρίς ειδοποίηση, και τα καταστήματα εφαρμογών θεωρούν αυτή την πρόσβαση ρίσκο. Το root στη συσκευή δεν τις κάνει σταθερές, αφού το root και η πρόσβαση σε κρυφά API είναι άσχετα προβλήματα.
Το υποστηριζόμενο βοήθημα πλοήγησης είναι το Settings.ACTION_VPN_SETTINGS, του οποίου η τιμή είναι android.net.vpn.SETTINGS. Επιλύστε το πριν το εκκινήσετε, γιατί μερικές εκδόσεις OEM δεν παρέχουν αυτή τη δραστηριότητα, και πέστε σε γραπτά βήματα όταν η επίλυση αποτύχει. Πηγαίνει τον χρήστη στην οθόνη και δεν ρυθμίζει τίποτα.
Οι διαδρομές ιδιοκτήτη συσκευής και MDM είναι η εξαίρεση που συνήθως εννοούν οι άνθρωποι. Το DevicePolicyManager μπορεί να ορίσει πακέτο VPN πάντα ενεργό, και οι διαχειριζόμενες ρυθμίσεις μπορούν να προφορτώσουν ρυθμίσεις για πελάτη που τις υποστηρίζει, αλλά αυτό δεν είναι ακόμα το δημόσιο SDK να συντάσσει προφίλ PPTP.
Περπατήστε την απόφαση από τη μεριά του χρήστη
Αν το προϊόν σας πρέπει να μεταφέρει κίνηση, σχεδιάστε VpnService συν μια πραγματική στοίβα πρωτοκόλλου, και υπολογίστε χρόνο για τη ροή συγκατάθεσης και τον κανόνα του ενός VPN. Αν ο στόχος είναι η σύνδεση σε υπάρχον εταιρικό προφίλ, η δουλειά σας είναι καθοδήγηση: βαθύς σύνδεσμος στην οθόνη ρυθμίσεων, τεκμηρίωση των πεδίων, και αφήστε τον πελάτη της πλατφόρμας να κάνει το τούνελ. Αν η εφαρμογή χρειάζεται μόνο να φτάσει ένα ιδιωτικό τελικό σημείο, δεν χρειάζεται καθόλου δικό της τούνελ.
Γράψτε αυτή την απόφαση πριν γράψετε κώδικα, γιατί τα τρία μονοπάτια δεν έχουν σχεδόν τίποτα κοινό μετά το πρώτο sprint.
Ένας τελευταίος έλεγχος πριν ξεκινήσετε: η απαίτηση λέει ότι συνδέεται η εφαρμογή μας ή ότι συνδέεται η συσκευή; Το πρώτο είναι VpnService, το δεύτερο είναι προφίλ που δεν μπορείτε να δημιουργήσετε. Το να γράψετε σωστά αυτή την πρόταση είναι φθηνότερο από κάθε αναδιάρθρωση.