Дамен-франтынг на базе TLS 1.3

Увядзенне

Дамен-франтынг на базе TLS 1.3
Сучасныя карпаратыўныя сістэмы фільтрацыі кантэнту, ад такіх знакамітых вытворцаў як Cisco, BlueCoat, FireEye маюць даволі шмат агульнага з больш магутнымі іх субратамі – DPI сістэмамі, якія ўзмоцнена ўкараняюцца на нацыянальным узроўні. Сутнасць працы і тых і іншых у тым, каб ажыццяўляць надгляд уваходнага і выходнага інтэрнэт-трафіка і, на падставе чорных/белых спісаў, прымаць рашэнне аб забароне інтэрнэт-злучэння. А паколькі і тыя, і іншыя ў асновах сваёй працы належаць на падобныя прынцыпы, то і спосабы іх абыходу таксама будуць мець шмат агульнага.

Адной з тэхналогій, якая дазваляе дастаткова эфектыўна абыходзіць як DPI, так і карпаратыўныя сістэмы, з'яўляецца тэхналогія дамен-франтынгу. Яе сутнасць складаецца ў тым, што мы ідзем на заблакаваны рэсурс, прыкрываючыся іншым, публічным даменам, з добрай рэпутацыяй, які загадзя не будзе блакіраваны ніводнай сістэмай, напрыклад google.com.

Аб дадзенай тэхналогіі было напісана ўжо дастаткова шмат артыкулаў і прыведзена шмат прыкладаў. Аднак папулярныя і якія абмяркоўваюцца ў апошні час тэхналогіі DNS-over-HTTPS і encrypted-SNI, а таксама новая версія пратаколу TLS 1.3 даюць магчымасць разгледзець яшчэ адзін варыянт дамен-франтынгу.

Разбіраемся з тэхналогіяй

Спачатку крыху вызначымся з асноўнымі паняццямі, каб ва ўсіх было разуменне who is who і навошта ўсё гэта трэба. Мы згадалі механізм eSNI, праца якога будзе разгледжана далей. Механізм eSNI (encrypted Server Name Indication) - абаронены варыянт SNI, даступны толькі для пратаколу TLS 1.3. Асноўная сутнасць - шыфраваць у тым ліку інфармацыю аб тым, да якога дамену адпраўляецца запыт.

А зараз давайце разгледзім працу механізму eSNI на практыку.

Дапушчальны, у нас ёсць інтэрнэт-рэсурс, які блакуецца сучасным DPI рашэннем (возьмем да прыкладу, знакаміты торэнт-трэкер — rutracker.nl). Пры спробе заходу на сайт торэнт-трэкера - мы бачым стандартную заглушку правайдэра аб тым, што рэсурс блакуецца:

Дамен-франтынг на базе TLS 1.3

На сайце РКН гэта дамен сапраўды лічыцца ў стоп-лістах:

Дамен-франтынг на базе TLS 1.3

Пры запыце whois – відаць, што сам дамен «схаваны» за хмарным правайдэрам Cloudflare.

Дамен-франтынг на базе TLS 1.3

Але ў адрозненне ад «адмыслоўцаў» з РКН, больш тэхнічна падкаваныя супрацоўнікі з білайна (ці навучаныя горкім досведам нашага знакамітага рэгулятара) не сталі тупа баніць сайт па IP-адрасу, а занеслі ў стоп-ліст менавіта даменнае імя. У гэтым лёгка пераканацца, калі паглядзець, якія яшчэ дамены хаваюцца за гэтым жа IP-адрасам, наведаць адзін з іх і ўбачыць, што доступ не заблакаваны:

Дамен-франтынг на базе TLS 1.3

А як жа гэта атрымліваецца? Якім чынам правайдэрскі DPI даведаецца, на які з даменаў ідзе мой браўзэр, бо ўсе камунікацыі адбываюцца па пратаколе https, а падмены сертыфікатаў https ад білайна мы нібыта пакуль не заўважалі? Ці не празорлівы ён ці за мной ідзе сачэнне?

Паспрабуем адказаць на гэтае пытанне, зірнуўшы на трафік праз wireshark

Дамен-франтынг на базе TLS 1.3

На скрыншоце відаць, што спачатку браўзэр атрымлівае IP-адрас сервера праз DNS, потым адбываецца стандартнае TCP-поціск рукі з серверам прызначэння, а затым браўзэр спрабуе ўсталяваць ssl-злучэнне з серверам. Для гэтага ён перадае пакет SSL Client Hello, у якім прысутнічае імя зыходнага дамена ў адчыненым выглядзе. Гэтае поле неабходна фронтэнд-серверу cloudflare для таго, каб правільна маршрутызаваць злучэнне. Вось тут-то нас і ловіць правайдэрскі DPI, раздзіраючы наша злучэнне. Пры гэтым мы не атрымліваем ніякай заглушкі ад правайдэра, і бачым стандартную памылку браўзэра як быццам сайт адключаны ці проста не працуе:

Дамен-франтынг на базе TLS 1.3

Цяпер давайце ўключым механізм eSNI у браўзэры, як гэта напісана ў інструкцыі для Firefox :
Для гэтага мы адчыняем старонку канфігурацыі Firefox about: config і які актывуецца наступныя налады:

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

Пасля гэтага мы праверым карэктнасць працы налад на сайце cloudflare па спасылцы і паспрабуем фокус з нашым торэнт-трэкерам яшчэ раз.

Дамен-франтынг на базе TLS 1.3

Вуаля. Наш любімы трэкер адкрыўся, без якіх-небудзь VPN і проксі-сервераў. Давайце зараз паглядзім на дамп трафіку ў wireshark, што ж адбылося.

Дамен-франтынг на базе TLS 1.3

На гэты раз пакет ssl client hello не ўтрымоўвае ў відавочным выглядзе дамен прызначэння, а замест гэтага ў складзе пакета з'явілася новае поле - encrypted_server_name - менавіта тамака і ўтрымоўваецца значэнне rutracker.nl, і расшыфраваць гэтае поле можа толькі фронтэнд сервер cloudflare. А раз так, то правайдэрскаму DPI не застаецца нічога акрамя як умыць рукі і дазволіць такі трафік. А іншых варыянтаў з шыфраваннем і не.

Такім чынам, як працуе тэхналогія ў браўзэры - мы паглядзелі. Цяпер давайце паспрабуем прымяніць яе для больш спецыфічных і цікавых рэчаў. І для пачатку мы навучым той жа curl выкарыстоўваць eSNI для працы з TLS 1.3, а заадно паглядзім, як працуе сам дамен-франтынг на аснове eSNI.

Дамен-франтынг з eSNI

З прычыны таго, што curl для падлучэння па пратаколе https выкарыстоўвае стандартную бібліятэку openssl, найперш нам неабходна забяспечыць падтрымку eSNI менавіта там. У master-галінках openssl падтрымкі eSNI пакуль што няма, таму нам неабходна спампаваць адмысловую галінку openssl, скампіляваць і ўсталяваць яе.

Клануем рэпазітар з гітхаба і кампілюем як звычайна:

$ 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/

што сведчыць аб тым, што наш запыт быў паспяхова дастаўлены да сервера прызначэння, пачуты і апрацаваны.

Цяпер давайце паглядзім на дамп трафіку ў wireshark, г.зн. што ўбачыў у дадзеным выпадку правайдэрскі DPI.

Дамен-франтынг на базе TLS 1.3

Відаць, што спачатку curl звярнуўся да DNS сервера за публічнымі eSNI ключом для сервера cloudflare – TXT DNS запыт на _esni.cloudflare.com (пакет №13). Затым, выкарыстоўваючы openssl-бібліятэку, curl адправіў TLS 1.3 запыт на сервер cloudflare у якім поле SNI было зашыфравана публічным ключом, атрыманым на папярэднім этапе (пакет №22). Але, акрамя поля eSNI, у складзе SSL-hello пакета было ўстаўлена яшчэ і поле са звычайным – адчыненым SNI, якое мы можам паказаць у адвольным парадку (у дадзеным выпадку – www.hello-rkn.ru).

Дадзенае поле адчыненага SNI ніяк не ўлічвалася пры апрацоўцы серверамі cloudflare і толькі з'яўлялася маскіровачным для правайдэрскага DPI. Сервер cloudflare прыняў наш ssl-hello пакет, расшыфраваў eSNI, дастаў адтуль арыгінальны SNI і апрацаваў яго як ні ў чым не хаджала (зрабіў усё менавіта так, як планавалася пры распрацоўцы eSNI).

Адзінае, завошта ў дадзеным выпадку можна ўчапіцца з пункта гледжання DPI - першасны DNS запыт на _esni.cloudflare.com. Але мы зрабілі DNS запыт адчыненым толькі для таго, каб паказаць, як дадзены механізм працуе знутры.

Каб канчаткова выбіць глебу з-пад ног DPI мы выкарыстоўваем ужо згаданы механізм DNS-over-HTTPS. Невялікае тлумачэнне - DOH - пратакол, які дазваляе абараніцца ад нападу "чалавек пасярэдзіне" за рахунак адпраўкі DNS-запыту па пратаколе HTTPS.

Выканаем запыт паўторна, але ў гэты раз публічныя eSNI ключы мы атрымаем па пратаколе https, а не DNS:

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

Дамп трафіку запыту прадстаўлены на скрыншоце ніжэй:

Дамен-франтынг на базе TLS 1.3

Відаць, што перш curl звяртаецца да сервера mozilla.cloudflare-dns.com па пратаколе DoH (https злучэнне на сервер 104.16.249.249), каб ад іх атрымаць значэнні public ключоў для шыфравання SNI, а затым ужо да сервера прызначэння, затуляючыся пры гэтым даменам. www.hello-rkn.ru.

Апроч паказанага вышэй DoH рэзалвера mozilla.cloudflare-dns.com мы можам выкарыстоўваць і іншыя папулярныя сэрвісы DoH, напрыклад, ад знакамітай карпарацыі зла.
Выканаем такі запыт:

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

Дамен-франтынг на базе TLS 1.3

У дадзеным выпадку мы звярнуліся на заблакаваны сервер 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/

Адказу ад сервера мы не атрымаем, т.я. наш запыт будзе заблакаваны DPI-сістэмай.

Невялікае заключэнне да першай часткі

Такім чынам, нам удалося паказаць працаздольнасць eSNI з дапамогай openssl і curl і праверыць працу дамен-франтынгу, заснаванага на eSNI. Такім жа чынам мы можам адаптаваць нашы любімыя інструменты, якія выкарыстоўваюць бібліятэку openssl, для працы "пад прыкрыццём" іншых даменаў. Больш падрабязна пра гэта - у нашых наступных артыкулах.

Крыніца: habr.com

Дадаць каментар