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

Τρεις αποφάσεις σε σταθερή σειρά

Ένα πακέτο στην έξοδό του παίρνει τρεις ξεχωριστές αποφάσεις. Πρώτον, ένας κανόνας πολιτικής αποφασίζει ποιος πίνακας δρομολόγησης ισχύει. Δεύτερον, μια διαδρομή μέσα σε αυτόν τον πίνακα αποφασίζει το επόμενο hop και τη διεπαφή εξόδου. Τρίτον, τα hooks του netfilter αποφασίζουν αν το πακέτο επιβιώνει, τροποποιείται ή ανακατευθύνεται.

Η σειρά έχει σημασία γιατί κάθε στάδιο μπορεί να απαντήσει μόνο στη δική του ερώτηση. Ένας κανόνας firewall που δέχεται ένα πακέτο δεν επιλέγει πίνακα, και μια διαδρομή που προστίθεται σε πίνακα που κανένας κανόνας δεν επιλέγει είναι ανενεργή. Μεγάλο μέρος της σύγχυσης γύρω από τα VPN του Android προέρχεται από το ότι διορθώνεις ένα από τα τρία και δεν βλέπεις αλλαγή, γιατί η βλάβη ήταν σε άλλο.

StageSelectorWhat it cannot decide
Policy ruleuid range, mark, incoming interfaceWhich route exists inside the table
Route lookupDestination prefix, longest matchWhether the packet is allowed out
Netfilter hookChain position, match conditionsWhich table was selected

Τα σημάδια είναι ένα συσκευασμένο πεδίο, όχι ετικέτα που σου ανήκει

Το Android συσκευάζει πολλά γεγονότα στην ίδια τιμή σημαδιού: ποιο δίκτυο επιλέχθηκε, αν μια εφαρμογή επέλεξε ρητά δίκτυο, αν ένα socket προστατεύεται από το VPN και bits που σχετίζονται με άδειες. Η κεφαλίδα fwmark του AOSP ορίζει αυτή τη διάταξη για το τρέχον δέντρο, και η διάταξη είναι εσωτερικό της πλατφόρμας που αλλάζει μεταξύ εκδόσεων.

Γι' αυτό η εγγραφή μιας ολόκληρης τιμής σημαδιού με iptables -j MARK --set-mark είναι επικίνδυνη στο Android. Δεν προσθέτει ετικέτα· αντικαθιστά την επιλογή δικτύου που έχει ήδη κάνει το σύστημα. Το πακέτο τότε ταιριάζει με διαφορετικούς κανόνες, κάτι που μπορεί να μοιάζει σαν το VPN να άρχισε να δουλεύει, ή σαν μια άσχετη εφαρμογή να έχασε τη σύνδεση, ανάλογα με τα bits που αντικαταστάθηκαν.

Αν πρέπει οπωσδήποτε να αγγίξεις σημάδια, διάβασε πρώτα την τρέχουσα τιμή και χρησιμοποίησε μάσκα ώστε να αλλάζουν μόνο τα bits που καταλαβαίνεις:

ip rule show
ip route show table all | head -40
ip route get 10.20.4.11

Ένα σημάδι σύνδεσης είναι ξεχωριστό αντικείμενο από ένα σημάδι πακέτου, και κανένα από τα δύο δεν είναι διαδρομή. Η επαναφορά του σημαδιού στα πακέτα απάντησης είναι ξεχωριστό βήμα από την επιλογή πίνακα στην έξοδο, γι' αυτό οι μονόδρομες διορθώσεις παράγουν συνδέσεις που ανοίγουν και μετά κολλάνε.

Ποιος κατέχει τους κανόνες και τους πίνακες

Η υπηρεσία δικτύου του Android, netd, δημιουργεί τους κανόνες και τους πίνακες ανά δίκτυο. Το AOSP RouteController είναι το σημείο όπου αυτοί οι κανόνες συναρμολογούνται για VPN, φυσικά δίκτυα και εύρη uid, και ο κύκλος ζωής του είναι δεμένος με συμβάντα δικτύου και όχι με αρχείο ρυθμίσεων.

Δύο συνέπειες ακολουθούν. Πρώτον, οι προτεραιότητες και οι αριθμοί πίνακα που βρίσκεις σε μια συσκευή είναι εσωτερικά της έκδοσης, όχι διεπαφή: αριθμοί που φαίνονται ίδιοι σε άλλη έκδοση Android μπορεί να σημαίνουν κάτι εντελώς διαφορετικό. Δεύτερον, η κατάσταση ξαναχτίζεται όταν αλλάζουν τα δίκτυα, οπότε ένας κανόνας που εισάγεται σήμερα από root shell μπορεί να έχει εξαφανιστεί μετά την επόμενη αλλαγή Wi-Fi.

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

Οι ερωτήσεις για τη σειρά των hooks δεν έχουν καθολική απάντηση

Η ερώτηση αν το iptables τρέχει πριν από τη δρομολόγηση του VPN δεν απαντιέται χωρίς να ονομάσεις τη διαδρομή του πακέτου. Ένα τοπικά παραγόμενο πακέτο διασχίζει το hook output, όπου μια αλλαγή σημαδιού προκαλεί έλεγχο επαναδρομολόγησης — δεύτερη αναζήτηση, όχι αναδρομική επεξεργασία της πρώτης. Ένα πακέτο που φτάνει από tethering πελάτη διασχίζει τη διαδρομή prerouting και προωθείται αντ' αυτού, και οι αλυσίδες που το βλέπουν είναι άλλες.

Έτσι ο ίδιος κανόνας μπορεί να είναι αποτελεσματικός για την κίνηση μιας εφαρμογής και αόρατος για κίνηση tethering, και ένας μετρητής που μένει στο μηδέν σου λέει ποια διαδρομή πήρε το πακέτο, όχι αν ο κανόνας είναι λάθος. Χρησιμοποίησε μετρητές για να διαπιστώσεις τη διαδρομή πριν αλλάξεις οποιαδήποτε συνθήκη ταιριάσματος.

Αυτό είναι και το στάδιο όπου ένα λάθος δρομολόγησης πολιτικής γίνεται δύσκολο να φανεί. Η δρομολόγηση σε πίνακα που υπάρχει αλλά δεν περιέχει τον προορισμό παράγει δίκτυο μη προσπελάσιμο που μοιάζει με απόρριψη firewall, ενώ μια απόρριψη firewall παράγει λήξη χρόνου που μοιάζει με μαύρη τρύπα δρομολόγησης.

Διάγνωση μέσα στο σύστημα ή αφήστε το ήσυχο

Για εξουσιοδοτημένη εξέταση, διαπίστωσε τέσσερα γεγονότα πριν αγγίξεις οτιδήποτε: το uid και το προφίλ της εφαρμογής, το δίκτυο που επέλεξε το Android γι' αυτήν, αν το VPN περιλαμβάνει καθόλου αυτή την εφαρμογή, και αν το πρόβλημα υπάρχει και για τις δύο οικογένειες διευθύνσεων. Μια εξαίρεση ανά εφαρμογή εξηγεί πάρα πολλές αναφορές του τύπου το VPN δεν δουλεύει χωρίς καμία βλάβη δρομολόγησης.

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

Για συνηθισμένες απαιτήσεις, χρησιμοποίησε τα υποστηριζόμενα χειριστήρια: συμπερίληψη και εξαίρεση ανά εφαρμογή στην εφαρμογή VPN και την επιλογή δικτύου της ίδιας της πλατφόρμας για ό,τι χρειάζεται συγκεκριμένη διαδρομή. Αν μια προνομιακή ενσωμάτωση πρέπει πραγματικά να συνεργαστεί με τη μηχανή δρομολόγησης, στόχευσε την υλοποίηση της ακριβούς έκδοσης Android που υποστηρίζεις και συντήρησε τον κύκλο ζωής της μέσω του συστατικού που την κατέχει. Το flush αλυσίδων της πλατφόρμας ή η εισαγωγή κανόνα υψηλής προτεραιότητας μετατρέπει μια διάγνωση σε δεύτερο διαχειριστή δικτύου, και το τηλέφωνο θα συμπεριφερθεί ανάλογα.

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