VPN σε Mac συνδεδεμένο αλλά το ip-up δεν ενεργοποιήθηκε ποτέ: τρέξτε επιτήρηση launchd
Τα τούνελ Cisco IPSec και IKEv2 δεν ξεκινούν ποτέ το pppd, οπότε το /etc/ppp/ip-up μένει σιωπηλό. Επιτηρήστε τον κατάλογο ρυθμίσεων και κάντε το σκριπτ να αποδείξει το τούνελ.
Βάζετε μια εντολή route στο /etc/ppp/ip-up, επανασυνδέετε το τούνελ του γραφείου και το αρχείο δεν εκτελείται ποτέ. Δεν υπάρχει πρόβλημα με το σκριπτ: αυτή η σύνδεση δεν περνά καθόλου από το PPP. Οι ενσωματωμένοι πελάτες Cisco IPSec και IKEv2 δεν ξεκινούν ποτέ το pppd, οπότε ο κατάλογος hooks δεν διαβάζεται ποτέ, ενώ το PPTP και το L2TP πάνω από IPSec εξακολουθούν να περνούν από εκεί. Βρείτε ποια περίπτωση ισχύει για εσάς και μετά ενεργοποιήστε την περίπτωση χωρίς PPP από μια εργασία επιτήρησης launchd.
Ελέγξτε τη διεπαφή πριν επεξεργαστείτε οποιοδήποτε hook
Δύο εντολές καθορίζουν ποιος μηχανισμός μπορεί να δουλέψει. Καταγράψτε τις ρυθμισμένες υπηρεσίες και μετά καταγράψτε τις διεπαφές που υπάρχουν όσο το τούνελ είναι ενεργό. Το όνομα της διεπαφής είναι η απόδειξη· η ετικέτα στις Ρυθμίσεις Συστήματος δεν είναι.
scutil --nc list
ifconfig -l | tr ' ' '\n' | grep -E '^(utun|ppp)[0-9]+$'
Μια υπηρεσία που παράγει ppp0 εκτελεί τα hooks του PPP και θα εκτελέσει το αρχείο σας. Μια υπηρεσία Cisco IPSec ή IKEv2 παράγει αντ’ αυτού μια συσκευή utun, μια διεπαφή τούνελ χωρίς επίπεδο PPP, οπότε τίποτα μέσα στο /etc/ppp δεν μπορεί να τη φτάσει. Όταν εμφανίζονται και οι δύο τύποι, ελέγξτε σε ποια υπηρεσία συνδεθήκατε. Οι άνθρωποι χάνουν ένα απόγευμα στο λάθος hook διαβάζοντας το όνομα του πελάτη.
Στη διαδρομή PPP το αρχείο πρέπει να ανήκει στο root και να είναι εκτελέσιμο, γιατί το pppd ελέγχει και τα δύο πριν τρέξει οτιδήποτε. Το install ορίζει ιδιοκτήτη και λειτουργία σε ένα βήμα.
sudo install -o root -g wheel -m 0755 /dev/null /etc/ppp/ip-up
sudo ls -l /etc/ppp/ip-up
Ένα αρχείο που δημιουργείται μέσω Finder ή γραφικού επεξεργαστή συχνά καταλήγει να ανήκει στον λογαριασμό σας ή χωρίς το bit εκτέλεσης και μετά αποτυγχάνει τόσο σιωπηλά όσο το hook που έλειπε. Βάλτε τώρα το ip-down δίπλα του. Το root και το wheel στη στήλη ιδιοκτήτη μαζί με το rwxr-xr-x στη στήλη λειτουργίας είναι αυτό που θέλετε.
Αφήστε το launchd να ενεργοποιήσει το σκριπτ όταν εμφανιστεί τούνελ
Για πελάτες που δεν αγγίζουν ποτέ το PPP, το έναυσμα πρέπει να έρθει από αλλού, και το σύστημα αποθήκευσης ρυθμίσεων είναι η έντιμη πηγή: το macOS το ξαναγράφει σε κάθε μεταβολή του τούνελ. Μια εργασία launchd που επιτηρεί αυτόν τον κατάλογο καλείται όταν ένα τούνελ εμφανίζεται ή εξαφανίζεται.
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>WatchPaths</key>
<array><string>/Library/Preferences/SystemConfiguration</string></array>
<key>Label</key><string>net.example.tunnel-watch</string>
<key>ProgramArguments</key>
<array><string>/bin/sh</string><string>/usr/local/sbin/tunnel-hook</string></array>
<key>RunAtLoad</key><true/>
<key>ThrottleInterval</key><integer>20</integer>
</dict>
</plist>
Εγκαταστήστε το ως launch daemon, όχι ως πράκτορα ανά χρήστη, γιατί η επισκευή διαδρομών ανήκει στο μηχάνημα. Το bootstrap αντικαθιστά την παλαιότερη μορφή load -w στις τρέχουσες εκδόσεις. Το RunAtLoad κάνει την πρώτη εκτέλεση παρατηρήσιμη και το ThrottleInterval σταματά μια ριπή αλλαγών σύνδεσης Wi-Fi από το να εκκινεί το σκριπτ επανειλημμένα.
sudo install -o root -g wheel -m 0644 tunnel-watch.plist \
/Library/LaunchDaemons/net.example.tunnel-watch.plist
sudo launchctl bootstrap system \
/Library/LaunchDaemons/net.example.tunnel-watch.plist
Η παγίδα είναι ότι ο επιτηρούμενος κατάλογος αλλάζει και για συμβάντα άσχετα με το VPN σας: σύνδεση Wi-Fi, ανανέωση DHCP, καλώδιο που μπαίνει. Ο φύλακας παρακάτω μετατρέπει ένα θορυβώδες έναυσμα σε χρήσιμο hook, και μια γραμμή αρχείου καταγραφής εξηγεί μια διαδρομή σε παράξενη ώρα.
Η κυριότητα καλύπτει το plist όπως και το σκριπτ. Ένας δαίμονας που εκτελεί αρχείο σε κατάλογο όπου ο δικός σας λογαριασμός μπορεί να γράψει δίνει σε αυτόν τον λογαριασμό root.
Προστατέψτε το σκριπτ ώστε μια δεύτερη εκτέλεση να μην αλλάξει τίποτα
Το σκριπτ αποφασίζει πρώτα αν υπάρχει το τούνελ και βγαίνει ήσυχα όταν δεν υπάρχει. Όλα μετά πρέπει να είναι ασφαλή για επανάληψη, γιατί το έναυσμα ενεργοποιείται πολύ πιο συχνά από μία σύνδεση. Βρείτε τη διεπαφή κατά την εκτέλεση αντί να κωδικοποιήσετε σκληρά ένα ευρετήριο που αλλάζει στην επόμενη σύνδεση.
#!/bin/sh
set -u
TUN=$(ifconfig -l | tr ' ' '\n' | grep -m1 '^utun[0-9]' || true)
[ -n "$TUN" ] || exit 0
netstat -rn -f inet | grep -q '^10\.42' && exit 0
route -n add -net 10.42.0.0/16 -interface "$TUN"
Το route add βγαίνει με μη μηδενική κατάσταση όταν η διαδρομή υπάρχει ήδη, οπότε ένα σκριπτ που θεωρεί κάθε μη μηδενική κατάσταση αποτυχία αναφέρει σπασμένο hook κάθε φορά που κάνει το σωστό. Το τεστ με netstat παραπάνω μετατρέπει αυτή την περίπτωση σε ρητό no-op.
Η παρουσία της διεπαφής είναι πιο αδύναμη απόδειξη απ’ ό,τι φαίνεται, γιατί άλλοι πελάτες VPN και μερικά περιβάλλοντα container δημιουργούν επίσης συσκευές utun. Ρωτήστε την ίδια την υπηρεσία με το scutil --nc status "Office VPN" και απαιτήστε συνδεδεμένη κατάσταση πριν αγγίξετε τη δρομολόγηση. Κρατήστε την απάντηση σε γραμμή καταγραφής, γιατί μια εβδομάδα αργότερα αυτή η εγγραφή θα είναι η μόνη εξήγηση που θα έχετε.
Επαναφέρετε την πύλη χωρίς να σπάσετε το DNS
Όταν το τούνελ παίρνει την προεπιλεγμένη διαδρομή, η συνηθισμένη περιήγηση φεύγει από το γραφείο και η τοπική διαδρομή στο διαδίκτυο σταματά να δουλεύει. Πιάστε πρώτα τον δρομολογητή της φυσικής διεπαφής και μετά στρέψτε την προεπιλογή πίσω σε αυτόν. Το DHCP υπερτερεί της ανάλυσης πίνακα που κρατά ήδη την προεπιλογή του ίδιου του τούνελ.
PHYS=en0
GW=$(ipconfig getoption "$PHYS" router)
[ -n "$GW" ] && sudo route -n change default "$GW"
Οι επιλυτές είναι ξεχωριστό επίπεδο με ξεχωριστό εργαλείο, και η επισκευή της διαδρομής δεν τους επισκευάζει. Δείτε με το scutil --dns τι ισχύει και μετά διορθώστε αυτό που το παράγει: τη σειρά υπηρεσιών και τις εγγραφές DNS στη φυσική υπηρεσία. Το άδειασμα της κρυφής μνήμης διαγιγνώσκει μια αναζήτηση που κόλλησε μετά από αλλαγή δικτύου· δεν είναι κάτι για προγραμματισμό.
Ένα τούνελ που επιβιώνει από αλλαγή Wi-Fi ενώ το DNS παγώνει είναι τρίτο σφάλμα: το sudo killall -HUP mDNSResponder κάνει τον επιλυτή να ξαναδιαβάσει τη ρύθμισή του. Χρησιμοποιήστε το μία φορά, με το χέρι.
Αποδείξτε ότι η εργασία ενεργοποιείται μόνη της
Επιβάλετε μία εκτέλεση με το kickstart -k πριν εμπιστευτείτε τη διαδρομή επιτήρησης και μετά διαβάστε την κατάσταση εξόδου που κατέγραψε η εργασία. Μια καθαρή έξοδος αποδεικνύει ότι το σκριπτ δουλεύει· δεν αποδεικνύει ότι δουλεύει το έναυσμα. Μετά αποσυνδέστε και επανασυνδέστε με την εργασία φορτωμένη και προσέξτε για μια εκτέλεση που δεν ζητήσατε.
sudo launchctl kickstart -k system/net.example.tunnel-watch
sudo launchctl print system/net.example.tunnel-watch | grep -E 'last exit code|state ='
Ελέγξτε το scutil --nc status πριν και μετά από κάθε προσπάθεια. Ένα σκριπτ που έτρεξε όσο το τούνελ ήταν κάτω δεν αποδεικνύει τίποτα για τη διαδρομή σύνδεσης.
Ο κλάδος κατεδάφισης αξίζει την ίδια μεταχείριση με τον κλάδο σύνδεσης: αφαιρέστε τη διαδρομή με το χέρι, αφήστε την εργασία να τρέξει και επιβεβαιώστε ότι επιστρέφει. Ένα hook που προσθέτει διαδρομή και δεν την αφαιρεί ποτέ αφήνει ένα μηχάνημα που συμπεριφέρεται άσχημα μια εβδομάδα αργότερα, χωρίς τίποτα να συνδέει τα δύο γεγονότα. Όταν ισχύουν και οι δύο συμπεριφορές, το sudo launchctl bootout system/net.example.tunnel-watch αποσύρει την εργασία καθαρά. Ένας δαίμονας επιτήρησης που μένει φορτωμένος είναι ο τρόπος με τον οποίο μια εφάπαξ επισκευή γίνεται ανεξήγητη διαδρομή μήνες αργότερα.