Podłączanie RADIUS do OpenVPN: wtyczka czy hak skryptowy?
Stara wtyczka RADIUS jest związana z kompilacją serwera, dla której powstała. Zastępuje ją hak auth-user-pass-verify, ale przenosi zaufanie do twojego skryptu.
Wtyczka jest wciąż polecana w wątkach starszych niż obecne kompilacje, a na serwerze skompilowanym wczoraj zawodzi przy ładowaniu. To nie jest błąd konfiguracji, który naprawisz ścieżką. Wtyczka i hak skryptowy rozwiązują ten sam problem na różnych warstwach, a przejście z jednego na drugi zmienia to, co trzeba zainstalować, co działa z uprawnieniami serwera i co faktycznie mówi nieudane logowanie.
Mit: wtyczka to wspierana droga
Wtyczka to obiekt współdzielony ładowany do procesu OpenVPN, więc musi pasować do interfejsu, który ten proces udostępnia. Kompilacje się zmieniają, pakowanie się zmienia, a biblioteka skompilowana dla starszego interfejsu po prostu odmawia załadowania. Nic w konfiguracji serwera nie wypełni tej luki, dlatego rada „po prostu zainstaluj radiusplugin” kończy się serwerem, który nie startuje.
Hak skryptowy stoi natomiast poza procesem. OpenVPN uruchamia program, przekazuje mu dane logowania i odczytuje werdykt. Właśnie to rozdzielenie pozwala mu przetrwać aktualizacje, a także czyni go twoją odpowiedzialnością w sposób, w jaki wtyczka nigdy nie była.
Żadne z podejść nie jest bezpieczniejsze z samej konstrukcji. Jedno uruchamia obcy kod wewnątrz demona; drugie uruchamia twój kod obok, z danymi logowania w ręku. Właściwe pytanie brzmi, którym z tych dwóch ryzyk naprawdę potrafisz zarządzać.
Co wtyczka wiązała razem
Wtyczka miała własny plik konfiguracji z hostem RADIUS, wspólnym sekretem, liczbą ponowień i limitem czasu, a konfiguracja serwera odwoływała się do niego jedną linią. Obsługa danych logowania pozostawała w procesie serwera, co oznaczało, że hasło nigdy nie przekraczało granicy procesu, którą administrator musiał zabezpieczyć.
Kosztem było sprzężenie. Każda aktualizacja OpenVPN ryzykowała niezgodny interfejs, a każda dystrybucja przebudowująca pakiet ryzykowała bibliotekę, która już nie pasuje. Gdy to nastąpi, awaria jest głośna i natychmiastowa, i to jedyne miłosierdzie tego projektu.
Jeśli taka wtyczka nadal ładuje się na twojej kompilacji, może być mniejszą powierzchnią operacyjną. Potwierdź interfejs, dla którego ją zbudowano, trzymaj ją przypiętą do przetestowanej kompilacji, a każdą aktualizację traktuj jako zmianę wymagającą pełnego testu logowania, nie rutynową aktualizację pakietu.
Czemu hak skryptowy naprawdę ufa
Hak konfiguruje się przez auth-user-pass-verify i mechanizm dostarczania: zmienne środowiskowe lub plik tymczasowy. W formie środowiskowej OpenVPN wymaga script-security 3, udokumentowanego poziomu, który pozwala ujawnić hasło skryptom. Ten poziom to celowe osłabienie domyślnego ustawienia i należy go traktować jako zgodę z dołączonym uzasadnieniem.
Wszystko, czego skrypt dotyka, dziedziczy to zaufanie. Musi należeć do roota, nie być zapisywalny dla grupy ani innych, być wskazany ścieżką bezwzględną i wolny od miejsca, w którym niezaufana wartość trafia do powłoki. Każdą zmienną ujmij w cudzysłów, odrzucaj nieoczekiwane znaki i nigdy nie buduj polecenia z podanej nazwy użytkownika. Skrypt działający jako root przy każdej próbie logowania zasługuje na jeden przegląd właśnie z powodu tych czterech właściwości.
ls -l /usr/local/sbin/radius-auth.sh
stat -c '%U %a' /usr/local/sbin/radius-auth.sh
Forma dostarczania plikiem unika problemu dziedziczenia środowiska i przekazuje dane logowania skryptowi przez plik tymczasowy z ograniczonymi uprawnieniami. Jeśli twój klient to obsługuje, zwykle jest to lepsze ustawienie domyślne, choć dodaje jeszcze jeden obiekt do sprzątnięcia przy awarii.
Kody wyjścia decydują, czy poniesiesz otwartą porażkę
Status wyjścia skryptu jest werdyktem: zero akceptuje, niezero odrzuca. Wzorzec, który sprawia kłopoty, to skrypt powłoki, który akceptuje tylko wtedy, gdy odpowiedź RADIUS zawiera określony token akceptacji, a dla wszystkiego innego zwraca błąd, bo to skleja trzy różne zdarzenia w jedną odpowiedź. Błędne hasło, nieosiągalny serwer i zniekształcona odpowiedź stają się tym samym odrzuceniem.
Rozdziel te przypadki w skrypcie, nawet jeśli hak potrafi zwrócić tylko akceptację lub odrzucenie. Rejestruj wynik backendu osobno, alarmuj o limitach czasu i błędach transportu, a w monitoringu wyraźnie pokazuj, kiedy uwierzytelnianie zawodzi z powodu niedziałającej usługi, a nie z powodu literówek użytkowników.
Dwa nawyki utrzymują resztę w rozsądku. Jeśli RADIUS jest autorytetem, powinien być jedynym miejscem, gdzie sprawdza się hasło, bo tabela cieni tworzy dwie odpowiedzi na to samo pytanie, a druga jest powierzchnią ataku, której nikt nie obserwuje. I pamiętaj, że hak jest wywoływany ponownie przy każdej próbie, więc wolny skrypt z niecierpliwym klientem staje się wzmacniaczem zgadywania haseł, chyba że dodasz opóźnienie lub politykę po stronie RADIUS.
Czego się wyrzekasz, gdy znika certyfikat
Wiele wdrożeń w tej formie całkowicie wyłącza sprawdzanie certyfikatu klienta, zostawiając nazwę użytkownika i hasło jako całe roszczenie klienta. To, co znika wraz z tym ustawieniem, to tożsamość oparta na certyfikacie. Kanał pozostaje szyfrowany, ale jedyną rzeczą, która nazywa klienta, jest werdykt RADIUS. Wszystko poniżej, co wcześniej opierało się na podmiocie certyfikatu, musi teraz opierać się na nazwie użytkownika.
Utrzymaj ochronę kanału kontrolnego, aby nieuwierzytelniony partner nie mógł sondować ani zalewać uścisku dłoni, i używaj username-as-common-name, gdy konfiguracja dla użytkownika zależy od nazwy wspólnej. Zarządzane bramy często rozwiązują to inaczej, kończąc uwierzytelnianie certyfikatem na bramie, która mówi EAP-TLS z RADIUS, i wtedy żadna z tych dyrektyw serwera nie ma zastosowania. Kopiuj model dokumentowany przez własną platformę, nie ten z sąsiedniego produktu. Dyrektywy, które mają znaczenie, różnią się na tyle, że ich mieszanie daje konfigurację, która się parsuje, a potem nie uwierzytelnia nikogo.