Домен-фронтинг на базе 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). При попытке захода на сайт торрент-трекера — мы видим стандартную заглушку провайдера о том, что ресурс блокируется:



    На сайте РКН это домен действительно числится в стоп-листах:



    При запросе whois — видно, что сам домен «спрятан» за облачным провайдером Cloudflare.



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



    А как же так получается? Каким образом провайдерский DPI узнает, на какой из доменов идет мой браузер, ведь все коммуникации происходят по протоколу https, а подмены сертификатов https от билайна мы вроде пока не замечали? Уж не ясновидящий ли он или за мной идет слежка?

    Попробуем ответить на это вопрос, взглянув на трафик через wireshark



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



    Теперь давайте включим механизм 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 по ссылке и попробуем фокус с нашим торрент-трекером еще раз.



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



    На сей раз пакет 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.



    Видно, что сначала 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/

    Дамп трафика запроса представлен на скриншоте ниже:



    Видно, что сперва 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
    



    В данном случае мы обратились на заблокированный сервер 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, для работы «под прикрытием» других доменов. Подробнее об этом — в наших следующих статьях.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 35

      +2
      dns.goolge (тут нет опечатки, теперь у знаменитой корпорации появился свой домен первого уровня)


      Тут все же опечатка, они конечно dns.google (8.8.4.4).
        +2

        Да, бывает...

        0

        Спасибо за статью, доступно изложены новые фичи протоколов. Можно брать на вооружение!

          0

          Единственная проблема во всей этой системе, что и Гугл, и cloudflare собирают все данные, до которых только могут дотянуться. Также получается, что с внедрением doh в браузеры весь dns трафик замкнётся на 2х компаниях. Это не тот интернет, который нам нужен.

            0
            Ставьте на своей виртуалке AdGuard Home, и пользуйтесь DoH на своём сервере. Заодно и рекламу поблочите.
              0
              Эта проблема давно стоит, вспомнить хоть ту статью про журналистку, которая пыталась неделю не пользоваться продуктами Google.
              eSNI — лишь одна из проблем.
                0

                Это все ещё лучше, чем нешифрованный DNS, а если хочется приватности — используем свой личный DNS.

                +1

                Я вдруг понял, что мне это сломает фильтрацию дома на pi-hole.

                  0
                  Интересно, а шифрование домена для eSNI с одним и тем же ключом даёт один и тот же результат? Или там какие-то IV есть?
                    0
                    Стандарт, 7.5.5:
                    This design is not forward secret because the server's ESNI key is
                    static. However, the window of exposure is bound by the key
                    lifetime. It is RECOMMENDED that servers rotate keys frequently.

                    Может клиенты будут добавлять seed/nonce в SNI, может это даже в стандарт внесут (или уже, но я ленивая задница и не прочёл).
                      +1
                      Просто я подозреваю, что сам сервер DPI может делать такие же запросы, получать ключи, шифровать, добавлять в табличку, а потом просто сравнивать с такой таблицей пакеты юзеров :(
                        0
                        Вы не поняли: клиент добавляет шум.
                        Вместо:
                        Алиса и Мэллори получает один и тот же публичный ключ и шифруют с его помощью SNI, получают один шифротекст и можно использовать его вместо SNI для бана.
                        Получаем это:
                        Алиса и Мэллори получает один и тот же публичный ключ и шифруют с его помощью SNI, но Алиса добавляет шум: «telegram.org:::%random_uint%», получая постоянно уникальный шифротекст, который запомнить нельзя, но получатель может расшифровать и убрать шум.
                        Ну, я так надеюсь, выглядит логично, иначе толку от eSNI и правда мало.
                          0
                          Ну вот я это и имел ввиду под IV. Можно в данном случае это назвать nonce. Если это используется, то хорошо.
                            0
                            Хм, что это за «IV»?
                              0
                              Вектор инициализации, используется в AES.
                      0

                      У той же клаудфлары ключи меняются раз в 20-30 мин...

                        +2
                        А DPI делает запрос сразу же с пользовательским, получая актуальный ключ.
                      0

                      Очень хочется увидеть инструкцию по поднятию собственного DNS-сервера с поддержкой eSNI, дабы "отвязаться" от Google с Cloudflare.

                        0

                        Ну, вроде бы там ничего особо мудреного нет. Генерируем пару ключей, открытый ключ бейсим и отдаем в виде txt-записи на запросы _esni.mydomain.com
                        Закрытый ключ скармливаем nginx'у чтобы он мог распарить esni.

                        +3

                        Это ж блин, теперь любая малварь и реклама будет резолвиться безнаказанно :-/

                          0
                          Эм, клиент-то знает что он шифрует, до шифрования и блочить.
                            +3

                            Угу. Как мне это поможет, если приложение на телефоне начнет телеметрию слать и резолвиться мимо локального DNS?

                              0
                              Настройка, что тут делать-то?
                              Новые технологии требуют нового подхода, ничего необычного.
                              Настроить обращение к общему для сети DNS (роутер?), например.
                                0

                                У меня и так настроено. Но теперь все приложения смогут это игнорировать

                            0
                            Большую часть рекламы можно зарезать на уровне ДНС. Ставите тот же dnsmasq, с файлом хостов, остальное он запрашивает у клиента, запрашивающего по протоколу DoH/DoT с вашей виртуалки в ЕС. Это если наколеночно делать, а можно взять AdGuard Home, который я выше упомянул, он всё это умеет. И код открыт.
                            А то, что не зарезалось на ДНС, резать расширениями всякими. Например, если баннеры на том же домене, что и контент, только урл другой.
                              0

                              В следующей части как раз пример будет;)

                                0

                                Многие приложения уже давно используют DOH, например — Telegram.

                                0

                                Теперь самый интересный вопрос: когда же google в chrome включит eSNI? Сейчас они только DOH включают и то, очень аккуратно...

                                  0
                                  На sumtel не работает такой способ, там блочится TLS с неизвестным ssl hello на IP-адреса, внесённые в список РКН. По мере распространения eSNI (сейчас он доступен только ИТ-специалистам) (проще говоря когда будет в хроме по умолчанию), РКН, очевидно даст рекомендацию блочить такой трафик.

                                  Т.е. eSNI это лишь временная «победа» над РКН как когда-то был IPv6 («специалисты» РКН похоже долго не знали что оно существует)
                                    0

                                    Так можешь блочится по причине того, что ИП внесён в список? Вся прелесть dpi как раз в том и заключается, что ркн хочет уйти от блокировки по ипам...

                                      0
                                      нет, я проверял, если подключаться без esni на тот же ip, то не блочится (прописал ip в hosts и попробовал)
                                    +1
                                    Возможно глупый вопрос, но кто мешает вырезать из запроса клиента поле encrypted_server_name? А то, что у него что-то там не работает, проблема клиента.
                                    «Отчего вы не пишите письма на открытках? Вы что-то плохое прячете.»

                                    Поломать возможность клиенту использовать eSNI и жить счастливо. Как вариант?
                                      0

                                      Если вырезать что то из пакета, то придется пересчитывать все чек суммы, перестраивать пакеты и т.д. а это при большом трафике довольно таки накладно.
                                      Проще уж тогда совсем дропать такие пакеты, но тогда опять мы вернёмся к самой первой картинке в статье.

                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          0
                                          По этому поводу вспомнилось, как редактор какого-то журнала (кажется, «Юный натуралист») рассказывал байку
                                          оффтопик
                                          В редакцию вечером пришло письмо с Камчатки, какой-то мальчик поймал краба и спрашивал, чем его можно кормить. Редактор прикинул, что письмо шло несколько дней, краб там уже наверное на грани голодной смерти, подорвался на телеграф и отстучал «кормите краба тухлым мясом». А утром за ним пришли товарищи в штатском и поинтересовались, что за шифровки он передает по ночам в приграничные регионы — телеграфистке телеграмма показалась подозрительной, и она её передала не адресату, а в КГБ.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое