TLS 1.3 nadal wysyła nazwę serwera jawnym tekstem
TLS 1.3 szyfruje uzgadnianie, ale nie SNI. Odczytaj ClientHello, sprawdź prawdziwą akceptację ECH i zapisz, co obserwator wciąż może zobaczyć.
Przełączenie listenera na TLS 1.3 zmienia to, co obserwator może odczytać, ale nie tak bardzo, jak sugeruje numer wersji. ClientHello nadal wędruje, zanim zostanie wynegocjowane jakiekolwiek szyfrowanie, a w zwykłym połączeniu żądana nazwa serwera leży tam jawnym tekstem. Encrypted Client Hello to mechanizm, który ją ukrywa, i jest to osobne wdrożenie z własnymi warunkami wstępnymi. Wykonaj te cztery kroki, zanim napiszesz politykę zakładającą jedno z tych zachowań.
Co faktycznie odsłania uzgadnianie połączenia
TLS 1.3 szyfruje certyfikat serwera i większość uzgadniania, które następuje po ServerHello. Wszystko, co klient wysyła najpierw, znajduje się poza tą ochroną, ponieważ klucze jeszcze nie istnieją. Wskazanie nazwy serwera jest częścią tego pierwszego lotu, dlatego pasywny obserwator wciąż może je odczytać, niczego nie łamiąc.
Specyfikacja ECH, RFC 9849, zmienia to, szyfrując wewnętrzny ClientHello dla współpracującego serwera. Zewnętrzne uzgadnianie pozostaje i niesie publiczną nazwę, którą sieć może zobaczyć, więc wdrożenie nadal potrzebuje zewnętrznej tożsamości, która ma sens dla pośredników. Ta zewnętrzna nazwa to część, którą ludzie przeoczają, gdy oczekują, że połączenie stanie się anonimowe. To nazwa osłonowa, a nie ukryta, i musi się rozwiązywać i uwierzytelniać jak każda inna.
Nic z tego nie ukrywa ścieżki dostarczania. Adresy źródłowe i docelowe, porty, rozmiary pakietów i czasy pozostają obserwowalne, a często mówią więcej o tym, kto rozmawia, niż nazwa. Rozwiązywanie nazw i relacje na poziomie aplikacji to jeszcze inna warstwa, każda z własną widocznością.
Odczytaj ClientHello zamiast zakładać
Wersja w ServerHello nie mówi, co wysłał klient. Przyjrzyj się pierwszemu lotowi bezpośrednio, z pozycji, która odpowiada obserwatorowi, na którym ci zależy.
openssl s_client -connect app.plant.example:443 -servername app.plant.example -tls1_3 </dev/null> 2>/dev/null | head -20 sudo tcpdump -ni eth0 -c 40 'tcp port 443' -w /tmp/tls.pcap tshark -r /tmp/tls.pcap -Y 'tls.handshake.extensions_server_name' -T fields -e tls.handshake.extensions_server_name
Pierwsze polecenie wykonuje uzgadnianie i pokazuje wynegocjowane parametry, w tym wersję protokołu i nazwę, o którą prosiłeś. Drugie przechwytuje pierwsze pakiety prawdziwego połączenia, a trzecie wyodrębnia pole SNI z tego przechwycenia. Jeśli pole jest wypełnione, emulowany przez ciebie obserwator może je odczytać.
Przechwytuj osobno po stronie klienta i na ścieżce, gdy te dwa się nie zgadzają, ponieważ lokalne przechwycenie może pokazać nazwę, którą middlebox później przepisuje lub odrzuca. Przechwytuj też z hosta, który sam nie kończy TLS, ponieważ kończące proxy widzi jawny tekst z założenia i niczego nie dowodzi o tym, co widzi sieć.
Traktuj rozszerzenie ECH jako twierdzenie, a nie dowód
Widok rozszerzenia ECH w ClientHello nie oznacza, że połączenie użyło ECH. Klienci wysyłają GREASE ECH, gdy nie mają użytecznej konfiguracji, właśnie po to, by ich uzgadniania wyglądały jednakowo. Rozszerzenie jest obecne, wewnętrzne hello to wabik, a rzeczywista nazwa wciąż jest czytelna.
dig +short HTTPS app.plant.example openssl s_client -connect app.plant.example:443 -tls1_3 -status </dev/null> 2>/dev/null | grep -i -E 'ech|status_request'
Pierwsze polecenie pokazuje, czy źródło publikuje rekord zasobu HTTPS z parametrem konfiguracji ECH, i w ten sposób klienci poznają klucz. Drugie szuka informacji o stanie uzgadniania, choć komunikat o powodzeniu klienta jest mocniejszym dowodem. Akceptacja jest tym, co się liczy: serwer, który nie ma pasującego klucza, nie może odszyfrować wewnętrznego hello, a połączenie się wycofuje.
Sprawdź też klienta, ponieważ obsługa przeglądarek i konfiguracja różnią się w zależności od wersji i platformy. Polityka oparta na „nowoczesne przeglądarki używają ECH” to domysł o flocie, a nie fakt o twojej flocie. Zinwentaryzuj wersje, które faktycznie się łączą, a potem przetestuj po jednej z każdej. Ta sama strona, która działa z aktualnej przeglądarki desktopowej, może niczego nie ukryć przed starszym klientem w tej samej sieci.
Zapisz zakres obserwatora w polityce
Określ, gdzie siedzi obserwator i co jest w tym punkcie widoczne, zanim zdecydujesz, na czym może polegać kontrola. Połączenie przeglądarki z witryną, zewnętrzny transport VPN i proxy kończące TLS ujawniają każdy inny zestaw faktów, a reguła napisana dla jednej pozycji rzadko przenosi się czysto na inną.
Jeśli kontrola zależy od odczytu SNI, sprawdź, jak zachowują się wdrożone klienty, gdy ECH jest dostępne, a gdy nie. Następnie zapisz konsekwencję zgodności, ponieważ filtr, który po cichu przestaje pasować, jest gorszy od takiego, którego nigdy nie wdrożono.
Na koniec zachowaj niepewność w protokole. Zastąpienie starego uniwersalnego twierdzenia nowszym zostawia tę samą lukę pod inną nazwą protokołu, a następny recenzent uwierzy w nie równie mocno.