Στήνεις μια διανομή Linux να τρέχει μέσα σε chroot στο τηλέφωνο, εγκαθιστάς εκεί έναν πελάτη VPN και το κέλυφος ανακοινώνει ότι το τούνελ ολοκληρώθηκε. Μετά περνάς σε ένα πρόγραμμα περιήγησης και η κίνηση βγαίνει από τα δεδομένα κινητής, σαν να μην έγινε τίποτα. Ή το αντίθετο: κάθε εφαρμογή στο τηλέφωνο χάνει τη σύνδεση, επειδή ο πελάτης πρόσθεσε μια προεπιλεγμένη διαδρομή στον χώρο ονομάτων που χρησιμοποιεί πραγματικά το Android. Αυτά τα δύο συμπτώματα προέρχονται από το ίδιο κομμάτι που λείπει και κανένα δεν είναι σφάλμα του πελάτη VPN.

Το κέλυφος λέει συνδεδεμένο, οι εφαρμογές διαφωνούν

Το πρώτο αποτέλεσμα είναι το συνηθισμένο. Ένα τούνελ χώρου χρήστη που άνοιξε από chroot μπορεί να ολοκληρώσει το handshake, να τυπώσει τα στατιστικά του και να μεταφέρει κίνηση που παράγει το ίδιο κέλυφος, ενώ οι εφαρμογές του Android συνεχίζουν να χρησιμοποιούν το προεπιλεγμένο δίκτυο του τηλεφώνου. Τίποτα δεν τις υποκλέπτει, γιατί τίποτα δεν είπε στο Android ότι υπάρχει VPN.

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

Ποιο από τα δύο αποτελέσματα πήρες απαντιέται με μία εντολή. Σύγκρινε το ip route μέσα στο chroot με την ίδια εντολή από κέλυφος Android έξω. Ίδια έξοδος σημαίνει ότι το chroot βρίσκεται στον χώρο ονομάτων του κεντρικού συστήματος: κάθε αλλαγή δικτύου που κάνει ισχύει για όλο το τηλέφωνο. Διαφορετική έξοδος σημαίνει ότι ο εκκινητής δημιούργησε χώρο ονομάτων γι αυτό και το τούνελ του είναι αόρατο στο Android εκ κατασκευής.

Τι άλλαξε το chroot και τι όχι

ObjectEffect of a chroot
Pathname resolutionChanged: lookups start at the new root
Kernel and driversUnchanged: the phone's kernel, its TUN driver, its limits
Network namespaceUnchanged unless the launcher creates one
Android VPN registrationUnchanged: no app consented, no VPN is selected

Η κλήση συστήματος chroot κάνει ένα πράγμα: αλλάζει τον κατάλογο που χρησιμοποιείται για την ανάλυση διαδρομών. Η σελίδα man λέει ρητά ότι δεν είναι όριο ασφαλείας και δεν λέει τίποτα για διεπαφές, διαδρομές ή κατάσταση VPN. Όλα όσα περιμένουν οι άνθρωποι από ένα container Linux — ιδιωτική στοίβα δικτύου, φιλτραρισμένο σύστημα αρχείων, όρια πόρων — προέρχονται από άλλους μηχανισμούς που ο εκκινητής μπορεί ή δεν μπορεί να χρησιμοποίησε.

Γι αυτό οι ισχυρισμοί ότι το chroot απομονώνει ένα VPN συνήθως απαντούν στη λάθος ερώτηση. Η σχετική ερώτηση είναι σε ποιον χώρο ονομάτων τρέχει η διεργασία και σε ποιο πεδίο SELinux είναι περιορισμένη, και τα δύο είναι ιδιότητες του πώς ξεκίνησε, όχι της λέξης chroot.

Το TUN χρειάζεται τρία πράγματα και ο κόμβος συσκευής είναι μόνο ένα

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

ls -l /dev/net/tun
ip tuntap add dev tun0 mode tun

Στο Android η υποστήριξη TUN είναι συνήθως μεταγλωττισμένη στον πυρήνα, επειδή τη χρησιμοποιεί η υπηρεσία VPN της πλατφόρμας, αλλά αυτό δεν σημαίνει ότι η δική σου διεργασία επιτρέπεται να τη χρησιμοποιήσει. Η ρύθμιση της διεπαφής απαιτεί την ικανότητα διαχείρισης δικτύου και το SELinux αποφασίζει αν η διεργασία μπορεί να φτάσει καθόλου στον κόμβο της συσκευής. Η άρνηση μοιάζει με σφάλμα άδειας χωρίς προφανή αιτία και η απάντηση βρίσκεται στο ίχνος ελέγχου:

dmesg | grep avc
logcat -d | grep "avc: denied"

Το root δεν το λύνει. Το SELinux περιορίζει τις διεργασίες με uid 0 ακριβώς όπως τις άλλες, οπότε ένα chroot που ξεκίνησε από κέλυφος root μπορεί ακόμη να απορριφθεί για μια συσκευή που βλέπει. Το να απενεργοποιήσεις την επιβολή για να δουλέψει ένας παλιός εγκαταστάτης είναι απόφαση για όλο το τηλέφωνο με συνέπειες πολύ πέρα από το τούνελ και δεν είναι διόρθωση για ένα ξεπερασμένο δυαδικό.

Γιατί οι εφαρμογές του Android αγνοούν το τούνελ σου

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

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

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

Η δυαδική συμβατότητα είναι ξεχωριστός τοίχος

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

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

Απόδειξέ το στο πλαίσιο του Android και καθάρισε μετά

Δοκίμασε αυτό που πραγματικά σε νοιάζει, από την πλευρά που μετράει: άνοιξε τη συγκεκριμένη εφαρμογή, φτάσε στον συγκεκριμένο ιδιωτικό προορισμό, επιβεβαίωσε ποιος resolver απάντησε, μετά αποσύνδεσε το τούνελ και επιβεβαίωσε τη τεκμηριωμένη συμπεριφορά. Ένα αποτέλεσμα από τερματικό μέσα στο chroot είναι απόδειξη για το πλαίσιο εκτέλεσης εκείνου του τερματικού και τίποτα περισσότερο.

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

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

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