OpenVPN push-peer-info: oznaczanie klientów bez przyznawania dostępu
Pole UV_ podróżuje przez uwierzytelniony tunel, ale wartość nadal jest twierdzeniem klienta. Skonfiguruj je, sprawdź, co dotarło, i pozostaw autoryzację po stronie serwera.
Tagi wdrożeniowe to zwykły powód, dla którego ludzie sięgają po tę funkcję: każde połączenie powinno nieść coś w rodzaju lokalizacji lub roli, a serwer powinien to czytać bez wymyślania drugiego formatu poświadczeń. OpenVPN społecznościowy ma już ten mechanizm i jest on niewielki. Bolesna część to oczekiwania. Ustawienie zwykłej zmiennej w profilu klienta nic nie robi na serwerze, a wartość, która jednak dotrze, dowodzi tylko, że klient ją wysłał.
To jest instrukcja dla działającej ścieżki, kroku weryfikacji, który pokazuje, co naprawdę dotarło, oraz wycofania, które nie zostawia na wpół skonfigurowanego hooka. Nic tutaj nie wymaga nowego certyfikatu, nowej wtyczki ani rozszerzenia protokołu.
Ustaw zmienną i włącz ścieżkę
Dwie linie wykonują pracę w profilu klienta i obie są potrzebne. Bez pierwszej nie ma czego wysłać; bez drugiej klient w ogóle nie oferuje informacji o peerze. Kolejność nie ma znaczenia, i warto to wiedzieć, ponieważ obie linie często trafiają w różne części generowanego profilu. Ważne jest, aby obie przetrwały każde przepisanie profilu, zanim klient go odczyta.
setenv UV_DEPLOY field-support
push-peer-info
Prefiks UV_ nie jest ozdobą. Zwykła zmienna DEPLOY pozostaje lokalna w procesie klienta i nigdy nie jest przekazywana, natomiast forma z prefiksem to przestrzeń nazw, którą protokół rezerwuje dla pól zdefiniowanych przez użytkownika. Zachowaj resztę zatwierdzonego profilu bez zmian i przed wdrożeniem potwierdź, że budowana wersja klienta obsługuje obie dyrektywy.
Jedna praktyczna kontrola należy tutaj, a nie na końcu: upewnij się, że dyrektywa dociera do pliku binarnego klienta i nie jest połykana przez nakładkę. Klient graficzny, który sam generuje wiersz poleceń, albo interfejs zarządzania, który ponownie wczytuje zapisany profil, mogą odrzucić linie, których nie rozpoznają. Jeśli serwer nic nie widzi, to pierwsze miejsce do sprawdzenia.
Odczytaj pole z hooka serwera
Po stronie serwera odebrane informacje o peerze są walidowane i wstawiane do środowiska przepływu połączenia, i właśnie to czyni je czytelnymi z hooka bez żadnej pracy nad protokołem z twojej strony. Serwer nie musi analizować kanału sterującego ani niczego dla ciebie przechowywać; wartość jest po prostu obecna, gdy połączenie jest ustanawiane. Minimalny skrypt client-connect, który zapisuje tag obok uwierzytelnionej nazwy, wygląda tak.
#!/bin/sh
# /etc/openvpn/server/hooks/label.sh
printf '%s %s\n' "$common_name" "${UV_DEPLOY:-unset}" \
>> /var/log/openvpn/deploy-labels.log
Odczytuj zmienną przez środowisko, a nie przez analizę logu, i zawsze dawaj jej wartość domyślną. ${UV_DEPLOY:-unset} utrzymuje skrypt w działaniu dla klientów, którzy nigdy nie wysyłają pola, co jest normalnym stanem podczas stopniowego wdrażania. Nie wylewaj całego środowiska do logu, aby znaleźć nazwę; zawiera ono znacznie więcej niż tag, w tym wartości, których nie zamierzałeś zachować.
Uruchom skrypt ręcznie, a zgłosi unset dla wszystkiego, bo ręczna powłoka nie przenosi środowiska połączenia. To nie jest błąd skryptu ani dowód, że pola brakuje. Przetestuj go przez rzeczywiste połączenie, jedyny kontekst, w którym zmienna istnieje.
Sprawdź, co naprawdę dotarło
Podłącz jednego klienta z tagiem i jednego bez niego, a następnie odczytaj plik. Para jest testem: jedna linia powinna nieść wartość, a druga wartość domyślną, i obie powinny nazywać tę samą uwierzytelnioną tożsamość, której oczekujesz.
tail -n 5 /var/log/openvpn/deploy-labels.log
# field-support deployed-client-07
# unset legacy-laptop-02
Te linie komentarza to kształt wyjścia, nie transkrypcja z twojego serwera; czytaj własny plik. Jeśli drugi klient również pokazuje wartość, zmienna jest ustawiona gdzie indziej w środowisku i czytasz nieaktualne ustawienie, a nie pole peera.
Sprawdź także log serwera dla tego połączenia. Informacje o peerze mogą się tam pojawić, co jest wygodne przy debugowaniu i powodem, by trzymać wartości nudne: bez imion ludzi, bez numerów zgłoszeń, nic, czego nie chciałbyś pokazać czytelnikowi logu.
Traktuj tag jako twierdzenie, a nie tożsamość
Każdy, kto może edytować profil klienta, może zmienić tag, a to, że tunel jest uwierzytelniony, nie czyni tagu autorytatywnym. Transport chroni wartość w drodze; nie poświadcza twierdzenia. Autoryzacja nadal należy do uwierzytelnionej tożsamości i do rekordu rejestracji, który posiada serwer, a tag jest porównywany z tym rekordem, gdy ma to znaczenie.
Ta różnica decyduje, gdzie tag może być używany. Dobre zastosowania to kierowanie sesji do właściwego pliku logu, wybór grupy wyświetlania w panelu albo oznaczanie sesji wsparcia, aby człowiek mógł ją później znaleźć. Złe zastosowania to wpuszczanie urządzenia do podsieci, wybór polityki zapory albo decydowanie, których danych klienta sesja może czytać.
Waliduj wartość, zanim dotrze do ścieżki, zapytania lub polecenia powłoki. Lista dozwolonych oczekiwanych ciągów wystarcza dla tagu wdrożeniowego i nic nie kosztuje. Nigdy nie wstawiaj ciągu dostarczonego przez peera do wiersza poleceń powłoki i ogranicz każdą zapisaną obserwację do sesji, a nie do adresu tunelu, którego następny klient użyje ponownie.
case "${UV_DEPLOY:-}" in
field-support|field-qa|lab) : ;;
*) UV_DEPLOY=unknown ;;
esac
Wycofaj to czysto
Usunięcie funkcji to dwa usunięcia i jedna weryfikacja. Usuń linie setenv i push-peer-info z profilu klienta, a następnie usuń lub wyłącz hook i jego cel logu na serwerze.
grep -rn 'UV_DEPLOY\|push-peer-info' /etc/openvpn/
tail -n 3 /var/log/openvpn/deploy-labels.log
Po tym podłącz ponownie jednego klienta i potwierdź, że linia logu przestaje się pojawiać. Hook, który nadal się uruchamia po zmianie profilu, to zwykle drugi profil wciąż wdrożony na urządzeniu testowym, a znalezienie go teraz jest tańsze niż podczas audytu.
Na końcu pozostaje mały, ograniczony fragment metadanych sesji o udokumentowanym pochodzeniu: klient go twierdzi, serwer go zapisuje, i nic w dostępie od niego nie zależy. To jest użyteczna wersja tej funkcji i nie wymaga nowych poświadczeń, aby do niej dotrzeć.