Fronting domeny oparty na TLS 1.3

Wprowadzenie

Fronting domeny oparty na TLS 1.3
Nowoczesne korporacyjne systemy filtrowania treści tak renomowanych producentów jak Cisco, BlueCoat, FireEye mają sporo wspólnego ze swoimi potężniejszymi odpowiednikami – systemami DPI, które są aktywnie wdrażane na poziomie krajowym. Istotą pracy obu jest kontrola przychodzącego i wychodzącego ruchu internetowego i na podstawie czarno-białych list podejmowanie decyzji o zakazie połączenia z Internetem. A ponieważ obaj w podstawach swojej pracy opierają się na podobnych zasadach, to sposoby ich obejścia również będą miały ze sobą wiele wspólnego.

Jedną z technologii, która pozwala dość skutecznie ominąć zarówno DPI, jak i systemy korporacyjne, jest technologia domainfronting. Jej istota polega na tym, że trafiamy do zablokowanego zasobu, chowając się za inną, publiczną domeną o dobrej reputacji, która oczywiście nie zostanie zablokowana przez żaden system, np. google.com.

O tej technologii napisano już sporo artykułów i podano wiele przykładów. Jednak popularne i ostatnio omawiane technologie DNS-over-HTTPS i szyfrowane-SNI, a także nowa wersja protokołu TLS 1.3, umożliwiają rozważenie innej opcji frontingu domeny.

Zrozumienie technologii

Najpierw zdefiniujmy trochę podstawowych pojęć, aby każdy wiedział, kto jest kim i dlaczego to wszystko jest potrzebne. Wspomnieliśmy o mechanizmie eSNI, którego działanie zostanie omówione w dalszej części. Mechanizm eSNI (ang. encrypted Server Name Indication) to bezpieczna wersja SNI, dostępna wyłącznie dla protokołu TLS 1.3. Główną ideą jest szyfrowanie m.in. informacji o tym, do której domeny kierowane jest żądanie.

Przyjrzyjmy się teraz, jak mechanizm eSNI działa w praktyce.

Załóżmy, że mamy zasób internetowy blokowany przez nowoczesne rozwiązanie DPI (weźmy na przykład słynny tracker torrentów rutracker.nl). Kiedy próbujemy uzyskać dostęp do strony internetowej narzędzia do śledzenia torrentów, widzimy standardowy kod pośredniczący dostawcy wskazujący, że zasób jest zablokowany:

Fronting domeny oparty na TLS 1.3

Na stronie RKN domena ta jest faktycznie wymieniona na listach zatrzymania:

Fronting domeny oparty na TLS 1.3

Gdy zapytasz Whois, zobaczysz, że sama domena jest „ukryta” za dostawcą usług w chmurze Cloudflare.

Fronting domeny oparty na TLS 1.3

Ale w przeciwieństwie do „specjalistów” z RKN, bardziej doświadczeni technicznie pracownicy Beeline (lub nauczeni gorzkim doświadczeniem naszego słynnego regulatora) nie głupio zablokowali witrynę według adresu IP, ale dodali nazwę domeny do listy stop. Możesz to łatwo zweryfikować, jeśli spojrzysz, jakie inne domeny kryją się za tym samym adresem IP, odwiedź jedną z nich i przekonaj się, że dostęp nie jest zablokowany:

Fronting domeny oparty na TLS 1.3

Jak to się stało? Skąd DPI dostawcy wie, w której domenie znajduje się moja przeglądarka, skoro cała komunikacja odbywa się po protokole https, a nie zauważyliśmy jeszcze zastąpienia certyfikatów https przez Beeline? Czy on jest jasnowidzem, czy jestem śledzony?

Spróbujmy odpowiedzieć na to pytanie, przyglądając się ruchowi w Wireshark

Fronting domeny oparty na TLS 1.3

Zrzut ekranu pokazuje, że najpierw przeglądarka uzyskuje adres IP serwera poprzez DNS, następnie następuje standardowe uzgadnianie protokołu TCP z serwerem docelowym, a następnie przeglądarka próbuje nawiązać połączenie SSL z serwerem. W tym celu wysyła pakiet SSL Client Hello, który zawiera nazwę domeny źródłowej w postaci zwykłego tekstu. To pole jest wymagane przez serwer frontendowy Cloudflare w celu prawidłowego przekierowania połączenia. W tym miejscu łapie nas dostawca DPI, zrywając nasze połączenie. Jednocześnie nie otrzymujemy żadnego kodu pośredniczącego od dostawcy i widzimy standardowy błąd przeglądarki, jakby strona była wyłączona lub po prostu nie działała:

Fronting domeny oparty na TLS 1.3

Włączmy teraz w przeglądarce mechanizm eSNI, tak jak napisano w instrukcji Firefox :
Aby to zrobić, otwieramy stronę konfiguracji Firefoksa about: config i aktywuj następujące ustawienia:

network.trr.mode = 2;
network.trr.uri = https://mozilla.cloudflare-dns.com/dns-query
network.security.esni.enabled = true

Następnie sprawdzimy, czy ustawienia działają poprawnie na stronie cloudflare. powiązanie i spróbujmy jeszcze raz skorzystać z naszego narzędzia do śledzenia torrentów.

Fronting domeny oparty na TLS 1.3

Voila. Nasz ulubiony tracker otworzył się bez VPN i serwerów proxy. Przyjrzyjmy się teraz zrzutowi ruchu w Wireshark, aby zobaczyć, co się stało.

Fronting domeny oparty na TLS 1.3

Tym razem pakiet hello klienta ssl nie zawiera jawnie domeny docelowej, ale zamiast tego w pakiecie pojawiło się nowe pole - zaszyfrowana_nazwa_serwera - w tym miejscu zawarta jest wartość rutracker.nl i tylko serwer frontendowy Cloudflare może to odszyfrować pole. A jeśli tak, to dostawca DPI nie ma innego wyjścia, jak tylko umyć ręce i pozwolić na taki ruch. Nie ma innych opcji z szyfrowaniem.

Przyjrzeliśmy się więc, jak ta technologia działa w przeglądarce. Spróbujmy teraz zastosować to do rzeczy bardziej konkretnych i interesujących. Najpierw nauczymy tego samego curla, jak używać eSNI do pracy z TLS 1.3, a jednocześnie zobaczymy, jak działa sam fronting domeny oparty na eSNI.

Fronting domeny z eSNI

Z uwagi na to, że curl wykorzystuje standardową bibliotekę openssl do łączenia się poprzez protokół https, przede wszystkim musimy zapewnić tam obsługę eSNI. W głównych gałęziach openssl nie ma jeszcze obsługi eSNI, więc musimy pobrać specjalną gałąź openssl, skompilować ją i zainstalować.

Klonujemy repozytorium z GitHuba i kompilujemy jak zwykle:

$ git clone https://github.com/sftcd/openssl
$ cd openssl
$ ./config

$ make
$ cd esnistuff
$ make

Następnie klonujemy repozytorium za pomocą curl i konfigurujemy jego kompilację przy użyciu naszej skompilowanej biblioteki openssl:

$ cd $HOME/code
$ git clone https://github.com/niallor/curl.git curl-esni
$ cd curl-esni

$ export LD_LIBRARY_PATH=/opt/openssl
$ ./buildconf
$ LDFLAGS="-L/opt/openssl" ./configure --with-ssl=/opt/openssl --enable-esni --enable-debug

Ważne jest tutaj, aby poprawnie określić wszystkie katalogi, w których znajduje się openssl (w naszym przypadku jest to /opt/openssl/) i upewnić się, że proces konfiguracji przebiegnie bez błędów.

Jeśli konfiguracja się powiedzie, zobaczymy linię:

OSTRZEŻENIE: esni ESNI włączone, ale oznaczone jako EKSPERYMENTALNE. Używaj ostrożnie!

$ make

Po pomyślnym zbudowaniu pakietu użyjemy specjalnego pliku bash z openssl do skonfigurowania i uruchomienia curl. Dla wygody skopiujmy go do katalogu z curl:

cp /opt/openssl/esnistuff/curl-esni 

i wykonaj testowe żądanie https do serwera Cloudflare, jednocześnie rejestrując pakiety DNS i TLS w Wireshark.

$ ESNI_COVER="www.hello-rkn.ru" ./curl-esni https://cloudflare.com/

W odpowiedzi serwera oprócz wielu informacji debugujących z openssl i curl otrzymamy odpowiedź HTTP z kodem 301 z cloudflare.

HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 13:12:55 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: max-age=3600
< Expires: Sun, 03 Nov 2019 14:12:55 GMT
< Location: https://www.cloudflare.com/

co oznacza, że ​​nasze żądanie zostało pomyślnie dostarczone do serwera docelowego, wysłuchane i przetworzone.

Przyjrzyjmy się teraz zrzutowi ruchu w Wireshark, tj. co dostawca DPI widział w tym przypadku.

Fronting domeny oparty na TLS 1.3

Widać, że curl najpierw zwrócił się do serwera DNS o publiczny klucz eSNI dla serwera cloudflare - żądanie TXT DNS do _esni.cloudflare.com (pakiet nr 13). Następnie korzystając z biblioteki openssl, curl wysłał do serwera cloudflare żądanie TLS 1.3, w którym pole SNI zostało zaszyfrowane kluczem publicznym uzyskanym w poprzednim kroku (pakiet #22). Ale oprócz pola eSNI pakiet SSL-hello zawierał także pole ze zwykłym - otwartym SNI, które możemy określić w dowolnej kolejności (w tym przypadku - www.hello-rkn.ru).

To otwarte pole SNI nie było w żaden sposób brane pod uwagę podczas przetwarzania przez serwery Cloudflare i służyło jedynie jako maska ​​dla DPI dostawcy. Serwer Cloudflare odebrał nasz pakiet ssl-hello, odszyfrował eSNI, wyodrębnił stamtąd oryginalny SNI i przetworzył go tak, jakby nic się nie stało (zrobiło wszystko dokładnie tak, jak zaplanowano podczas opracowywania eSNI).

Jedyną rzeczą, którą można w tym przypadku wychwycić z punktu widzenia DPI, jest główne żądanie DNS do _esni.cloudflare.com. Ale otworzyliśmy żądanie DNS tylko po to, aby pokazać, jak działa ten mechanizm od wewnątrz.

Aby w końcu wyciągnąć dywanik spod DPI, korzystamy ze wspomnianego już mechanizmu DNS-over-HTTPS. Małe wyjaśnienie - DOH to protokół, który pozwala zabezpieczyć się przed atakiem typu man-in-the-middle poprzez wysłanie żądania DNS przez HTTPS.

Zrealizujmy żądanie jeszcze raz, ale tym razem publiczne klucze eSNI otrzymamy poprzez protokół https, a nie DNS:

ESNI_COVER="www.hello-rkn.ru" DOH_URL=https://mozilla.cloudflare-dns.com/dns-query ./curl-esni https://cloudflare.com/

Zrzut ruchu żądania pokazano na zrzucie ekranu poniżej:

Fronting domeny oparty na TLS 1.3

Widać, że curl najpierw uzyskuje dostęp do serwera mozilla.cloudflare-dns.com poprzez protokół DoH (połączenie https z serwerem 104.16.249.249) w celu uzyskania od nich wartości kluczy publicznych do szyfrowania SNI, a następnie do miejsca docelowego serwer, chowając się za domeną www.hello-rkn.ru.

Oprócz powyższego resolwera DoH mozilla.cloudflare-dns.com możemy skorzystać z innych popularnych usług DoH, na przykład słynnej złej korporacji.
Uruchommy następujące zapytanie:

ESNI_COVER="www.kremlin.ru" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/

I otrzymujemy odpowiedź:

< HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 14:10:22 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=da0144d982437e77b0b37af7d00438b1a1572790222; expires=Mon, 02-Nov-20 14:10:22 GMT; path=/; domain=.rutracker.nl; HttpOnly; Secure
< Location: https://rutracker.nl/forum/index.php
< CF-Cache-Status: DYNAMIC
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 52feee696f42d891-CPH

Fronting domeny oparty na TLS 1.3

W tym przypadku zwróciliśmy się do zablokowanego serwera rutracker.nl, korzystając z resolwera DoH dns.google (tu nie ma literówki, teraz słynna korporacja ma własną domenę pierwszego poziomu) i zasłoniliśmy się inną domeną, która jest ściśle zabronione wszystkim DPI blokowanie pod groźbą śmierci. Na podstawie otrzymanej odpowiedzi można zrozumieć, że nasza prośba została pomyślnie przetworzona.

W ramach dodatkowego sprawdzenia, czy DPI dostawcy odpowiada na otwarty SNI, który przesyłamy jako przykrywkę, możemy wysłać żądanie do rutracker.nl pod przykrywką innego zabronionego zasobu, na przykład innego „dobrego” narzędzia do śledzenia torrentów:

$ ESNI_COVER="rutor.info" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/

Nie otrzymamy odpowiedzi z serwera, ponieważ... nasze żądanie zostanie zablokowane przez system DPI.

Krótkie podsumowanie pierwszej części

Udało nam się zatem zademonstrować funkcjonalność eSNI przy użyciu openssl i curl oraz przetestować działanie frontingu domen w oparciu o eSNI. W ten sam sposób możemy dostosować nasze ulubione narzędzia korzystające z biblioteki openssl do pracy „pod przykrywką” innych domen. Więcej szczegółów na ten temat w kolejnych naszych artykułach.

Źródło: www.habr.com

Dodaj komentarz