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

Ο αντιστοιχιστής σπάνια φταίει

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

Η κενή εγγραφή A είναι το κλασικό λάθος. Η επιστροφή NOERROR με μηδέν απαντήσεις μοιάζει με έγκυρη απάντηση, οπότε ο stub resolver τη δέχεται, το πρόγραμμα περιήγησης ξαναπροσπαθεί, δοκιμάζει AAAA, δοκιμάζει άλλον resolver και τα παρατάει πολύ αργότερα. Ένας κωδικός απάντησης 3, NXDOMAIN, με το τμήμα ερώτησης σε επανάληψη και το αναγνωριστικό συναλλαγής αντιγραμμένο τελειώνει τη συζήτηση αμέσως. Χρησιμοποιήστε τον για κάθε όνομα που αρνείστε σκόπιμα.

Το IPv6 αξίζει την ίδια απόφαση και όχι μια προεπιλογή. Αν απαντάτε NXDOMAIN για A και αφήνετε το AAAA να περάσει, ο πελάτης μπορεί να φτάσει το αποκλεισμένο όνομα μέσω IPv6 και το φίλτρο διαρρέει. Μερικές υλοποιήσεις απαντούν στα αποκλεισμένα ερωτήματα AAAA με διεύθυνση loopback ώστε η σύνδεση να αποτυγχάνει αμέσως αντί να πέφτει σε εναλλακτική. Διαλέξτε μία πολιτική, εφαρμόστε την και στους δύο τύπους εγγραφών και καταγράψτε και τις δύο.

Μια διαδρομή που τα πιάνει όλα κατέχει τα πάντα

Ένας σχεδιασμός μόνο με DNS δεν προσθέτει ποτέ addRoute("0.0.0.0", 0), οπότε μόνο τα ερωτήματα μπαίνουν στη διεπαφή TUN και όλα τα άλλα συνεχίζουν να χρησιμοποιούν το υποκείμενο δίκτυο. Αυτό είναι το ασφαλές σχήμα, και εξηγεί επίσης γιατί μερικές λίστες επιτρεπόμενων φαίνεται να δουλεύουν στο Wi-Fi και αποτυγχάνουν στο δίκτυο κινητής.

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

Το socket του resolver πρέπει να βγει από τη σήραγγα

Η προώθηση είναι εκεί όπου βρίσκεται η επόμενη παγίδα. Οι resolvers των παρόχων συχνά ζουν σε ιδιωτική διεύθυνση που η σήραγγα δεν φτάνει, οπότε το ερώτημα που προωθείτε πάει πουθενά και η εφαρμογή αναφέρει λήξη χρόνου ανάγνωσης. Στείλτε τα εγκεκριμένα ερωτήματα σε έναν resolver που ξέρετε ότι είναι προσβάσιμος, και περάστε πρώτα αυτό το socket στο VpnService.protect(). Ένα μη προστατευμένο socket στέλνει το ερώτημα πίσω στη δική σας σήραγγα, όπου φτάνει ξανά στην εφαρμογή και γυρίζει μέχρι να ενεργοποιηθεί το χρονικό όριο.

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

Το μέγεθος και τα αθροίσματα ελέγχου αποτυγχάνουν χωρίς μήνυμα

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

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

Τι δεν θα κάνει ένα VpnService για εσάς

Δύο όρια αξίζει να τα ξέρετε πριν σχεδιάσετε γύρω τους. Καμία συνηθισμένη εφαρμογή δεν μπορεί να εγκαταστήσει διακομιστή μεσολάβησης σε επίπεδο συστήματος ή αρχείο PAC εκτός Wi-Fi, και αυτό το κομμάτι δεν έχει αλλάξει. Η διαδρομή ανά εφαρμογή άλλαξε: πριν από το API 29 το VpnService.Builder δεν μπορούσε να μεταφέρει καθόλου διακομιστή μεσολάβησης, και από το API 29 το setHttpProxy(ProxyInfo.buildPacProxy(uri)) δίνει στην πλατφόρμα ένα σενάριο PAC για αξιολόγηση για το δίκτυο VPN. Αξιολογήστε τους κανόνες στον δικό σας κώδικα όταν στοχεύετε παλαιότερα API ή όταν το μοντέλο PAC δεν μπορεί να εκφράσει τον κανόνα. Ούτε το UDP είναι δωρεάν: τα προγράμματα περιήγησης στέλνουν μόνο TCP μέσω διακομιστή μεσολάβησης SOCKS, και οι περισσότεροι πελάτες SOCKS5 δεν υλοποιούν ποτέ το UDP ASSOCIATE, οπότε ένας σχεδιασμός βασισμένος σε διακομιστή μεσολάβησης απορρίπτει ή διαρρέει UDP ενώ το TCP φαίνεται υγιές.

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

Ελέγξτε με αυτή τη σειρά

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

  1. Καταγράψτε τις εγκατεστημένες διαδρομές και επιβεβαιώστε αν πακέτα που δεν είναι DNS μπαίνουν καθόλου στη διεπαφή TUN.
  2. Καταγράψτε το όνομα του ερωτήματος, την απόφαση και τον κωδικό απάντησης για ένα αποκλεισμένο και ένα εγκεκριμένο όνομα.
  3. Επιβεβαιώστε ότι το socket του resolver είναι προστατευμένο και ότι ο επιλεγμένος resolver απαντά από μέσα στη σήραγγα.
  4. Επιβεβαιώστε το MTU της διεπαφής και το άθροισμα ελέγχου μιας απάντησης που φτιάξατε με το χέρι.
  5. Επαναλάβετε την ίδια σελίδα σε Wi-Fi και σε δίκτυο κινητής, αφού οι resolvers του παρόχου και το MTU της διαδρομής διαφέρουν.

Αν και τα πέντε κρατήσουν και η σελίδα κολλάει ακόμη, ο επόμενος ύποπτος είναι ο ίδιος ο προωθητής: συγκρίνετε ένα καταγεγραμμένο αίτημα με μια καταγεγραμμένη απάντηση και ψάξτε για πλήθος byte που λείπει ή μισόκλειστο socket. Η αναφορά του VpnService.Builder καλύπτει τα συμβόλαια διαδρομής, DNS και MTU, και το protect() είναι ξεχωριστή κλήση VpnService και όχι επιλογή του builder· μια συνδεδεμένη διεπαφή σημαίνει μόνο ότι το πρώτο συμβόλαιο εκπληρώθηκε.

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