Įrašote route komandą į /etc/ppp/ip-up, iš naujo prisijungiate prie biuro tunelio, o failas niekada neįvykdomas. Su scenarijumi viskas gerai: tas ryšys visai neina per PPP. Įmontuoti Cisco IPSec ir IKEv2 klientai niekada nepaleidžia pppd, todėl hook katalogas niekada neskaitomas, o PPTP ir L2TP per IPSec vis dar eina pro jį. Nustatykite, kuris atvejis jūsų, tada paleiskite ne PPP atvejį iš launchd stebėjimo užduoties.

Patikrinkite sąsają prieš redaguodami bet kurį hook

Dvi komandos nusprendžia, kuris mechanizmas gali veikti. Išvardykite sukonfigūruotas paslaugas, tada išvardykite sąsajas, kurios egzistuoja, kol tunelis įjungtas. Sąsajos pavadinimas yra įrodymas; etiketė sistemos nustatymuose – ne.

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

Paslauga, kuri sukuria ppp0, vykdo PPP hook ir įvykdys jūsų failą. Cisco IPSec arba IKEv2 paslauga vietoj to sukuria utun įrenginį, tunelio sąsają be PPP sluoksnio, todėl niekas /etc/ppp viduje negali jo pasiekti. Kai pasirodo abi rūšys, patikrinkite, prie kurios paslaugos prisijungėte. Žmonės praranda popietę prie netinkamo hook skaitydami kliento pavadinimą.

PPP kelyje failas turi priklausyti root ir būti vykdomas, nes pppd patikrina abu prieš ką nors paleisdamas. install nustato savininką ir režimą vienu žingsniu.

sudo install -o root -g wheel -m 0755 /dev/null /etc/ppp/ip-up
sudo ls -l /etc/ppp/ip-up

Failas, sukurtas per Finder arba grafinį redaktorių, dažnai atsiduria jūsų paskyros nuosavybėje arba be vykdymo bito, o tada nepavyksta taip tyliai kaip trūkstamas hook. Dabar padėkite ip-down šalia. root ir wheel savininko stulpelyje bei rwxr-xr-x režimo stulpelyje yra tai, ko norite.

Leiskite launchd paleisti scenarijų, kai pasirodo tunelis

Klientams, kurie niekada neliečia PPP, trigeris turi ateiti iš kitur, o sistemos konfigūracijos saugykla yra sąžiningas šaltinis: macOS ją perrašo kiekvieno tunelio perėjimo metu. Šį katalogą stebinti launchd užduotis iškviečiama, kai tunelis pasirodo arba dingsta.

<?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>

Įdiekite jį kaip launch daemon, o ne kaip kiekvieno naudotojo agentą, nes maršrutų taisymas priklauso mašinai. bootstrap dabartinėse versijose pakeičia senesnę load -w formą. RunAtLoad padaro pirmą vykdymą stebimą, o ThrottleInterval neleidžia „Wi-Fi“ prisijungimų pokyčių srautui kartoti scenarijaus paleidimo.

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

Spąstai yra tai, kad stebimas katalogas keičiasi ir dėl įvykių, nesusijusių su jūsų VPN: „Wi-Fi“ prisijungimo, DHCP atnaujinimo, įkišto kabelio. Toliau esantis sargas paverčia triukšmingą trigerį naudingu hook, o žurnalo eilutė paaiškina neįprastos valandos maršrutą.

Nuosavybė apima plist taip pat kaip ir scenarijų. Daemonas, vykdantis failą kataloge, į kurį jūsų paskyra gali rašyti, atiduoda tai paskyrai root.

Apsaugokite scenarijų, kad antras paleidimas nieko nepakeistų

Scenarijus pirmiausia nusprendžia, ar tunelis egzistuoja, ir tyliai išeina, jei ne. Viskas po to turi būti saugu kartoti, nes trigeris suveikia daug dažniau nei vienas prisijungimas. Išspręskite sąsają vykdymo metu, o ne koduokite indeksą, kuris pasikeis kitą kartą prisijungus.

#!/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 išeina su ne nuliniu statusu, kai maršrutas jau yra, todėl scenarijus, kuris kiekvieną ne nulinį statusą laiko klaida, kiekvieną kartą, kai elgiasi teisingai, praneša apie sulaužytą hook. Aukščiau esantis netstat testas paverčia tą atvejį aiškiu no-op.

Sąsajos buvimas yra silpnesnis įrodymas, nei atrodo, nes kiti VPN klientai ir kai kurios konteinerių aplinkos taip pat kuria utun įrenginius. Klauskite pačios paslaugos su scutil --nc status "Office VPN" ir reikalaukite prisijungusio būvio prieš liesdami maršrutizavimą. Laikykite atsakymą žurnalo eilutėje, nes po savaitės tas įrašas bus vienintelis paaiškinimas, kurį turėsite.

Grąžinkite tinklų sietuvą nesulaužę DNS

Kai tunelis perima numatytąjį maršrutą, įprasta naršymas išeina per biurą ir vietinis interneto kelias nustoja veikti. Pirmiausia užfiksuokite fizinės sąsajos maršrutizatorių, tada nukreipkite numatytąjį atgal į jį. DHCP yra geriau nei lentelės, kurioje jau yra paties tunelio numatytasis maršrutas, analizavimas.

PHYS=en0
GW=$(ipconfig getoption "$PHYS" router)
[ -n "$GW" ] && sudo route -n change default "$GW"

Resursų sprendėjai yra atskiras sluoksnis su atskiru įrankiu, ir maršruto taisymas jų netaiso. Pažiūrėkite su scutil --dns, kas galioja, tada pataisykite tai, kas tai sukuria: paslaugų tvarką ir DNS įrašus fizinėje paslaugoje. Podėlio išvalymas diagnozuoja po tinklo pakeitimo įstrigusią užklausą; tai ne tai, ką reikėtų planuoti.

Tunelis, kuris išgyvena „Wi-Fi“ pakeitimą, bet DNS užstringa, yra trečia gedimas: sudo killall -HUP mDNSResponder priverčia sprendėją iš naujo perskaityti konfigūraciją. Naudokite jį vieną kartą, ranka.

Įrodykite, kad užduotis paleidžiama pati

Priverskite vieną paleidimą su kickstart -k prieš pasitikėdami stebėjimo keliu, tada perskaitykite užduoties įrašytą išėjimo statusą. Švarus išėjimas įrodo, kad scenarijus veikia; tai neįrodo, kad veikia trigeris. Tada atjunkite ir vėl prisijunkite su įkelta užduotimi ir stebėkite paleidimą, kurio neprašėte.

sudo launchctl kickstart -k system/net.example.tunnel-watch
sudo launchctl print system/net.example.tunnel-watch | grep -E 'last exit code|state ='

Patikrinkite scutil --nc status prieš ir po kiekvieno bandymo. Scenarijus, kuris veikė tuneliui esant išjungtam, nieko neįrodo apie prisijungimo kelią.

Išmontavimo šaka nusipelno tokio pat elgesio kaip prisijungimo šaka: pašalinkite maršrutą ranka, leiskite užduočiai veikti ir patvirtinkite, kad jis grįžta. Hook, kuris prideda maršrutą ir niekada jo nepašalina, palieka mašiną, kuri po savaitės elgiasi blogai, ir niekas nesieja dviejų įvykių. Kai abi elgsenos išsilaiko, sudo launchctl bootout system/net.example.tunnel-watch švariai atleidžia užduotį. Įkeltas paliktas stebėjimo daemonas yra kelias, kuriuo vienkartinis taisymas po mėnesių tampa nepaaiškintu maršrutu.

Susiję straipsniai