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

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

Γιατί το hook περιμένει μια σήραγγα που περιμένει εκείνο

OpenVPN καλεί τα hooks του σύγχρονα, μέσα στην ίδια διεργασία που μετακινεί πακέτα. Το up ενεργοποιείται μόλις υπάρξει η συσκευή tun ή tap αλλά πριν προστεθεί οποιαδήποτε διαδρομή, και το route-up ενεργοποιείται μετά τις διαδρομές· καμία από τις δύο στιγμές δεν υπόσχεται ότι ο peer θα απαντήσει. Όσο ένα σκριπτ από οποιοδήποτε hook εκτελείται ακόμη, ο δαίμονας δεν προωθεί, οπότε μια εντολή που περιμένει κίνηση να διασχίσει τη σήραγγα περιμένει μια σήραγγα που περιμένει την εντολή. Αυτή η κυκλική αναμονή είναι ο λόγος που μια χειροκίνητη εκτέλεση περνά και το hook λήγει.

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

Επιλέξτε το hook κατά συμβάν, όχι κατά ευκολία

Συνδέστε το up σε εργασία που χρειάζεται μόνο τη συσκευή, το route-up σε εργασία που χρειάζεται διαδρομές, και κρατήστε το client-connect και το client-disconnect για εργασίες ανά πελάτη στην πλευρά του διακομιστή. Ο καθαρισμός κατά την αποσύνδεση πρέπει να αντέχει να εκτελεστεί δύο φορές, καθώς οι επανασυνδέσεις μέσω μόνιμης διεπαφής δεν ακολουθούν την ίδια ακολουθία με μια πλήρη επανεκκίνηση. Στον διακομιστή, το client-connect ενεργοποιείται όταν ο πελάτης πιστοποιείται, όχι όταν ξεκινά ο δαίμονας, κάτι που αξίζει επιβεβαίωση πριν μεταφερθεί εκεί η λογική. Αν η εργασία ανήκει στον κύκλο ζωής της υπηρεσίας και όχι σε μία σύνδεση, μια μονάδα systemd είναι καλύτερο σπίτι από οποιοδήποτε hook.

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

Τρεις τρόποι να αποσπάσετε την εργασία

Η πρώτη επιλογή είναι να στείλετε τον βοηθό στο παρασκήνιο μέσα από το hook: ξεκινήστε τον με setsid ή systemd-run --scope, κλείστε τους κληρονομημένους περιγραφείς και εξέλθετε αμέσως με μηδέν. Η δεύτερη είναι να γράψει το hook ένα μικρό αρχείο κατάστασης και να ενεργήσει πάνω του ένα χρονόμετρο systemd ή μια μονάδα διαδρομής, που κρατά το hook ασήμαντο και βάζει την πολιτική επαναλήψεων εκεί όπου υπάρχουν αρχεία καταγραφής. Η τρίτη είναι να εγκαταλείψετε εντελώς το hook και να μεταφέρετε την εργασία σε μονάδα που διατάσσεται μετά την υπηρεσία VPN, που είναι η σωστή απάντηση όταν η εργασία δεν είναι καθόλου ανά σύνδεση. Και οι τρεις μοιράζονται έναν κανόνα: το hook πρέπει να επιστρέψει πριν χρειαστεί τη σήραγγα.

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

Διαχωρίστε τις αστοχίες sandbox από τις αστοχίες κύκλου ζωής

Όταν ένα σκριπτ εκτελείται από προτροπή root και αποτυγχάνει ως υπηρεσία, η αιτία είναι συνήθως sandbox και όχι το δίκτυο. Ένα περιοριστικό ProtectHome, ένα μόνο για ανάγνωση ProtectSystem ή ένας κατάλογος εργασίας που δεν υπάρχει μπορούν να αφήσουν το σκριπτ ή τα δεδομένα του απρόσιτα, και σε κεντρικό υπολογιστή SELinux το αρχείο χρειάζεται επίσης συμφραζόμενο που επιτρέπει εκτέλεση. Διαβάστε τη μονάδα με το systemctl cat openvpn-server@server και το ημερολόγιο με το journalctl -u openvpn-server@server -n 80, μετά αναζητήστε σφάλμα άδειας ή συμφραζομένου αντί για χρονικό όριο σύνδεσης. Η απενεργοποίηση του sandbox πρέπει να είναι η τελευταία κίνηση, όχι η πρώτη.

Μια αστοχία κύκλου ζωής φαίνεται διαφορετική: το hook ξεκινά, ο βοηθός εκτελείται και το socket απλώς δεν είναι ακόμη εκεί. Γράψτε μια γραμμή με χρονική σήμανση από το ίδιο το hook, αποσυνδεθείτε και επανασυνδεθείτε, και διαβάστε τα γεγονότα με τη σειρά. Όταν ο βοηθός χρειάζεται πραγματικά τη σήραγγα, αφήστε τον να ελέγχει την ετοιμότητα αντί να κοιμάται για σταθερό διάστημα.

Τρία πεδία κάνουν την επόμενη αναφορά χρήσιμη: ποιο hook εκτελέστηκε, ποιον λογαριασμό χρησιμοποίησε και πού σταμάτησε. Χωρίς αυτά, κάθε μεταγενέστερη έρευνα ξεκινά από την αρχή.

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