VPN Mac bersambung tetapi ip-up tidak pernah berjalan: jalankan pemantauan launchd
Tunnel Cisco IPSec dan IKEv2 tidak pernah memulakan pppd, jadi /etc/ppp/ip-up kekal senyap. Pantau direktori konfigurasi dan buat skrip membuktikan tunnel itu.
Anda meletakkan arahan route dalam /etc/ppp/ip-up, menyambung semula tunnel pejabat, dan fail itu tidak pernah berjalan. Tiada apa yang salah dengan skrip: sambungan itu tidak melalui PPP sama sekali. Klien terbina dalam Cisco IPSec dan IKEv2 tidak pernah memulakan pppd, jadi direktori cangkuk tidak pernah dibaca, manakala PPTP dan L2TP di atas IPSec masih melaluinya. Tentukan kes mana yang anda hadapi, kemudian picu kes bukan PPP daripada kerja pemantauan launchd.
Semak antara muka sebelum anda menyunting mana-mana cangkuk
Dua arahan menentukan mekanisme mana yang boleh berfungsi. Senaraikan perkhidmatan yang dikonfigurasikan, kemudian senaraikan antara muka yang wujud semasa tunnel hidup. Nama antara muka ialah buktinya; label dalam Tetapan Sistem bukan.
scutil --nc list
ifconfig -l | tr ' ' '\n' | grep -E '^(utun|ppp)[0-9]+$'
Perkhidmatan yang menghasilkan ppp0 menjalankan cangkuk PPP dan akan melaksanakan fail anda. Perkhidmatan Cisco IPSec atau IKEv2 sebaliknya menghasilkan peranti utun, antara muka tunnel tanpa lapisan PPP, jadi tiada apa pun di dalam /etc/ppp boleh mencapainya. Apabila kedua-dua jenis muncul, semak perkhidmatan mana yang anda sambungkan. Orang membuang satu petang pada cangkuk yang salah kerana membaca nama klien.
Pada laluan PPP fail itu mesti dimiliki oleh root dan boleh dilaksanakan, kerana pppd menyemak kedua-duanya sebelum menjalankan apa-apa. install menetapkan pemilik dan mod dalam satu langkah.
sudo install -o root -g wheel -m 0755 /dev/null /etc/ppp/ip-up
sudo ls -l /etc/ppp/ip-up
Fail yang dibuat melalui Finder atau editor grafik selalunya menjadi milik akaun anda, atau tanpa bit laksana, dan kemudian gagal sesenyap cangkuk yang hilang. Letakkan ip-down di sebelahnya sekarang. root dan wheel dalam lajur pemilik serta rwxr-xr-x dalam lajur mod ialah apa yang anda mahu.
Biarkan launchd mencetuskan skrip apabila tunnel muncul
Bagi klien yang tidak pernah menyentuh PPP, pencetus mesti datang dari tempat lain, dan stor konfigurasi sistem ialah sumber yang jujur: macOS menulis semulanya pada setiap peralihan tunnel. Kerja launchd yang memantau direktori itu dipanggil apabila tunnel muncul atau hilang.
<?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>
Pasang ia sebagai daemon launch, bukan agen setiap pengguna, kerana pembaikan laluan milik mesin. bootstrap menggantikan bentuk lama load -w pada keluaran semasa. RunAtLoad menjadikan pelaksanaan pertama boleh diperhati, dan ThrottleInterval menghalang gelombang perubahan sambungan Wi-Fi daripada melancarkan skrip berulang kali.
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
Perangkapnya ialah direktori yang dipantau berubah untuk peristiwa yang tiada kaitan dengan VPN anda: sambungan Wi-Fi, pembaharuan DHCP, kabel dipasang. Pengawal di bawah menukar pencetus bising menjadi cangkuk yang berguna, dan satu baris log menerangkan laluan pada jam yang pelik.
Pemilikan meliputi plist serta skrip. Daemon yang melaksanakan fail dalam direktori yang akaun anda sendiri boleh tulis menyerahkan root kepada akaun itu.
Lindungi skrip supaya larian kedua tidak mengubah apa-apa
Skrip mula-mula memutuskan sama ada tunnel wujud, dan keluar dengan senyap apabila tiada. Semua selepas itu mesti selamat diulang, kerana pencetus menyala jauh lebih kerap daripada satu sambungan. Selesaikan antara muka semasa masa jalan dan bukan mengekod keras indeks yang berubah pada sambungan seterusnya.
#!/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 keluar dengan status bukan sifar apabila laluan sudah wujud, jadi skrip yang menganggap setiap status bukan sifar sebagai kegagalan melaporkan cangkuk rosak setiap kali ia melakukan perkara yang betul. Ujian netstat di atas menukar kes itu menjadi no-op yang jelas.
Kehadiran antara muka ialah bukti yang lebih lemah daripada kelihatannya, kerana klien VPN lain dan sesetengah persekitaran kontena juga mencipta peranti utun. Tanya perkhidmatan itu sendiri dengan scutil --nc status "Office VPN" dan tuntut keadaan bersambung sebelum menyentuh penghalaan. Simpan jawapan dalam baris log, kerana seminggu kemudian rekod itu ialah satu-satunya penjelasan yang anda ada.
Bawa gateway kembali tanpa merosakkan DNS
Apabila tunnel mengambil alih laluan lalai, pelayaran biasa keluar melalui pejabat dan laluan internet tempatan berhenti berfungsi. Tangkap penghala antara muka fizikal dahulu, kemudian halakan lalai kembali kepadanya. DHCP mengalahkan penghuraian jadual yang sudah mengandungi lalai tunnel itu sendiri.
PHYS=en0
GW=$(ipconfig getoption "$PHYS" router)
[ -n "$GW" ] && sudo route -n change default "$GW"
Penyelesai ialah lapisan berasingan dengan alat berasingan, dan membaiki laluan tidak membaiki mereka. Lihat apa yang berkuat kuasa dengan scutil --dns, kemudian baiki apa yang menghasilkannya: susunan perkhidmatan dan entri DNS pada perkhidmatan fizikal. Mengosongkan cache mendiagnosis carian yang tersekat selepas pertukaran rangkaian; ia bukan sesuatu untuk dijadualkan.
Tunnel yang bertahan melalui perubahan Wi-Fi sementara DNS tersekat ialah kerosakan ketiga: sudo killall -HUP mDNSResponder membuat penyelesai membaca semula konfigurasinya. Gunakan sekali sahaja, dengan tangan.
Buktikan bahawa kerja itu menyala sendiri
Paksa satu larian dengan kickstart -k sebelum anda mempercayai laluan pemantauan, kemudian baca status keluar yang direkodkan oleh kerja itu. Keluar bersih membuktikan skrip berfungsi; ia tidak membuktikan pencetus berfungsi. Kemudian putuskan dan sambung semula dengan kerja dimuatkan, dan perhatikan larian yang anda tidak minta.
sudo launchctl kickstart -k system/net.example.tunnel-watch
sudo launchctl print system/net.example.tunnel-watch | grep -E 'last exit code|state ='
Semak scutil --nc status sebelum dan selepas setiap percubaan. Skrip yang berjalan semasa tunnel turun tidak membuktikan apa-apa tentang laluan sambungan.
Cabang perobohan berhak mendapat layanan yang sama seperti cabang sambungan: buang laluan dengan tangan, biarkan kerja berjalan, dan pastikan ia kembali. Cangkuk yang menambah laluan dan tidak pernah membuangnya meninggalkan mesin yang berkelakuan buruk seminggu kemudian, tanpa apa-apa yang menghubungkan dua peristiwa itu. Setelah kedua-dua tingkah laku bertahan, sudo launchctl bootout system/net.example.tunnel-watch menamatkan kerja itu dengan bersih. Daemon pemantauan yang dibiarkan dimuatkan ialah cara pembaikan sekali jalan menjadi laluan yang tidak dijelaskan berbulan-bulan kemudian.