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

Δύο διευθύνσεις, δύο διαφορετικοί ισχυρισμοί

Το εξωτερικό άκρο είναι αυτό που παρατήρησε ο διακομιστής όταν συνδέθηκε ο πελάτης, διαθέσιμο ως trusted_ip για IPv4 και trusted_ip6 για IPv6. Η εικονική διεύθυνση είναι αυτή που εκχώρησε η δεξαμενή για αυτή τη συνεδρία, διαθέσιμη ως ifconfig_pool_remote_ip.

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

Μια ελάχιστη ανάγνωση μοιάζει έτσι.

$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner  = getenv('ifconfig_pool_remote_ip');
$outer  = $outer4 !== false ? $outer4 : $outer6;

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

Ελέγξτε πώς ξεκίνησε το PHP, όχι το κέλυφός σας

Το hook τρέχει ως παιδί του δαίμονα VPN με περιβάλλον που χτίζει ο δαίμονας. Το διαδραστικό σας κέλυφος έχει άλλο, και το να τρέξετε το σκριπτ με το χέρι δοκιμάζει το περιβάλλον του κελύφους και όχι του hook.

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

Μετά επιβεβαιώστε ποιος διερμηνέας και ποιο αρχείο ρυθμίσεων χρησιμοποιεί αυτή η κλήση. Η επεξεργασία των ρυθμίσεων PHP για έναν διακομιστή ιστού δεν αλλάζει τίποτα σε μια διεργασία CLI που ξεκίνησε το OpenVPN, και τα δύο μπορούν να φορτώσουν εντελώς διαφορετικά αρχεία php.ini.

Γιατί ένα κενό $_ENV δεν αποδεικνύει τίποτα

Η αναφορά getenv του PHP τεκμηριώνει άμεση ανάγνωση του περιβάλλοντος της διεργασίας, που επιστρέφει false όταν το όνομα απουσιάζει. Η υπερκαθολική $_ENV γεμίζει χωριστά, και η οδηγία variables_order αποφασίζει ποιες υπερκαθολικές γεμίζουν.

Αν αυτή η οδηγία παραλείπει το E, το $_ENV μένει κενό ό,τι κι αν περιέχει το περιβάλλον. Κώδικας που το ευρετηριάζει αναφέρει τότε μια μεταβλητή που λείπει ενώ στην πραγματικότητα υπάρχει, και η έρευνα κατευθύνεται προς το OpenVPN ενώ η απάντηση είναι στο php.ini. Ελέγξτε την οδηγία ειδικά για τη ρύθμιση CLI, όχι για τον διακομιστή ιστού.

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

Αποθηκεύστε μια συσχέτιση, όχι ενημέρωση γραμμής

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

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

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

Διαγνώστε χωρίς να πετάτε το περιβάλλον

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

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

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