/etc/ppp/ip-up ішіне route командасын саласыз, кеңсе туннелін қайта қосасыз, ал файл ешқашан орындалмайды. Скриптте еш мін жоқ: бұл қосылым PPP арқылы мүлде өтпейді. Кірістірілген Cisco IPSec және IKEv2 клиенттері pppd-ды ешқашан іске қоспайды, сондықтан hook қалтасы ешқашан оқылмайды, ал PPTP мен IPSec үстіндегі L2TP әлі де одан өтеді. Қай жағдай сізде екенін анықтаңыз, содан кейін PPP емес жағдайды launchd бақылау тапсырмасынан іске қосыңыз.

Кез келген hook-ты өңдеуден бұрын интерфейсті тексеріңіз

Екі команда қай механизм жұмыс істей алатынын шешеді. Конфигурацияланған қызметтерді тізімдеңіз, содан кейін туннель қосулы кезде бар интерфейстерді тізімдеңіз. Интерфейс атауы — дәлел; Жүйе параметрлеріндегі белгі емес.

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

ppp0 шығаратын қызмет PPP hook-тарын іске қосады және файлыңызды орындайды. 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 немесе графикалық редактор арқылы жасалған файл көбінесе сіздің тіркелгіңізге тиесілі болады немесе орындау биті жоқ болады, содан кейін жоқ 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 клиенттері мен кейбір контейнер орталары да 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 тапсырманы таза түрде зейнетке шығарады. Жүктелген күйде қалдырылған бақылау демоны — бір реттік жөндеудің айлардан кейін түсіндірілмеген маршрутқа айналу жолы.

Қатысты мақалалар