Dwa skoki VPN pod rząd: kto naprawdę widzi twój ruch?
Skoki szeregowe odszyfrowują i ponownie szyfrują na pierwszej bramie; skoki zagnieżdżone usuwają tylko zewnętrzną warstwę. Przejdź oba projekty i zobacz, który operator co czyta.
Każdy profil klienta wskazuje jeden serwer, więc z miejsca użytkownika jest jeden tunel i jedno miejsce, w którym ochrona się kończy. To, co dzieje się za tą pierwszą bramą, jest decyzją projektową, której klient nigdy nie widzi, a oba typowe projekty zachowują się podczas kontroli bardzo różnie. W łańcuchu szeregowym pierwsza brama odszyfrowuje i ponownie szyfruje. W łańcuchu zagnieżdżonym usuwa zewnętrzną warstwę i przekazuje wewnętrzny tunel, którego nie potrafi otworzyć. Liczba skoków jest w obu identyczna, dlatego różnicę trzeba narysować, a nie policzyć.
Zacznij od klienta i nazwij oba końce
Zacznij tam, gdzie zaczyna użytkownik, w profilu połączenia. Zawiera on jeden adres zdalny, jedną metodę uwierzytelniania i, gdy projekt to obsługuje, listę tras. Oznacz ten zewnętrzny tunel od klienta do bramy A i nadaj mu przykładowe adresy: adres tunelu klienta 10.77.0.2, adres A 10.77.0.1 oraz publiczny punkt końcowy A 198.51.100.10, wzięte z zakresu dokumentacyjnego TEST-NET-2, aby nic w przykładzie nie mogło kolidować z prawdziwym hostem.
Nic w tym profilu nie wspomina bramy B i nie jest to wadą. Drugi skok należy do A, a jedynym obowiązkiem klienta jest dostarczyć ruch do A i przyjąć to, co wraca. Czy A kończy tunel, przekazuje go dalej, czy otwiera nowy, to pytanie, na które odpowiada reszta tego przeglądu, i ono decyduje, co A może czytać.
Szeregowo: A odszyfrowuje, a potem ponownie szyfruje
W projekcie szeregowym A kończy ruch dwa razy. Usuwa ochronę od klienta, otrzymuje pakiet IP aplikacji, a następnie wysyła ten pakiet drugim tunelem, który A tworzy w stronę B. Między tymi dwiema operacjami pakiet leży na ścieżce przekazywania A jako zwykły pakiet IP zaadresowany do celu prywatnego.
Daje to dwa skutki, które warto powiedzieć wprost. A może zastosować politykę do pakietu wewnętrznego w postaci tras, reguł filtrowania i rejestrowania źródła i celu, a A musi utrzymywać dwa zestawy poświadczeń: jeden jako serwer dla klienta i jeden jako klient B. Ochrona istnieje w każdej chwili, ale chroniony obiekt zmienia tożsamość w A.
Z tego nie wynika, że A czyta jawny tekst aplikacji. Gdy klient i usługa używają TLS i weryfikują nawzajem swoje certyfikaty, A widzi strumień rekordów TLS, a nie czytelne żądanie. Potwierdzenie, gdzie kończy się ta ochrona, wymaga spojrzenia na łańcuch certyfikatów usługi, a nie na schemat tunelu.
Zagnieżdżone: A usuwa tylko zewnętrzną warstwę
W projekcie zagnieżdżonym klient najpierw buduje wewnętrzny tunel do B, a następnie niesie ten tunel w zewnętrznym do A. A zdejmuje zewnętrzny nagłówek, znajduje wewnętrzny tunel i przekazuje go, nie trzymając jego kluczy, więc ochrona wewnętrzna nadal kończy się w B.
Łącze wysyłowe klienta niesie wtedy dwie warstwy, a ścieżka między A i B niesie jedną. A widzi zewnętrzne adresy tunelu wewnętrznego, co wystarcza, by wiedzieć, że ruch istnieje i mniej więcej dokąd zmierza, a nie wystarcza, by przeczytać ładunek. To cała różnica wobec przypadku szeregowego i żaden licznik skoków jej nie pokazuje. To, co A nadal może zrobić, to odmówić przekazania tego, czego nie potrafi przeczytać, a to jest zawsze dostępne operatorowi tej bramy.
Zagnieżdżenie kosztuje za tę właściwość. Każda warstwa dodaje narzut nagłówka, więc planowanie MTU i MSS staje się obowiązkowe, a nie tylko porządne, i ścieżka, która działa z jedną warstwą, z dwiema może po cichu gubić duże pakiety. Każda warstwa potrzebuje też własnego zachowania przy ponownym łączeniu i utrzymywaniu połączenia, a awaria w jednej warstwie wygląda przez drugą jak częściowa przerwa.
Rysujcie obserwatorów, nie tylko tunele
Tunele to łatwa część rysunku. Obserwatorzy są tematem projektu, więc napiszcie po jednym wierszu na punkt widzenia i wypełnijcie, co każdy naprawdę może przeczytać.
| Vantage point | Serial chain | Nested chain |
|---|---|---|
| Client's access network | Outer tunnel only | Outer tunnel only |
| Operator of A | Inner IP packet between A and B | Outer addresses of the inner tunnel, not its payload |
| Path between A and B | Second tunnel | Second tunnel |
| Operator of B | Inner packet re-originated by A | Payload after the inner layer is removed |
| Service edge | Traffic from the exit address | Traffic from the exit address |
Dwa wiersze są stale mylone: operator A i dostawca tunelu klienta. Mogą być jednym podmiotem, a odrębne nazwy bram nie czynią ich niezależnymi. Niezależna własność wymaga odrębnej kontroli administracyjnej, odrębnych poświadczeń i odrębnego rejestrowania.
Metadane przeżywają oba projekty. Czas, rozmiary pakietów i liczby połączeń pozostają obserwowalne na każdym skoku, więc dwa skoki podnoszą koszt korelacji, a nie usuwają sygnału. Projekt, który obiecuje niewidzialność, należy sprawdzić wobec tej listy, zanim ktoś na nim polega.
Przejdźcie ścieżki awarii, zanim wybierzecie
Psujcie rzeczy celowo od strony klienta, w kolejności, w jakiej użytkownik by je napotkał. Zacznijcie od interfejsu i jego MTU, bo zagnieżdżenie zawodzi na rozmiarze pakietu znacznie wcześniej niż na uwierzytelnianiu.
ip -4 addr show dev tun0
ip link show dev tun0 | grep mtu
ping -M do -s 1380 -c 2 10.77.1.1
Następnie potwierdźcie punkty końcowe ochrony, zamiast je zakładać. Poproście usługę o jej certyfikat z wnętrza dowolnego aktywnego tunelu i porównajcie łańcuch, który widzi klient, z łańcuchem, który usługa naprawdę przedstawia. Brama, która podpisuje ponownie lub przechwytuje, zmienia ten certyfikat, a kontrola staje się widoczna jednym poleceniem.
openssl s_client -connect intranet.example.com:443 -brief < /dev/null
Zakończcie macierzą ponownego łączenia: tunel klienta pada, tunel B pada, ścieżka między A i B się zmienia. Zanotujcie, co wraca, a co nie, i czy wewnętrzne połączenie kiedykolwiek spada na trasę poza swoim zamierzonym nośnikiem. Zapisujcie adresy użyte przez każdy test, bo powtórzenie w innej sieci dostępowej odpowiada na inne pytanie. Powtarzajcie też próbę MTU po każdym ponownym połączeniu, bo zmieniona ścieżka może obniżyć użyteczny rozmiar, nie ruszając ani jednej linii konfiguracji.
Wybierzcie szeregowy, gdy A musi zastosować politykę do pakietu wewnętrznego albo gdy klient nie może uruchomić dwóch warstwowych tuneli. Wybierzcie zagnieżdżenie, gdy wewnętrzny ładunek musi pozostać nieczytelny w A. Zapiszcie wybór wraz z jego obserwatorami i liczbami MTU, a następna osoba nie będzie musiała przerysowywać całego obrazu, by odpowiedzieć na jedno pytanie.