Czy skrypt haka OpenVPN może użyć tunelu, który właśnie zbudował?
OpenVPN uruchamia haki w ramach własnego startu, więc skrypt, który potrzebuje tunelu, czeka na tunel, który czeka na niego. Odłącz pracę i wybieraj hak według zdarzenia.
Czy skrypt haka dotrze na drugą stronę tunelu, zależy od trzech warunków: do jakiego zdarzenia jest podpięty, czy OpenVPN nadal znajduje się w swojej sekwencji startowej, gdy skrypt działa, oraz czy praca została odłączona od tej sekwencji. Większość skryptów zawodzi na trzecim. Dodanie snu traktuje problem cyklu życia jako problem czasu i działa dokładnie tak często, by wprowadzić w błąd.
Najpierw zdecyduj o zdarzeniu, potem o mechanizmie odkładania pracy, a potem o miejscu, w którym działa odłożona praca. Te trzy decyzje są niezależne, a ich mieszanie to sposób, w jaki dwuliniowy hak staje się całym popołudniem.
Dlaczego hak czeka na tunel, który czeka na niego
OpenVPN wywołuje swoje haki synchronicznie, w tym samym procesie, który przenosi pakiety. up uruchamia się, gdy urządzenie tun lub tap już istnieje, ale zanim zostanie dodana jakakolwiek trasa, a route-up uruchamia się po trasach; żaden z tych momentów nie obiecuje, że druga strona odpowie. Dopóki skrypt któregokolwiek haka jeszcze działa, demon nie przekazuje, więc polecenie, które oczekuje, że ruch przejdzie przez tunel, czeka na tunel, który czeka na polecenie. To cykliczne oczekiwanie jest powodem, dla którego ręczne uruchomienie przechodzi, a hak kończy się przekroczeniem czasu.
Oczywista łatka, czyli kilka sekund snu, czasem działa, bo drugi koniec podniósł się sam, a nie dlatego, że sen coś naprawił. Pomocnik pytający o gotowość to inna odpowiedź: hak wraca, przekazywanie się zaczyna, a pomocnik dostaje to, czego potrzebuje, gdy jest to naprawdę dostępne.
Wybieraj hak według zdarzenia, nie według wygody
Podepnij up do pracy, która potrzebuje tylko urządzenia, route-up do pracy, która potrzebuje tras, a client-connect i client-disconnect zostaw dla zadań na klienta po stronie serwera. Czyszczenie przy rozłączeniu musi znosić dwukrotne uruchomienie, ponieważ ponowne połączenia przez trwały interfejs nie podążają tą samą sekwencją co pełny restart. Na serwerze client-connect uruchamia się, gdy klient się uwierzytelnia, a nie gdy startuje demon, co warto potwierdzić przed przeniesieniem tam logiki. Jeśli praca należy do cyklu życia usługi, a nie do jednego połączenia, jednostka systemd jest lepszym domem niż jakikolwiek hak.
Polecenia haka wykonuje bezpośrednio demon, bez powłoki pomiędzy, więc ifconfig_remote w wierszu up przychodzi jako dosłowny tekst. Opakuj polecenie w jawną powłokę albo trzymaj logikę w skrypcie, który czyta środowisko. ipchange to jedna dyrektywa, która dodaje własne argumenty: przekazuje poleceniu adres i port, więc skrypt napisany dla żadnego widzi dwa nieoczekiwane.
Trzy sposoby odłączenia pracy
Pierwsza opcja to wysłanie pomocnika w tło z wnętrza haka: uruchom go przez setsid lub systemd-run --scope, zamknij odziedziczone deskryptory i wyjdź od razu z zerem. Druga to pozwolić hakowi zapisać mały plik stanu i pozwolić timerowi systemd lub jednostce ścieżki działać na nim, co utrzymuje hak trywialnym i umieszcza politykę ponowień tam, gdzie są logi. Trzecia to całkowite porzucenie haka i przeniesienie pracy do jednostki uporządkowanej po usłudze VPN, co jest właściwą odpowiedzią, gdy praca wcale nie jest na połączenie. Wszystkie trzy dzielą jedną regułę: hak musi wrócić, zanim będzie potrzebował tunelu.
Cokolwiek wybierzesz, uczyń pomocnika idempotentnym i obserwowalnym. Dwa nakładające się wywołania nie powinny wykonać tej samej nieodwracalnej akcji dwa razy, a pomocnik, który zawodzi, musi zostawić coś, co człowiek może przeczytać.
Oddziel awarie sandboxa od awarii cyklu życia
Gdy skrypt działa z wiersza root i zawodzi jako usługa, przyczyną jest zwykle sandbox, a nie sieć. Restrykcyjny ProtectHome, tylko do odczytu ProtectSystem lub katalog roboczy, który nie istnieje mogą sprawić, że skrypt lub jego dane będą nieosiągalne, a na hoście SELinux plik potrzebuje też kontekstu, który pozwala na wykonanie. Przeczytaj jednostkę przez systemctl cat openvpn-server@server i dziennik przez journalctl -u openvpn-server@server -n 80, a potem szukaj błędu uprawnień lub kontekstu, a nie przekroczenia czasu połączenia. Wyłączanie sandboxa powinno być ostatnim krokiem, nie pierwszym.
Awarie cyklu życia wyglądają inaczej: hak startuje, pomocnik działa, a gniazda po prostu jeszcze nie ma. Zapisz wiersz z znacznikiem czasu z samego haka, rozłącz się i połącz ponownie, i przeczytaj zdarzenia po kolei. Gdy pomocnik naprawdę potrzebuje tunelu, pozwól mu pytać o gotowość zamiast spać przez stały okres.
Trzy pola czynią następny raport użytecznym: który hak działał, z jakiego konta korzystał i gdzie się zatrzymał. Bez nich każde późniejsze dochodzenie zaczyna się od nowa.