Αποτυχία client-connect στο OpenVPN: είναι εγγυημένος ο καθαρισμός στο disconnect;
Ένας απορριφθείς πελάτης δεν αναιρεί έναν κανόνα τείχους προστασίας ούτε μια γραμμένη εγγραφή. Συγκρίνετε το συμβόλαιο της επιστροφής κλήσης με την επαναφορά που πρέπει να κάνει μόνο του το hook σας.
Όταν ένα script client-connect εξέρχεται με μη μηδενικό κωδικό, το OpenVPN απορρίπτει τον πελάτη και οι διαχειριστές συνήθως υποθέτουν ότι το αντίστοιχο script client-disconnect τακτοποιεί τα πάντα. Συχνά δεν εκτελείται ποτέ, επειδή η επεξεργασία disconnect εξαρτάται από το τι κατάφερε να ολοκληρώσει το στάδιο connect. Το να αντιμετωπίζουμε την απόρριψη και την επαναφορά ως έναν μηχανισμό είναι αυτό που μετατρέπει μια αποτυχημένη σύνδεση σε διαρρεύσαντα κανόνα τείχους προστασίας ή σε ορφανή εγγραφή. Είναι δύο ξεχωριστές υποχρεώσεις και μόνο μία από αυτές είναι αυτόματη. Διαβάστε την ίδια τη διαδρομή εξόδου του hook πριν κατηγορήσετε τον διακομιστή ότι άφησε κατάσταση πίσω του.
Μια μη μηδενική έξοδος απορρίπτει τον πελάτη· δεν αναιρεί τη δουλειά σας
Η κατάσταση εξόδου του client-connect είναι απόφαση εισδοχής. Το μηδέν σημαίνει εισδοχή, οτιδήποτε άλλο σημαίνει κατεδάφιση του στιγμιότυπου πριν εδραιωθεί πλήρως. Τίποτα σε αυτό το συμβόλαιο δεν εξετάζει τι έχει ήδη κάνει το script στον έξω κόσμο. Αν το script πρόσθεσε κανόνα iptables, έγραψε γραμμή ή αύξησε μετρητή, αυτές οι αλλαγές επιβιώνουν της απόρριψης.
Η ίδια ασυμμετρία ισχύει για τα πρόσθετα, όπου πολλές συναρτήσεις connect μπορούν να εκτελεστούν για ένα στιγμιότυπο. Μια μεταγενέστερη αποτυχία δεν ακυρώνει αναδρομικά μια προηγούμενη επιτυχία και η προηγούμενη συνάρτηση δεν έχει τρόπο να μάθει ότι μια αδελφή συνάρτηση απέτυχε.
Η απόρριψη είναι αυτόματη, ο καθαρισμός όχι
Το εγχειρίδιο του OpenVPN 2.6 συνδέει την επεξεργασία client-disconnect με την προηγούμενη επιτυχή επεξεργασία connect. Μια τεκμηριωμένη εξαίρεση καλύπτει αλυσίδες καταρράκτη: αν ένα βήμα connect έχει ήδη επιστρέψει επιτυχία, τα αντίστοιχα βήματα disconnect εκτελούνται παρ’ όλα αυτά όταν κατεδαφίζεται το στιγμιότυπο, ακόμη και αν ένα μεταγενέστερο βήμα connect απέτυχε. Αυτή η εξαίρεση είναι στενή και εξαρτάται από το πόσες επιστροφές κλήσης έχουν ρυθμιστεί, γι’ αυτό η δοκιμή ενός μόνο script κελύφους δεν σας λέει τίποτα για μια αλυσίδα.
Χαρτογραφήστε την πραγματική διαμόρφωση πριν σχεδιάσετε γύρω της: ποιο script, ποιο πρόσθετο και με ποια σειρά εκτελούνται. Ο πίνακας παρακάτω απαριθμεί τι αφήνει πίσω μια μισοτελειωμένη εγκατάσταση.
| What the hook did before failing | What the client sees | What stays behind |
|---|---|---|
| Created a firewall entry | A rejection, with no tunnel | A rule matching an address nobody owns |
| Wrote a state row | A rejection, with no tunnel | A record of a session that never started |
| Allocated a tunnel address | A rejection, with no tunnel | An address marked busy until something releases it |
Κάθε γραμμή τελειώνει με τον ίδιο τρόπο για τον πελάτη και διαφορετικά για τον κεντρικό υπολογιστή. Ο πελάτης δεν μπορεί να πει ποια από αυτές συνέβη, οπότε το hook πρέπει να αναιρέσει ό,τι έκανε πριν επιστρέψει την κατάσταση αποτυχίας.
Αντισταθμίστε μέσα στο script που απέτυχε
Επικυρώστε ό,τι μπορείτε πριν αγγίξετε κοινόχρηστη κατάσταση: πεδία πιστοποιητικού, διαθεσιμότητα διεύθυνσης, την ομάδα στην οποία ανήκει ο πελάτης. Η φθηνότερη απόρριψη είναι αυτή που συμβαίνει πριν από οποιαδήποτε κατανομή. Μόλις η εγκατάσταση καλύψει πολλές εξωτερικές λειτουργίες, κρατήστε αρχείο για το ποιες ολοκληρώθηκαν και αναιρέστε τις με αντίστροφη σειρά πριν επιστρέψετε την κατάσταση αποτυχίας.
Συγκεκριμένη περίπτωση: το script δημιουργεί καταχώριση τείχους προστασίας ανά πελάτη και μετά αποτυγχάνει να γράψει τη γραμμή κατάστασης που την περιγράφει. Ο κλάδος που αποτυγχάνει πρέπει να αφαιρέσει την καταχώριση που μόλις δημιούργησε και μετά να εξέλθει με μη μηδενικό κωδικό. Το να περιμένεις ένα συμβάν disconnect που μπορεί να μην προγραμματιστεί ποτέ είναι ο τρόπος με τον οποίο ένας κανόνας επιβιώνει της συνεδρίας για την οποία προοριζόταν.
Κάντε την αντιστάθμιση ιδεμποτεντή και με ιδιοκτήτη
Ο καθαρισμός πρέπει να είναι ασφαλής για διπλή εκτέλεση και ακριβής ως προς το τι επιτρέπεται να διαγράψει. Ένα καθυστερημένο συμβάν από προηγούμενη προσπάθεια δεν πρέπει να αφαιρέσει την κατανομή μιας νεότερης συνεδρίας μόνο και μόνο επειδή και οι δύο μοιράζονται κοινό όνομα ή ανακυκλωμένη διεύθυνση σήραγγας. Καταγράψτε τη συγκεκριμένη λαβή ή το αναγνωριστικό λειτουργίας μαζί με τον πόρο και διαγράψτε με αυτό το κλειδί και όχι με το όνομα. Οι συναλλαγές βάσης δεδομένων βοηθούν μόνο με τις αλλαγές της ίδιας της βάσης· ένας κανόνας τείχους προστασίας εκτός αυτού του ορίου χρειάζεται ρητό βήμα αντιστάθμισης.
Υποθέστε ότι η διεργασία μπορεί να πεθάνει μεταξύ της αλλαγής και του καθαρισμού και προσθέστε έναν συμβιβαστή που συγκρίνει την εξωτερική κατάσταση με τη λίστα των εισδεκτών πελατών σε τακτικό πρόγραμμα.
Δοκιμάστε τα τρία μονοπάτια που πραγματικά διαφέρουν
Εξασκηθείτε σε τρεις περιπτώσεις: απόρριψη πριν κατανεμηθεί οτιδήποτε, απόρριψη μετά από μερική κατανομή και μια κανονική εισδεκτή συνεδρία που αργότερα τελειώνει. Αυτές οι τρεις παράγουν διαφορετικές γραμμές καταγραφής και διαφορετικά κατάλοιπα. Ελέγξτε την εξωτερική κατάσταση μετά από καθεμία, όχι μόνο το μήνυμα αποτυχίας του πελάτη, γιατί η αποτυχία του πελάτη είναι το αναμενόμενο αποτέλεσμα στις δύο από τις τρεις.
Καταγράψτε το στάδιο του hook, την κατάσταση εξόδου και τι κατανεμήθηκε ή απελευθερώθηκε, χωρίς τα διαπιστευτήρια. Ένα αρχείο καταγραφής του hook που ονομάζει τον πόρο που δημιούργησε είναι αυτό που κάνει έναν διαρρεύσαντα κανόνα ανιχνεύσιμο έξι μήνες αργότερα.