Beim Booten kann eine Socket-Unit, die eine feste VPN-Adresse bindet, scheitern, bevor der Tunnel sie zugewiesen hat, und der Dienst dahinter startet nie. Zwei Schalter sehen wie Lösungen aus und lösen unterschiedliche Hälften dieses Problems. FreeBind lässt systemd den Listener anlegen, während die Adresse noch fehlt. After= ordnet nur Aufträge, ändert also, wann Dinge starten, ohne die Adresse früher ankommen zu lassen.

Zwei verschiedene Probleme, zwei verschiedene Schalter

Das erste Problem ist ein Bindungsfehler: der Kernel verweigert das Lauschen auf einer Adresse, die der Host nicht besitzt, also scheitert die Socket-Unit sofort und der Dienst wird nie aktiviert. Das zweite Problem ist ein Bereitschaftsfehler: die Adresse existiert schließlich, aber etwas versucht sie zu nutzen, bevor der Tunnel Verkehr trägt. FreeBind adressiert das erste und tut nichts für das zweite. Ordnungsdirektiven adressieren keines von beiden direkt, denn sie entscheiden nur, was in welcher Reihenfolge startet. Den Fehler zu benennen, den Sie tatsächlich haben, ist die ganze Entscheidung.

Prüfen Sie im Journal, welchen der beiden Sie haben, nicht in der Dienstbeschreibung. Ein Bindungsfehler nennt eine Adresse und meldet, dass sie nicht zugewiesen werden kann. Ein Bereitschaftsfehler zeigt sich meist später, als Zeitüberschreitung oder abgelehnte Verbindung von der Gegenseite gesehen, während im Log eine völlig gesunde Socket-Unit steht.

FreeBind: der Listener existiert vor der Adresse

FreeBind weist den Kernel an, eine Bindung an eine nicht-lokale Adresse zu erlauben, sodass systemd den lauschenden Socket beim Booten anlegen und ihn der Anwendung übergeben kann, wann immer die Anwendung startet. Das ist der Sinn der Socket-Aktivierung und der Grund, warum der Socket den Dienst dahinter überleben kann.

[Socket]
ListenStream=
ListenStream=10.8.0.1:8443
FreeBind=yes

Die leere Zuweisung löscht die von der Hersteller-Unit geerbten Lauscheinträge, bevor der neue hinzugefügt wird, was verhindert, dass ein übrig gebliebener Wildcard-Listener auf jeder Schnittstelle antwortet. Ersetzen Sie Adresse und Port durch Ihre eigenen und prüfen Sie die effektive Unit statt nur der Drop-in-Datei. Verwenden Sie ein Drop-in unter dem Unit-Namen, statt eine Paketdatei an Ort und Stelle zu bearbeiten, denn das nächste Paketupdate überschreibt die Änderung und hinterlässt keine Spur der Absicht. Wenden Sie es dann über das Neulade- und Neustartverfahren an, das die Socket-Unit erwartet.

Die systemd-Socket-Referenz dokumentiert das IPv4- und IPv6-Verhalten hinter dieser Option, und das wichtige Detail ist, dass es für die Bindung und nicht für das Routing gilt. Nichts darin weist eine Adresse zu oder startet ein VPN. FreeBind ist eine dem Listener erteilte Erlaubnis, kein Ersatz für die Schnittstelle.

After= und Wants=: Reihenfolge ist keine Bereitschaft

Reihenfolge und Anforderung sind getrennte Achsen, und ihre Verwechslung erzeugt Units, die in der richtigen Reihenfolge starten und trotzdem scheitern. After=vpn-client.service bedeutet nur, dass diese Unit, wenn beide Aufträge gestartet werden, auf den Start des anderen wartet. Es zieht das VPN nicht herein und wartet nicht darauf, dass das VPN das Verbinden abschließt.

Anforderungsdirektiven wie Wants= und Requires= übernehmen die Aktivierung und unterscheiden sich darin, was beim Scheitern der Abhängigkeit passiert: eine fährt fort, die andere stoppt. Keine von beiden weiß, was ein verbundener Tunnel bedeutet. Ein VPN-Prozess kann aktiv sein, ohne dass eine Adresse zugewiesen ist, oder mit zugewiesener Adresse und ohne Route zum Gegenüber, und beide Zustände erfüllen die Abhängigkeit. Wenn die Anwendung die Adresse benötigt, modellieren Sie diese Bedingung ausdrücklich, statt den Prozessstart als Beweis der Bereitschaft zu behandeln.

Prüfen Sie mit systemctl cat und systemctl show -p After -p Wants -p Requires, was die Unit tatsächlich deklariert. Drop-ins aus drei verschiedenen Verzeichnissen können Direktiven hinzufügen, die Sie nie geschrieben haben, und systemd liest nur die effektive Unit.

Was network-online.target nicht tut

Eine nach network-online.target geordnete Unit wartet darauf, dass der Netzwerkmanager das Netz für nutzbar erklärt, was ein Synchronisationspunkt beim Booten und keine dauerhafte Bedingung ist. Sie sagt nichts darüber aus, ob ein bestimmter Tunnel oben ist, und sie löst nicht erneut aus, wenn ein VPN am Nachmittag erneut verbindet. Sie als Wiederverbindungsmonitor zu behandeln ist die häufigste Fehldeutung dieses Ziels.

Das systemd-Projekt dokumentiert diese Unterscheidung direkt, und die praktische Folge ist, dass alles, was eine Tunneladresse braucht, die Abhängigkeit selbst besitzen muss. Eine Unit, die auf network-online wartet und dann eine Tunneladresse bindet, ist nur dann korrekt, wenn der Tunnel zufällig zuerst hochkommt, und das ist ein Zufall und kein Entwurf.

Testen Sie den Lebenszyklus, den Sie tatsächlich gewählt haben

Testen Sie einen sauberen Boot, eine Anfrage, nachdem die Adresse erscheint, und das Verhalten, nachdem das VPN ausfällt und zurückkehrt. Diese drei Fälle trennen einen funktionierenden Listener von einem funktionierenden Dienst.

systemd-analyze verify myapp.socket
systemctl cat myapp.socket
ss -ltn "sport = :8443"

Der erste Befehl fängt Fehler in der Unit-Datei vor einem Neustart, der zweite zeigt die zusammengeführte Unit, und der dritte belegt, ob der Listener existiert und auf welcher Adresse. Ein Listener auf einer Wildcard-Adresse, wo Sie eine Tunneladresse erwartet hatten, ist genau der Rest, den der leere ListenStream entfernen sollte. Wiederholen Sie den dritten Befehl nach einer VPN-Wiederverbindung, um zu sehen, ob die Adresse gewandert ist.

Wählen Sie den Lebenszyklus bewusst: entweder einen frei gebundenen Listener, der auf die Rückkehr einer stabilen Adresse wartet, oder einen Dienst, der mit dem Tunnel stoppt und bei der Wiederherstellung erneut startet. Das sind unterschiedliche Entwürfe, und sie scheitern auf unterschiedliche Weise. Binden Sie dann die Zugriffsrichtlinie an die Quellen und Pfade, die Sie beabsichtigt haben, denn das Binden einer Zieladresse verlangt nicht, dass angenommene Pakete über eine vertrauenswürdige Schnittstelle kamen.

Ähnliche Artikel