آپ /etc/ppp/ip-up میں route کمانڈ رکھتے ہیں، دفتر کی ٹنل دوبارہ جوڑتے ہیں، اور فائل کبھی نہیں چلتی۔ اسکرپٹ میں کوئی خرابی نہیں: وہ کنکشن PPP سے ہی نہیں گزرتا۔ بلٹ اِن Cisco IPSec اور IKEv2 کلائنٹ کبھی pppd شروع نہیں کرتے، اس لیے hook فولڈر کبھی نہیں پڑھا جاتا، جبکہ PPTP اور IPSec پر L2TP اب بھی اس سے گزرتے ہیں۔ طے کریں کہ آپ کا کون سا معاملہ ہے، پھر غیر-PPP معاملہ launchd نگرانی کے کام سے چلائیں۔

کوئی بھی hook ترمیم کرنے سے پہلے interface جانچیں

دو کمانڈیں طے کرتی ہیں کہ کون سا طریقہ کار کر سکتا ہے۔ تشکیل شدہ سروسز کی فہرست بنائیں، پھر وہ interfaces گنیں جو ٹنل کے قائم رہنے کے دوران موجود ہیں۔ interface کا نام ہی ثبوت ہے؛ System Settings کا لیبل نہیں۔

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

جو سروس ppp0 پیدا کرتی ہے وہ PPP hook چلاتی ہے اور آپ کی فائل چلائے گی۔ Cisco IPSec یا IKEv2 سروس اس کے بجائے utun ڈیوائس بناتی ہے، PPP پرت کے بغیر ٹنل interface، اس لیے /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 یا گرافیکل ایڈیٹر سے بنی فائل اکثر آپ کے اکاؤنٹ کی ملکیت میں آ جاتی ہے، یا اس میں اجرا کا بِٹ نہیں ہوتا، اور پھر غائب 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 دے دیتا ہے۔

اسکرپٹ کی حفاظت کریں تاکہ دوسرا چلنا کچھ نہ بدلے

اسکرپٹ پہلے طے کرتا ہے کہ ٹنل موجود ہے یا نہیں، اور نہ ہونے پر خاموشی سے نکل جاتا ہے۔ اس کے بعد سب کچھ دہرانے کے لیے محفوظ ہونا چاہیے، کیونکہ محرک ایک کنکشن سے کہیں زیادہ بار چلتا ہے۔ اگلے کنکشن پر بدلنے والے انڈیکس کو ہارڈ کوڈ کرنے کے بجائے رن ٹائم پر interface حل کریں۔

#!/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 بنا دیتا ہے۔

interface کی موجودگی دکھنے سے کمزور ثبوت ہے، کیونکہ دوسرے VPN کلائنٹ اور بعض کنٹینر ماحول بھی utun ڈیوائس بناتے ہیں۔ scutil --nc status "Office VPN" کے ساتھ خود سروس سے پوچھیں اور روٹنگ چھونے سے پہلے منسلک حالت کا مطالبہ کریں۔ جواب لاگ کی ایک سطر میں رکھیں، کیونکہ ایک ہفتے بعد وہی ریکارڈ آپ کے پاس واحد وضاحت ہوگا۔

DNS توڑے بغیر گیٹ وے واپس لائیں

جب ٹنل ڈیفالٹ راستہ لے لیتی ہے، عام براؤزنگ دفتر کے راستے باہر جاتی ہے اور مقامی انٹرنیٹ راستہ کام کرنا چھوڑ دیتا ہے۔ پہلے فزیکل interface کا راؤٹر پکڑیں، پھر ڈیفالٹ کو واپس اسی کی طرف موڑیں۔ 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 کام کو صاف طور پر ریٹائر کرتا ہے۔ لوڈ کیا ہوا چھوڑ دیا گیا نگرانی ڈیمن وہی راستہ ہے جس سے ایک بار کی مرمت مہینوں بعد بے وضاحت راستہ بن جاتی ہے۔

متعلقہ مضامین