Mac VPN csatlakozva, de az ip-up soha nem futott le: állíts be launchd figyelőt
A Cisco IPSec és IKEv2 alagutak soha nem indítják el a pppd-t, ezért az /etc/ppp/ip-up csendben marad. Figyeld a konfigurációs könyvtárat, és késztesd a szkriptet az alagút bizonyítására.
Egy route parancsot teszel a /etc/ppp/ip-up fájlba, újracsatlakozol az irodai alagúthoz, és a fájl soha nem fut le. A szkripttel semmi baj: az a kapcsolat egyáltalán nem megy át PPP-n. A beépített Cisco IPSec és IKEv2 kliensek soha nem indítják el a pppd-t, így a hook könyvtár soha nem olvasódik, miközben a PPTP és az IPSec feletti L2TP továbbra is átmegy rajta. Állapítsd meg, melyik eset áll fenn, majd indítsd el a nem-PPP esetet egy launchd figyelő feladatból.
Ellenőrizd az interfészt, mielőtt bármelyik hookot szerkeszted
Két parancs dönti el, melyik mechanizmus működhet. Listázd a beállított szolgáltatásokat, majd listázd azokat az interfészeket, amelyek az alagút aktív állapotában léteznek. Az interfész neve a bizonyíték; a Rendszerbeállításokban látható címke nem az.
scutil --nc list
ifconfig -l | tr ' ' '\n' | grep -E '^(utun|ppp)[0-9]+$'
Az a szolgáltatás, amely ppp0-t hoz létre, futtatja a PPP hookokat, és végrehajtja a fájlodat. A Cisco IPSec vagy IKEv2 szolgáltatás helyette utun eszközt hoz létre, PPP réteg nélküli alagút-interfészt, így a /etc/ppp belsejében semmi nem érheti el. Amikor mindkét fajta megjelenik, ellenőrizd, melyik szolgáltatáshoz csatlakoztál. Az emberek egy délutánt pazarolnak a rossz hookra, mert a kliens nevét olvassák.
A PPP útvonalon a fájlnak root tulajdonában kell lennie és futtathatónak kell lennie, mert a pppd mindkettőt ellenőrzi, mielőtt bármit futtat. A install egy lépésben állítja be a tulajdonost és a módot.
sudo install -o root -g wheel -m 0755 /dev/null /etc/ppp/ip-up
sudo ls -l /etc/ppp/ip-up
A Finderrel vagy grafikus szerkesztővel létrehozott fájl gyakran a saját fiókod tulajdonába kerül, vagy nincs futtatási bitje, és aztán ugyanolyan csendben hibázik, mint a hiányzó hook. Tedd most mellé a ip-down-t. A root és wheel a tulajdonos oszlopban, valamint a rwxr-xr-x a mód oszlopban az, amit szeretnél.
Engedd, hogy a launchd indítsa a szkriptet, amikor megjelenik egy alagút
Azoknál a klienseknél, amelyek soha nem érintik a PPP-t, a kiváltónak máshonnan kell jönnie, és a rendszerkonfigurációs tár a tisztességes forrás: a macOS minden alagút-átmenetnél újraírja. Az ezt a könyvtárat figyelő launchd feladat akkor hívódik meg, amikor egy alagút megjelenik vagy eltűnik.
<?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>
Telepítsd launch daemonként, ne felhasználónkénti ágensként, mert az útvonal-javítás a géphez tartozik. A bootstrap a jelenlegi kiadásokon a régebbi load -w formát váltja le. A RunAtLoad megfigyelhetővé teszi az első futást, a ThrottleInterval pedig megakadályozza, hogy a Wi-Fi-csatlakozások változásainak özöne újra meg újra elindítsa a szkriptet.
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
A csapda az, hogy a figyelt könyvtár olyan eseményekre is változik, amelyeknek semmi közük a VPN-edhez: Wi-Fi-csatlakozás, DHCP-megújítás, bedugott kábel. Az alábbi őrszem zajos kiváltóból használható hookot csinál, és egy naplósor megmagyaráz egy furcsa órában keletkezett útvonalat.
A tulajdonjog a szkript mellett a plist-re is kiterjed. Az a daemon, amely olyan könyvtárban futtat fájlt, ahová a saját fiókod írhat, rootot ad annak a fióknak.
Védd meg a szkriptet, hogy a második futás ne változtasson semmit
A szkript először eldönti, létezik-e az alagút, és ha nem, csendben kilép. Mindennek utána biztonságosan ismételhetőnek kell lennie, mert a kiváltó sokkal gyakrabban fut, mint egyetlen kapcsolat. Oldd fel az interfészt futásidőben, ahelyett hogy beégetnél egy indexet, amely a következő csatlakozáskor megváltozik.
#!/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"
A route add nem nulla státusszal lép ki, ha az útvonal már létezik, így az a szkript, amely minden nem nulla státuszt hibának tekint, minden alkalommal törött hookot jelent, amikor helyesen cselekszik. A fenti netstat teszt ezt az esetet kifejezett no-op-pá teszi.
Az interfész jelenléte gyengébb bizonyíték, mint látszik, mert más VPN-kliensek és néhány konténerkörnyezet is létrehoz utun eszközöket. Kérdezd meg magát a szolgáltatást a scutil --nc status "Office VPN"-mal, és követeld meg a csatlakozott állapotot, mielőtt hozzányúlsz az útvonalválasztáshoz. Tartsd a választ naplósorban, mert egy hét múlva ez a bejegyzés lesz az egyetlen magyarázatod.
Hozd vissza az átjárót a DNS elrontása nélkül
Amikor az alagút átveszi az alapértelmezett útvonalat, a szokásos böngészés az irodán keresztül megy ki, és a helyi internetútvonal működése leáll. Először kapd el a fizikai interfész routerét, aztán irányítsd vissza rá az alapértelmezettet. A DHCP jobb, mint egy olyan táblázat elemzése, amely már tartalmazza az alagút saját alapértelmezettjét.
PHYS=en0
GW=$(ipconfig getoption "$PHYS" router)
[ -n "$GW" ] && sudo route -n change default "$GW"
A feloldók külön réteg külön eszközzel, és az útvonal javítása nem javítja őket. Nézd meg a scutil --dns-mal, mi van érvényben, aztán javítsd azt, ami létrehozza: a szolgáltatások sorrendjét és a fizikai szolgáltatás DNS-bejegyzéseit. A gyorsítótár ürítése egy hálózatváltás után elakadt keresést diagnosztizál; nem ütemezni való dolog.
Egy Wi-Fi-váltást túlélő, de DNS-ben megakadó alagút harmadik hiba: a sudo killall -HUP mDNSResponder ráveszi a feloldót a konfigurációja újraolvasására. Használd egyszer, kézzel.
Bizonyítsd, hogy a feladat magától fut
Kényszeríts ki egy futást a kickstart -k-mal, mielőtt megbízol a figyelő útvonalban, aztán olvasd ki a feladat által rögzített kilépési státuszt. A tiszta kilépés azt bizonyítja, hogy a szkript működik; nem bizonyítja, hogy a kiváltó működik. Utána bontsd a kapcsolatot és csatlakozz újra a betöltött feladattal, és figyeld, jön-e olyan futás, amelyet nem kértél.
sudo launchctl kickstart -k system/net.example.tunnel-watch
sudo launchctl print system/net.example.tunnel-watch | grep -E 'last exit code|state ='
Ellenőrizd a scutil --nc status-et minden kísérlet előtt és után. Az az alagút leállása alatt lefutott szkript semmit nem bizonyít a kapcsolódási útvonalról.
A bontási ág ugyanazt a bánásmódot érdemli, mint a kapcsolódási ág: távolítsd el kézzel az útvonalat, hagyd futni a feladatot, és igazold, hogy visszajön. Az a hook, amely hozzáad egy útvonalat és soha nem távolítja el, olyan gépet hagy maga után, amely egy hét múlva rosszul viselkedik, és semmi nem köti össze a két eseményt. Ha mindkét viselkedés tart, a sudo launchctl bootout system/net.example.tunnel-watch tisztán visszavonja a feladatot. Egy betöltve hagyott figyelő daemon az, ahogyan egy egyszeri javítás hónapokkal később megmagyarázhatatlan útvonallá válik.