De job draait bij het inloggen, het log toont de client die start, maar de tunnel komt nooit op. Of hij komt op en verdwijnt een paar seconden later. In beide gevallen was de property list waarschijnlijk in orde. launchd deed twee beloften toen hij de job aannam: hij bewaakt een proces, en dat proces blijft draaien. De VPN heeft beide nodig, en een correct XML-bestand levert geen van beide.

Een geldige property list is nog geen werkende dienst

plutil -lint controleert de structuur. Het kan je niet vertellen of het binary bestaat, of de argumenten door deze clientversie worden ondersteund, of de job start in een context waarin de inloggegevens beschikbaar zijn. Dat zijn semantische vragen, en ze verklaren de meeste storingen die op launchd-problemen lijken.

plutil -lint /Library/LaunchDaemons/com.example.vpn.plist
launchctl print system/com.example.vpn

Lees de uitvoer van de tweede opdracht in plaats van aan te nemen dat de job is geladen. Die meldt de laatste exitstatus en of de dienst draait, wat onderscheid maakt tussen "nooit gestart" en "gestart en gestorven" voordat je het profiel aanraakt.

Agents erven een gebruikerssessie, daemons niet

Apples launchd-documentatie scheidt agents per gebruiker van systeemdaemons. Een agent draait in de context van de ingelogde gebruiker, met diens sleutelhanger en omgeving. Een daemon draait zonder die sessie, en een job naar een systeemmap verplaatsen herschept de interactieve inloggegevens van de gebruiker niet.

Dat verschil bepaalt het ontwerp. Als de verbinding vereist dat iemand inlogt of een MFA-prompt goedkeurt, is de ondersteunde opzet een job in de gebruikerssessie die na het inloggen draait. Als het moet werken zonder dat iemand is ingelogd, heeft de client een goedgekeurde onbeheerde identiteit nodig met een eigen vernieuwings- en intrekkingsproces. De verkeerde rij kiezen levert een job op die schoon start en bij de eerste authenticatiestap faalt.

Verberg het verschil niet met een wachtwoord in de argumentarray of door certificaatcontroles uit te zetten. Beide maken van een authenticatievereiste een permanent geheim in een leesbaar bestand, en het tweede betekent dat de tunnel alles authenticeert wat antwoordt.

Bewaking werkt alleen als het proces voorop blijft

Een client die zichzelf daemoniseert, geeft de besturing meteen terug aan launchd, en de bewaker kijkt dan naar een proces dat al is afgelopen. De tunnel kan omhoog zijn, maar launchd denkt dat de job is mislukt, en het herstartbeleid doet iets wat je niet bedoelde.

Gebruik de gedocumenteerde voorgrond- of servicemodus van de client. Heeft het product een eigen ondersteunde opstartfunctie, dan weet die al hoe hij op de voorgrond blijft en hoe hij overdraagt aan de netwerkstack; een eigen job is een apart ontwerp, geen verbetering ervan.

Geef de job een uniek label, het bedoelde uitvoerbare bestand en een bewuste argumentarray. Een array is geen shell-opdrachtregel, dus pijpen en omleidingen werken daar niet, en quoting gedraagt zich anders. Een opdracht die in de terminal van een beheerder slaagt, is hooguit een voorcontrole.

Inloggegevens moeten zonder prompt werken

Onbeheerd gebruik verplaatst het probleem met de inloggegevens in plaats van het weg te nemen. Iemand moet de identiteit bezitten, beslissen hoe lang die leeft en documenteren hoe die wordt vervangen. Een certificaat zonder vervaldatummonitoring wordt een storing met een datum in de agenda.

Houd geheimen buiten de argumenten en buiten de standaarduitvoer van de job. Als de client het lezen van een inloggegeven uit een beveiligde opslag ondersteunt, gebruik dan dat pad, en controleer of de uitvoeringscontext van de job die opslag kan bereiken. Een daemon die als root draait, kan meestal geen item uit de inlogsleutelhanger lezen, en dat is het soort detail dat alleen in de systeemcontext opduikt.

Definieer wat gereed betekent en test daar

Een geslaagde start bewijst dat het proces begon. Het bewijst niet dat het netwerk op is, dat de gateway de identiteit accepteerde, of dat de privéapplicatie bereikbaar is. Als iets anders van de tunnel afhangt, heeft het een gereedheidssignaal nodig dat de verbinding weerspiegelt, niet het startmoment van de job.

Nieuwe pogingen moeten begrensd zijn en moeten een ontbrekend netwerk onderscheiden van een geweigerd inloggegeven. Bij elke fout opnieuw starten kan een verlopen certificaat niet repareren en levert een log vol identieke pogingen op dat de echte verbergt.

Accepteer de job in de context waarin hij werkelijk draait: geen netwerk bij het opstarten, een normale login, een ontwaken uit slaap en een gecontroleerde stop. Leg daarna het joblabel, de clientversie en de profielrevisie samen vast, zodat de volgende persoon een toerekenbare dienst erft in plaats van een bestand dat ooit werkte.

Gerelateerde artikelen