Zwracanie adresu ze skryptu client-connect wygląda tak, jakby miało ustawić adres IP klienta. Tak się nie dzieje: jedynym kanałem haka do serwera jest plik tymczasowy, którego ścieżka przychodzi jako ostatni argument skryptu, a adres trzeba tam zapisać w składni ifconfig-push. Skrypt, który wypisuje adres albo kończy się zerem, nic nie zapisując, tworzy połączonego klienta z adresem z puli, a dziennik serwera wygląda całkowicie zdrowo.

Zamieszanie jest zrozumiałe, ponieważ kilka innych haków naprawdę odpowiada przez kody wyjścia lub zmienne środowiskowe. Ten ma własny kontrakt, a kontrakt zaczyna się od nazwy pliku.

Hak zapisuje plik, a nie wartość zwracaną

Deklaracja to dwie linie: script-security 2, aby zezwolić na wywołanie, następnie client-connect /etc/openvpn/server/assign-address.sh. Gdy klient się uwierzytelni, serwer uruchamia ten skrypt, dodając wygenerowaną ścieżkę pliku jako ostatni argument, który jest $1 tylko wtedy, gdy deklaracja nie przekazuje własnych dodatkowych argumentów. Wszystko, co stosuje się do tego klienta, trafia do tego pliku jako zwykłe dyrektywy, jedna na linię, dokładnie tak, jak wyglądałyby w konfiguracji. Otoczka dodająca własne parametry przesuwa pozycję, a klasycznym objawem jest skrypt zapisujący do ścieżki wyglądającej jak --verbose.

Kod wyjścia to druga połowa kontraktu. Zero oznacza przyjmij i odczytaj plik; cokolwiek innego odrzuca połączenie, i tak niezmapowana tożsamość zostaje odrzucona, zamiast po cichu wrócić do puli. Zapisz pełną dyrektywę, zanim zwrócisz sukces, aby na wpół zapisany plik nigdy nie stał się konfiguracją klienta.

Dwie dyrektywy zasługują na uwagę, bo oddziałują na wszystko inne. ifconfig-push ustala adres, a wysłany route mówi klientowi, co jest osiągalne przez tunel; zwróć pierwszą i zapomnij drugiej, a otrzymasz klienta z adresem i bez celu. Kolejność w pliku nie ma znaczenia, ale kompletność ma. Hak, który wysyła trasę dla prefiksu, do którego żaden równorzędny nie może dotrzeć, to ten sam błąd widziany z drugiej strony.

Dane wejściowe przychodzą przez zmienne środowiskowe: common_name, trusted_ip, ifconfig_pool_remote_ip i resztę. Traktuj je wszystkie jako łańcuchy spoza serwera, nigdy jako fragmenty powłoki.

Mapowanie adresów to polityka, nie arytmetyka

Kuszącym skrótem jest przeanalizowanie nazwy certyfikatu i użycie jej cyfr jako ostatniego oktetu. To nie jest przydzielacz i zawodzi w zwykłe sposoby: dwie nazwy z tym samym sufiksem kolidują, nazwa kończąca się na 300 nie jest adresem, a certyfikat zmieniony przez administratora po cichu przenosi urządzenie. Przy każdym wywołaniu sprawdzaj przynależność do podsieci, użyteczny zakres hostów, adresy zarezerwowane i unikalność, a mapowanie trzymaj w tabeli, którą człowiek może przeczytać.

Kto kontroluje nazwę, kontroluje adres, więc zdecyduj, co common_name naprawdę reprezentuje w tym wdrożeniu. Przy włączonym username-as-common-name tożsamością jest login, a nie podmiot certyfikatu. Nigdy nie przekazuj tej wartości do oceny powłoki i nigdy nie pozwól klientowi wpływać na ścieżkę pliku.

Przydzielacz oparty na rejestrze musi przetrwać współbieżność. Rezerwuj adres atomowo, obsługuj nieudany zapis bez dopuszczania na wpół skonfigurowanego klienta i oznaczaj każde przydzielenie połączeniem, które je posiada, aby późne rozłączenie starszej sesji nie mogło zwolnić adresu, który nowsza już trzyma. Kilka instancji serwera współdzielących jedną pulę czyni ten wymóg ostrzejszym, a nie opcjonalnym.

Topologia decyduje, co znaczy ifconfig-push

Przy topology subnet na 10.77.0.0/24 ifconfig-push 10.77.0.20 255.255.255.0 to adres plus jego maska sieci. W topology net30 drugi argument wcale nie jest maską, lecz adresem drugiej strony, więc skopiowanie formy podsieci na serwer net30 daje klienta, który się łączy i nie potrafi przepuścić ruchu. Zmieniaj topologię świadomie, nigdy po to, by przykład wyglądał spójnie. Serwer, który już działa w net30, ma żywych klientów na starym adresowaniu, więc przełączenie to migracja z oknem serwisowym, a nie edycja jednej linii.

Adresy statyczne muszą leżeć poza pulą dynamiczną i poza każdym innym statycznym przypisaniem, w tym tymi z zwykłych plików client-config-dir. Jeśli dwa mechanizmy mogą wytworzyć ten sam adres dla różnych klientów, jeden z nich w końcu to zrobi.

Przetestuj cztery przypadki, zanim mu zaufasz

Uruchom te same testy na tożsamości zmapowanej, niezmapowanej, ponownym połączeniu i symulowanej awarii rejestru. openvpn --config client.ovpn --verb 4 pokazuje przydzielony adres w odpowiedzi push, a na serwerze grep -A2 PUSH_REPLY /var/log/openvpn/openvpn.log potwierdza, co faktycznie wysłano. Dla niezmapowanej tożsamości oczekiwanym wynikiem jest odrzucone połączenie, a nie adres z puli.

Następnie sprawdź katalog, do którego demon zapisuje te pliki tymczasowe. Skrypt działa w obniżonym kontekście usługi, więc ścieżka zapisywalna dla roota, ale nie dla demona, zamienia każde połączenie w odrzucenie z błędem uprawnień zakopanym kilka linii niżej w dzienniku.

Przydzielenie to nie autoryzacja: przypięty adres nadal nie daje dostępu do każdego celu za serwerem. Trzymaj politykę routingu i zapory w jej własnej warstwie i weryfikuj ją względem adresu, który właśnie ustaliłeś.

Powiązane artykuły