आप /etc/ppp/ip-up में route कमांड डालते हैं, ऑफ़िस टनल फिर से जोड़ते हैं, और फ़ाइल कभी नहीं चलती। स्क्रिप्ट में कोई गड़बड़ नहीं है: वह कनेक्शन PPP से ही नहीं गुज़रता। अंतर्निहित Cisco IPSec और IKEv2 क्लाइंट कभी pppd शुरू नहीं करते, इसलिए हुक डिरेक्टरी कभी पढ़ी नहीं जाती, जबकि PPTP और IPSec पर L2TP अब भी उससे गुज़रते हैं। तय करें कि आपका कौन-सा मामला है, फिर ग़ैर-PPP मामले को launchd निगरानी जॉब से ट्रिगर करें।

कोई भी हुक संपादित करने से पहले इंटरफ़ेस जाँचें

दो कमांड तय करते हैं कि कौन-सी विधि काम कर सकती है। कॉन्फ़िगर की गई सेवाओं की सूची बनाएँ, फिर टनल चालू रहने के दौरान मौजूद इंटरफ़ेस की सूची बनाएँ। इंटरफ़ेस का नाम ही सबूत है; System Settings का लेबल नहीं।

scutil --nc list
ifconfig -l | tr ' ' '\n' | grep -E '^(utun|ppp)[0-9]+$'

ppp0 पैदा करने वाली सेवा PPP हुक चलाती है और आपकी फ़ाइल निष्पादित करेगी। Cisco IPSec या IKEv2 सेवा इसके बजाय utun डिवाइस पैदा करती है, PPP परत के बिना एक टनल इंटरफ़ेस, इसलिए /etc/ppp के अंदर कुछ भी उस तक नहीं पहुँच सकता। जब दोनों तरह दिखें, जाँचें कि आप किस सेवा से जुड़े थे। लोग क्लाइंट का नाम पढ़कर ग़लत हुक पर दोपहर बर्बाद करते हैं।

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 या ग्राफ़िकल एडिटर से बनी फ़ाइल अक्सर आपके खाते की हो जाती है, या उसमें निष्पादन बिट नहीं होता, और फिर वह ग़ायब हुक की तरह ही चुपचाप विफल हो जाती है। अब उसके बगल में 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 नवीनीकरण, केबल लगना। नीचे का पहरेदार शोरगुल वाले ट्रिगर को काम का हुक बना देता है, और एक लॉग पंक्ति अजीब घड़ी के रूट की व्याख्या करती है।

स्वामित्व स्क्रिप्ट के साथ 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 रूट पहले से होने पर शून्येतर स्थिति के साथ निकलता है, इसलिए हर शून्येतर स्थिति को विफलता मानने वाली स्क्रिप्ट सही काम करते समय भी हर बार टूटे हुक की रिपोर्ट करती है। ऊपर का netstat परीक्षण उस स्थिति को स्पष्ट no-op बना देता है।

इंटरफ़ेस की उपस्थिति दिखने से कमज़ोर सबूत है, क्योंकि अन्य VPN क्लाइंट और कुछ कंटेनर वातावरण भी 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 जाँचें। टनल बंद होने पर चली स्क्रिप्ट कनेक्शन मार्ग के बारे में कुछ साबित नहीं करती।

तोड़ने वाली शाखा भी जोड़ने वाली शाखा जैसी ही देखभाल की हक़दार है: रूट हाथ से हटाएँ, जॉब चलने दें, और पुष्टि करें कि वह वापस आता है। जो हुक रूट जोड़ता है और उसे कभी नहीं हटाता, वह एक सप्ताह बाद ग़लत व्यवहार करने वाली मशीन छोड़ जाता है, और दोनों घटनाओं को कुछ नहीं जोड़ता। जब दोनों व्यवहार टिके रहें, sudo launchctl bootout system/net.example.tunnel-watch जॉब को साफ़ तरीके से सेवानिवृत्त करता है। लोड किया हुआ छोड़ दिया गया निगरानी डेमन वही रास्ता है जिससे एकबारगी मरम्मत महीनों बाद बिना व्याख्या वाला रूट बन जाती है।

संबंधित लेख