Sissejuhatus

Moodne ettevõtte sisu filtreerimise süsteemid, nagu Cisco, BlueCoat ja FireEye, omavad palju ühist oma võimsamate kolleegidega — DPI süsteemidega, mis on laialdaselt kasutusele võetud riiklikul tasandil. Nende töö tuumik on sama: uurida saabuvat ja väljaminevat interneti liiklust ning mustade/valgete serverite põhjal otsustada internetiühenduse blokeerimise üle. Kuna mõlemad tuginevad oma töös sarnastele põhimõtetele, on ka nende ületamise viisidel palju ühist.
Üks tehnoloogiatest, mis võimaldab tõhusalt vältida nii DPI-d kui ka ettevõtte süsteeme, on domeenifrontimine. Selle olemus seisneb selles, et me pääseme blokeeritud ressursile, varjates end teise, avaliku domeeni, hea mainega, millel ei ole mingit süsteemi poolt blokeerimise ohtu, näiteks google.com.
Selle tehnoloogia kohta on juba kirjutatud piisavalt palju artikleid ja toodud esile palju näiteid. Kuid populaarsed ja viimastel aegadel arutelud teema DNS-over-HTTPS ja krüptitud SNI, samuti uus protokoll TLS 1.3 annavad võimaluse vaadelda veel ühte domeenide peitmise varianti.
Uurime tehnoloogiat
Alustame natuke põhimõistetega, et kõigil oleks arusaam, kes on kes ja miks see kõik vajalik on. Oleme maininud eSNI mehhanismi, mille tööle saab edaspidi lähemalt vaatama. eSNI (krüptitud Server Name Indication) on SNI kaitstud variant, mis on saadaval ainult protokolli TLS 1.3 jaoks. Põhimõte on selles, et krüptida ka teavet selle kohta, millisele domeenile päring saadetakse.
Nüüd vaatame eSNI mehhanismi tööd praktikas.
Oletame, et meil on internetiressurss, mis on blokeeritud kaasaegse DPI lahendusega (võtame näiteks kuulus torrentide jälgija — rutracker.nl). Kui proovime külastada torrentide jälgija saiti, näeme teenusepakkuja tavalist teavitust, et ressurss on blokeeritud:

RKNi lehelt on see domeen tõepoolest mustades nimekirjades:

Whois päringut tehes on näha, et domeen on „peidetud“ Cloudflare'i pilveteenuse pakkuja taha.

Kuid erinevalt RKN-i „spetsialistidest“ ei otsustanud tehniliselt paremini haritud töötajad Beeline'is (või kellel on olnud valusat kogemust meie tuntud regulaatoriga) lihtsalt IP-aadressi põhjal saiti blokeerida, vaid lisasid musta nimekirja just domeeninime. Selle tõelisusesse veendumiseks vaadake, millised teised domeenid on sama IP-aadressiga, külastage ühte neist ja näete, et juurdepääs ei ole blokeeritud:

Kuidas see nii juhtub? Kuidas teab teenusepakkuja DPI, kuhu minu brauser suundub, kui kõik suhtlused toimuvad https-protokolli kaudu, ja Beeline'i poolt sertifikaatide valevahetust me siiani pole märganud? Kas ta on kaugeleulatuv või jälgib keegi mind?
Proovime sellele küsimusele vastata, vaadates liiklust Wiresharki kaudu.

Ekraanipildil on näha, et esmalt saab brauser DNS-i kaudu serveri IP-aadresse, seejärel toimub standardne TCP kätlemine sihiserveriga, ja siis püüab brauser SSL-ühendust serveriga luua. Selleks edastab ta paketi SSL Client Hello, milles on algse domeeni nimi avatud kujul. See väli on vajalik cloudflare'i esirakenduse serverile, et korralikult suunata ühendust. Just siin tabab meid teenusepakkuja DPI, katkestades meie ühenduse. Sel juhul me ei saa teenusepakkujalt mingit tõkestust ja näeme standardset brauseri viga justkui sait oleks välja lülitatud või lihtsalt ei tööta:

Nüüd lülitame brauseris sisse eSNI mehhanismi, nagu on kirjutatud juhendis Firefox :
Selleks avame Firefoxi konfiguratsioonilehe about:config ja aktiveerime järgmised seaded:
network.trr.mode = 2;
network.trr.uri = https://mozilla.cloudflare-dns.com/dns-query
network.security.esni.enabled = true
Pärast seda kontrollime seadete õigsust cloudflare'i saidil lingi kaudu ja proovime meie torrent-trackeriga trikki veel kord.

Voilà. Meie lemmik tracker avanes, ilma igasuguste VPNide ja proksiserveriteta. Vaatame nüüd wireshark'is liiklusdummit, mis juhtus.

Sel korral ssl kliendi tervituse pakett ei sisalda selgesõnaliselt sihtdomeeni, vaid selle asemel on paketi koostises uus väli — encrypted_server_name — just seal paikneb väärtus rutracker.nl, ning seda välja suudab dekrüpteerida ainult Cloudflare'i frontend-server. Seega ei jää teenusepakkuja DPI-le muud üle, kui käed üles tõsta ja selline liiklus lubada. Teisi šifreerimise variante pole.
Nüüd, kui me oleme vaadanud, kuidas tehnoloogia brauseris töötab, proovime rakendada seda spetsiifilisematel ja huvitavatel viisidel. Esmalt õpetame curl'i kasutama eSNI-d TLS 1.3 puhul ning vaatame, kuidas toimib domeenifronting eSNI alusel.
Domeenifronting eSNI-ga
Kuna curl kasutab https-protokolli jaoks standardset OpenSSL teeki, peame kõigepealt tagama eSNI toe just seal. OpenSSL-i master-haru ei toeta veel eSNI-d, seega peame laadima alla erilise OpenSSL haru, selle kompileerima ja installima.
Kloonime GitHubi hoidla ja kompileerime nagu tavaliselt:
$ git clone https://github.com/sftcd/openssl
$ cd openssl
$ ./config
$ make
$ cd esnistuff
$ make
Далее — клонируем репозиторий с curl и конфигурируем его компиляцию с использованием нашей собранной 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
Здесь важно правильно указать все каталоги, где находится openssl (в нашем случае — это /opt/openssl/) и проследить, чтобы процесс конфигурации прошел без ошибок.
В случае успешной конфигурации — мы увидим строку:
WARNING: esni ESNI enabled but marked EXPERIMENTAL. Use with caution!
$ makeПосле успешной сборки пакета мы воспользуемся специальным bash-файлом из состава openssl для настройки и запуска curl. Скопируем его в каталог с curl для удобства:
cp /opt/openssl/esnistuff/curl-esni и выполним тестовый https-запрос на сервер cloudflare, одновременно записав DNS и TLS пакеты в Wireshark.
$ ESNI_COVER="www.hello-rkn.ru" ./curl-esni https://cloudflare.com/В ответе сервера помимо множества отладочной-информации от openssl и curl мы получим HTTP-ответ с кодом 301 от 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/
mis näitab, et meie päring on edukalt jõudnud sihtserverisse, kuulatud ja töödeldud.
Nüüd vaatame Wiresharkis liiklust, st mida nägi antud juhul teenusepakkuja DPI.

On näha, et esmalt küsis curl DNS-serverilt avalike eSNI võtmete kohta Cloudflare'i serveri jaoks – TXT DNS-küsimus _esni.cloudflare.com (pakett nr 13). Seejärel saatis curl, kasutades openssl-i teeki, TLS 1.3 päringu Cloudflare'i serverile, kus SNI väli oli krüpteeritud eelnevalt saadud avaliku võtmega (pakett nr 22). Kuid lisaks eSNI väljale oli SSL-hello paketi koostisesse lisatud veel ka tavapärase, avaliku SNI väli, mille saame määrata suvalises järjekorras (antud juhul – www.hello-rkn.ru).
Antud avaliku SNI väli ei mõjutanud Cloudflare'i serverites töötlemist ja see oli lihtsalt teenusepakkuja DPI jaoks maskeeriv. Cloudflare'i server võttis meie ssl-hello paketi vastu, dekrüpteeris eSNI, ekstrakteeris sealt algse SNI ja töötles selle nagu tavaliselt (tegi kõik just nii, nagu eSNI väljatöötamisel oli planeeritud).
Ainus, millele sellisel juhul DPI mõttes toetuda, on esmase DNS-päringu tegemine _esni.cloudflare.com. Kuid me tegime DNS-päringu avalikuks vaid selleks, et näidata, kuidas see mehhanism seestpoolt töötab.
DPI alt väljasaamiseks kasutame juba mainitud DNS-over-HTTPS mehhanismi. Väike selgitus – DOH on protokoll, mis kaitseb keskmise inimese rünnaku eest, edastades DNS-päringu HTTPS-protokolli kaudu.
Teeme päringu uuesti, kuid seekord saame avalikud eSNI võtmed HTTPS-protokolli, mitte DNS kaudu:
ESNI_COVER="www.hello-rkn.ru" DOH_URL=https://mozilla.cloudflare-dns.com/dns-query ./curl-esni https://cloudflare.com/Päringu liikluse dump on esitatud alloleval ekraanipiltidel:

On näha, et esmalt pöördub curl serveri mozilla.cloudflare-dns.com poole DoH protokolli kaudu (HTTPS-ühendus serveriga 104.16.249.249), et saada neilt avalikud võtmed SNI krüpteerimiseks, ning seejärel juba sihtserveri poole, kaitstes end samas domeeni kaudu. www.hello-rkn.ru.
Lisaks eelnevale DoH resolvijale mozilla.cloudflare-dns.com saame kasutada ka teisi populaarseid DoH teenuseid, näiteks ühte kurikuulsast kurjast ettevõttest.
Teeme sellise päringu:
ESNI_COVER="www.kremlin.ru" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/И получим ответ:
< 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

В данном случае мы обратились на заблокированный сервер rutracker.nl, использовав при этом DoH-резолвер dns.google (тут нет опечатки, теперь у знаменитой корпорации появился свой домен первого уровня) и прикрылись уже другим доменом, блокировать который строго-настрого запрещено всем DPI под страхом смертной казни. По полученному ответу можно понять, что наш запрос был удачно обработан.
В качестве дополнительной проверки того, что провайдерский DPI реагирует на открытый SNI, который мы передаем в качестве прикрытия — мы можем выполнить запрос к rutracker.nl прикрывшись каким-нибудь другим запрещенным ресурсом, например другим «хорошим» торрент-трекером:
$ ESNI_COVER="rutor.info" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/Serverilt vastust ei saa, kuna meie päring blokeeritakse DPI-süsteemi poolt.
Lühike kokkuvõte esimesele osale
Nii õnnestus meil demonstreerida eSNI toimimist openssl ja curl abil ning kontrollida eSNI-põhise domeeni esiotsa töökindlust. Samamoodi saame kohandada oma lemmikinstrumente, mis kasutavad openssl raamatukogu, et töötada "varjatult" teiste domeenide all. Rohkem teavet selle kohta leiate meie järgmistest artiklitest.
Allikas: habr.com
