Podczas rozruchu jednostka gniazda wiążąca stały adres VPN może zawieść, zanim tunel go przydzieli, a usługa za nią nigdy nie startuje. Dwa przełączniki wyglądają jak poprawki i rozwiązują różne połowy tego problemu. FreeBind pozwala systemd utworzyć nasłuchiwacz, gdy adres jeszcze nie istnieje. After= tylko porządkuje zadania, więc zmienia, kiedy rzeczy startują, ale nie sprawia, że adres pojawia się wcześniej.

Dwa różne problemy, dwa różne przełączniki

Pierwszy problem to błąd wiązania: jądro odmawia nasłuchu na adresie, którego host nie posiada, więc jednostka gniazda natychmiast zawodzi, a usługa nigdy nie zostaje aktywowana. Drugi problem to błąd gotowości: adres w końcu istnieje, ale coś próbuje go użyć, zanim tunel przesyła ruch. FreeBind rozwiązuje pierwszy i nic nie robi dla drugiego. Dyrektywy kolejności nie rozwiązują żadnego z nich bezpośrednio, ponieważ decydują jedynie, co startuje i w jakiej kolejności. Nazwanie błędu, który naprawdę masz, to cała decyzja.

Sprawdź, który z dwóch masz, w dzienniku, a nie w opisie usługi. Błąd wiązania wskazuje adres i zgłasza, że nie można go przydzielić. Błąd gotowości pojawia się zwykle później, jako przekroczenie limitu czasu lub odrzucone połączenie widziane z drugiej strony, a w logach pozostaje całkowicie zdrowa jednostka gniazda.

FreeBind: nasłuchiwacz istnieje przed adresem

FreeBind każe jądru zezwolić na wiązanie z adresem nie-lokalnym, dzięki czemu systemd może utworzyć nasłuchujące gniazdo przy rozruchu i przekazać je aplikacji, gdy tylko aplikacja startuje. Na tym polega aktywacja gniazdem i to jest powód, dla którego gniazdo może przeżyć usługę za nim.

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

Puste przypisanie usuwa wpisy nasłuchu odziedziczone po jednostce dostawcy, zanim dodany zostanie nowy, co zapobiega odpowiadaniu przez pozostały nasłuchiwacz wildcard na każdym interfejsie. Zastąp adres i port własnymi i sprawdź jednostkę efektywną, a nie tylko plik drop-in. Użyj drop-in pod nazwą jednostki zamiast edytować plik pakietu na miejscu, ponieważ następna aktualizacja pakietu nadpisze zmianę i nie pozostawi żadnego śladu intencji. Następnie zastosuj go procedurą przeładowania i restartu, której oczekuje jednostka gniazda.

Dokumentacja gniazd systemd opisuje zachowanie IPv4 i IPv6 stojące za tą opcją, a ważny szczegół jest taki, że dotyczy ona wiązania, a nie routingu. Nic w niej nie przydziela adresu ani nie uruchamia VPN. FreeBind to uprawnienie przyznane nasłuchiwaczowi, a nie zamiennik interfejsu.

After= i Wants=: kolejność to nie gotowość

Kolejność i wymaganie to osobne osie, a ich mylenie daje jednostki, które startują w dobrej kolejności i mimo to zawodzą. After=vpn-client.service znaczy tylko tyle, że jeśli oba zadania zostaną uruchomione, ta jednostka czeka na uruchomienie drugiej. Nie wciąga VPN i nie czeka, aż VPN zakończy łączenie.

Dyrektywy wymagania, takie jak Wants= i Requires=, obsługują aktywację i różnią się tym, co dzieje się, gdy zależność zawiedzie: jedna kontynuuje, druga się zatrzymuje. Żadna z nich nie wie, co oznacza połączony tunel. Proces VPN może być aktywny bez przydzielonego adresu albo z przydzielonym adresem i bez trasy do peera, i oba stany spełniają zależność. Jeśli aplikacja potrzebuje istnienia adresu, modeluj ten warunek wprost, zamiast traktować start procesu jako dowód gotowości.

Sprawdź, co jednostka naprawdę deklaruje, za pomocą systemctl cat i systemctl show -p After -p Wants -p Requires. Drop-in z trzech różnych katalogów mogą dodać dyrektywy, których nigdy nie napisałeś, a systemd czyta tylko jednostkę efektywną.

Czego network-online.target nie robi

Jednostka uporządkowana po network-online.target czeka, aż menedżer sieci ogłosi sieć jako użyteczną, co jest punktem synchronizacji przy rozruchu, a nie stałym warunkiem. Nie mówi nic o tym, czy konkretny tunel jest podniesiony, i nie uruchomi się ponownie, gdy VPN połączy się ponownie w środku popołudnia. Traktowanie go jako monitora ponownego połączenia to najczęstsze błędne odczytanie tego celu.

Projekt systemd dokumentuje tę różnicę bezpośrednio, a praktyczna konsekwencja jest taka, że wszystko, co potrzebuje adresu tunelu, musi samo posiadać zależność. Jednostka, która czeka na network-online, a następnie wiąże adres tunelu, jest poprawna tylko wtedy, gdy tunel przypadkiem powstanie pierwszy, a to zbieg okoliczności, nie projekt.

Przetestuj cykl życia, który naprawdę wybrałeś

Przetestuj czysty rozruch, żądanie po pojawieniu się adresu i zachowanie po upadku i powrocie VPN. Te trzy przypadki oddzielają działający nasłuchiwacz od działającej usługi.

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

Pierwsze polecenie wyłapuje błędy pliku jednostki przed restartem, drugie pokazuje scaloną jednostkę, a trzecie dowodzi, czy nasłuchiwacz istnieje i na jakim adresie. Nasłuchiwacz na adresie wildcard tam, gdzie oczekiwałeś adresu tunelu, jest dokładnie tą pozostałością, którą pusty ListenStream miał usunąć. Powtórz trzecie polecenie po ponownym połączeniu VPN, aby zobaczyć, czy adres się przesunął.

Wybierz cykl życia świadomie: albo nasłuchiwacz związany swobodnie, który czeka na powrót stabilnego adresu, albo usługa, która zatrzymuje się wraz z tunelem i startuje ponownie przy odzyskaniu. To różne projekty i zawodzą na różne sposoby. Następnie trzymaj politykę dostępu związaną ze źródłami i ścieżkami, które zamierzałeś, ponieważ związanie adresu docelowego nie wymaga, aby akceptowane pakiety przyszły przez zaufany interfejs.

Powiązane artykuły