- PVSM.RU - https://www.pvsm.ru -
Давайте сразу вопрос на засыпку: может ли быть так, что клиент подключается, ну, например, к серверу www.python.org (самому настоящему, тому, к которому обращаются еще миллионы клиентов со всего мира), а потом использует его как прокси и гоняет через это подключение трафик до своего для доступа в неподцензурный интернет? Если вы не уверены в ответе на этот вопрос или почему-то ответили "нет", то добро пожаловать в статью.
Я уже не раз рассказывал здесь о технологии XTLS-Reality (1 [2], 2 [3], 3 [4]), суть которой в том, что ваш прокси-сервер
Еще я рассказывал о разных вариантах проксировать трафик посредством вебсокетов [5] и простых HTTP-туннелей через различные CDN, такие как Cloudflare и Gcore. Вероятность того, что под блокировку попадет вся CDN гораздо ниже, чем что забанят какой-то один сервер или диапазон хостера, но та схема требовала регистрацию своего домена для работы через CDN.
И наверняка многим в голову приходила идея, а нельзя ли как-нибудь совместить эти два механизма? Проксироваться через CDN, но при этом "прикрываясь" каким-нибудь чужим доменом? Ответ: да, можно, и сейчас мы посмотрим, как именно.
Итак, что такое "domain fronting"?
Что такое CDN, вы, наверное, хорошо знаете: это сети из тысяч серверов, которыми оперируют компании типа Cloudflare, Google, Amazon, и т.д, нередко с выделеными каналами связи между ними, которые используются для доставки интернет-трафика клиентам. Благодаря оптимальным маршрутам следования трафика и кэшированию данных поближе к пользователям, они позволяют раздавать контент быстрее и эффективнее и гибко масштабировать нагрузку.
А теперь разберем, что именно происходит, когда вы подключаетесь браузером к какому-нибудь сайту по HTTPS. Первый шаг - установление зашифрованного соединения по протоколу TLS. В самом начале запроса клиент, среди других данных, передает на сервер строку, называемую SNI - server name identification, в которой он указывает, к какому именно домену он хочет подключиться (потому что один веб-сервер может обслуживать сразу много доменов). Эта информация передается в нешифрованном виде, ее могут прочитать цензоры и заблокировать ваше подключение, если им не понравился домен интересующего вас сайта. Второй шаг — когда шифрованное подключение уже установлено, начинает работать протокол HTTP, и там, в заголовках запросов, есть поле "Host", в котором снова указывается домен сайта, к которому вы обращаетесь. На этом этапе данные передаются уже в зашифрованном виде, и подслушать со стороны их нельзя. Когда вы серфите сайтом в браузере, эти два значения (SNI в TLS и Host в HTTP) всегда одинаковые.
И когда-то очень давно, какой-то сообразительный Между прочим, каноническое значение этого слова - не "взломщик" (cracker), а "IT-специалист, занимающийся глубоким изучением работы систем и их нестандартного использования"</p>" data-abbr="хакер">хакер подумал: CDN может обслуживать сотни и тысячи разных сайтов, а что если мы передадим в SNI домен одного сайта, а в Host - домен другого? Он (или она, кто ж знает) попробовал и с удивлением обнаружил, что все работает и так - сервер демонстрирует TLS-сертификат домена, который был запрошен в SNI, но при этом отдает содержимое веб-сайта для другого домена, который был запрошен в HTTP Host. Так и появился domain fronting - когда обращаясь к веб-серверу мы "снаружи" демонстрируем один домен (приличный, разрешенный, незаблокированный), а на самом деле нас интересует другой.
Я, пожалуй, разделил бы domain fronting на два типа.
Первый тип - это когда мы прикрываемся каким-нибудь популярным доменом на той же CDN. Понятное дело, что для этого надо, чтобы CDN такое позволяла, а таких CDN все меньше и меньше - потому что кроме нас таких хороших подобной техникой еще пользуются всякие жулики для вредоносного ПО.
Второй тип - это когда CDN не разрешает прикрываться чужим доменом, но при этом для целей раздачи контента выдает свой технический домен типа cdn-abg456sf1.bignetwork.com, и мы можем работать через него, что тоже неплохо - во-первых не нужно иметь свой домен, а во-вторых, подобные домены все равно очень популярны, используются на тысячах сайтов, и ведут в правильный IP-диапазон, принадлежащий этой CDN. А если вдруг домен попал под блокировку, перепрыгнуть на другой можно за пару минут.
Осталось только узнать, какие именно CDN такое разрешают. Обладая эти знанием, мы можем гонять трафик до прокси-сервера через CDN, прикрываясь каким-нибудь чужим популярным доменом, например, через вебсокеты средствами XRay [5] или GOST [6], или даже без веб-сокетов (если CDN их не поддерживает или хочет за них дополнительных денег) через plain HTTP tunnel [6]. Такую же механику использовал [7] популярный мессенджер Signal, пока их не выгнали с Google Cloud и с Amazon, такую же механику до сих пор использует Tor с транспортом meek [8].
Собственно, в wiki Tor есть очень и очень интересный документ: https://gitlab.torproject.org/legacy/trac/-/wikis/doc/meek [9]. Там разбирается механика domain fronting, и приведен анализ возможностей использования его на разных популярных CDN. Одно НО — документ датируется 2018-м годом, и с тех пор очень многое поменялось. Я советую все равно изучить его для вдохновения и идей, а пока поделюсь тем, что успел нарыть сам.
Серверную часть можно настраивать так, как я описывал в статье "Особенности проксирования через CDN/Websocket/gRPC для обхода блокировок [5]", разве что в некоторых случаях вместо TLS (HTTPS) на сервере понадобится обычный HTTP (без шифрования и сертификатов). Также возможно использовать на сервере GOST [6] и его родной клиент.
Самая любимая на сегодняшний день CDN для фронтеров, потому что разрешает прикрываться чужими доменами. Но, кажется это золотое время уже проходит, потому что недавно они объявили, что в следущем году такую лафу запретят [10], однако пока еще есть немного времени чтобы поразвлекаться.
При регистрации дарят 50 долларов на аккаунт. Никаких паспортных данных предоставлять не надо, банковскую карту привязывать тоже, поэтому, в теории, ни что не мешает создавать новый аккаунт каждый раз, когда закончилась халява на старом (если что, осуждаем). Fastly может проксировать вебсокеты, они там идут по отдельному тарифу, но есть бесплатный 30-дневный пробный период.
Чтобы создать ресурс, нужно зарегистрироваться, потом пойти в раздел "Deliver", нажать "Create delivery service". Если у вас нет своего домена или вы не планируете его использовать, то в "Domains" можно написать все что угодно:

Далее идем в Origins -> Hosts и добавляем IP-адрес вашего сервера:

После добавления Origin Host можно нажать на редактирование и посмотреть, что там еще есть, а именно, настройки TLS:

Вот тут аккуратно. С одной стороны, хорошо бы, чтобы трафик между CDN и вашим сервером бегал зашифрованным. С другой стороны, если у вас нет своего домена, то вы сможете использовать только самоподписанный сертификат - в этом случае можно заполнить нужные поля и подсунуть в Fastly ваш сертификат, чтобы она знала, что сервер, с которым она коммуницирует, действительно тот, за кого себя выдает.
Но тут есть важный нюанс, в документации Fastly про проксирование вебсокетов написано, что вебсокеты не будут работать с самоподписанными сертификатами. Что там говорить, у меня они даже с настоящим сертификатом от LetsEncrypt не заработали, пока я не отключил TLS вообще. Поэтому можно оставить "No, do not enable TLS" и CDN будет подключаться к вашему серверу на простой 80 порт без шифрования.
В принципе, если вы хотите использовать plain HTTP tunnel, то это достаточно - можно сохранять параметры, нажимать "Activate", подождать 5-10 минут, пока информация о вашем ресурсе разлетится по серверам сети Fastly, и можно начинать пользоваться.
Если же вы хотите использовать вебсокеты, то все чуть сложнее - идем слева в меню в Settings -> Webosckets, скроллим вниз, активируем триальный период для вебсокетов и сами вебсокеты:

Думаете все? Ха, хрен там. Нужно сделать еще одну очень неочевидную вещь, которая запрятана глубоко в документации: https://developer.fastly.com/learning/concepts/real-time-messaging/websockets-tunnel/ [11]
Идите слева в меню в VCL snippets, нажмите Create your first snippet:

Там задаете какое-нибудь имя, выбираете средний тип "within subroutine", и саму сабрутину recv (vcl_recv), и вставляете там такой код:
if (req.http.Upgrade) {
return (upgrade);
}

Сохраняете, и наконец-то делаете Activate для вашего ресурса. Ждете 5-10 минут (раньше бесполезно - не заработает) и можно пробовать.
Настраивайте свой прокси-клиент с вебсокетами или plain HTTP tunnel так, чтобы он стучался на адрес какой-нибудь популярного сайта, который испольщует Fastly, например, www.python.org или www.spotify.com, пусть в SNI передается тоже www.python.org или www.spotify.com, но при этом в поле "Host" HTTP-запроса должен быть ваш домен (возможно даже в реальности не существующий), который вы указали при создании ресурса в Fastly.

Здесь у нас будет возможен фронтинг типа 2 - Amazon выдает "технический домен" для раздачи контента.
В первую очередь надо зарегистрироваться в облаке Amazon. Хоть мы и будем использовать Free Tier, придется привязать банковскую карточку, и да, карты российских банков не принимаются.
Я зарегистрировался в Amazon Cloud, но при попытке создать новый ресурс в Cloudfront вылетало сообщение типа "Неизвестная ошибка, обратитесь в техподдержку" (да, для тех кто делает такие сообщения об ошибках в аду зарезервирован отдельный котел). Я начал переписку с техподдержкой (на первой линии у них, кажется, отвечает нейросеть), и в итоге выяснилось, что им "требуется дополнительная верификация моего аккаунта". Впрочем, это не удивительно - у меня давным-давно был аккаунт со страной Russia, теперь у меня новый аккаунт с телефоном и адресом страны, где я теперь живу, но с тем же ФИО, при этом IP-адреса моего провайдера почему-то во всех GeoIP-база определяются не как страна где я живу, а как Германия, а карточку я привязал банка Revolut, которая по коду платежной системы вообще относится к какому-то литовскому банку. Короче, очень подозрительный аккаунт получился :)
В процессе переписки с саппортом мне вообще закрыли доступ к аккаунту. Оказалось, что Amazon несколько раз мне присылал емайлы, типа, "нам нужно уточнить ваши данные, пожалуйста, загрузите вот по этой ссылке вот такие документы в течении 3-х дней", но при этом GMail почему-то такие письма от Amazon'а отмечал как опасные и фишинговые (!) и отправлял сразу в спам, где я их, естественно, не видел.
В итоге они потребовали отправить им какие-нибудь счета за коммунальные услуги, где видно мое имя и адрес, а так же выписку из банка для карты, которую я привязал. Тут я немного подофигел, потому что жилье я арендую и счета приходят не на мое имя - в итоге сошлись на том, что я пришлю им ежемесячную квитанцию от моего мобильного оператора (там есть мое имя и адрес), и выписку со счета Revolut'а. После загрузки документов они присылали мне ответ, что мои документы "неразборчивые", не указывая, что именно там черт возьми неразборчивое, я загружал их снова, в итоге на 4-ую или 5-ую итерацию они все-таки согласились, что да, документы разборчивые :) Возможно помогло приложенное сопроводительное письмо, мол "вот это и вот это - вот это, и обратите внимание, dear sir or madam, выписка из банка - по счету, но если вы присмотритесь, то в деталях транзакции увидите так желаемый вами номер карты". И да, еще важно, чтобы выписка была именно по тому счету, с которого Амазон списал и вернул 1 евро для верификации карты.
В итоге аккаунт мне разблокировали, я попробовал снова создать ресурс в Cloudfront, и... снова получил ту же самую ошибку. Я переоткрыл тикет в поддержке, написал что проблема решена и изложил все что думаю по поводу их саппорта и сервиса. В итоге в субботу утром (!) мне поступил звонок на телефон с нью-йоркского номера, голос на другой стороне на хорошем английском представился саппортом Амазона, попросил продиктовать код верификации, который они отправили на емайл (там в емайле прямо так и пишется, "for Your Recent Support Request" и "please provide the following One-Time-Password (OTP) over the phone"), после чего сообщил, что они моё обращение разобрали, что-то там поправили у себя в моем аккаунте, и попросили сразу проверить, что теперь все работает. Я проверил - действительно заработало.
Итак, создали аккаунт, выбираем Free Tier - он включает в себя бесплатно 1 терабайт передаваемых данных в месяц и 10 миллионов запросов. С запросами аккуратнее, при постоянном использовании Plain HTTP tunnel их можно высадить и раньше чем за месяц, но мы будем использовать вебсокеты, Amazon их поддерживает даже на бесплатном тарифе.
Идем в консоли в Cloudfront, нажимаем Create distirbution:

И начинаем заполнять. Придется иметь свой домен, хоть какой-нибудь, пусть даже это будет бесплатный DynDNS - только лишь IP-адрес система использовать не дает. Вставляем его в Origin domain.
Протокол я для простоты выбрал HTTP only, чтобы не заморачиваться с сертификатом на сервере.

Далее привожу настройки, которые сработали у меня:
Origin shield = No

Viewer protocol policy = HTTP and HTTPS

Allowed HTTP methods - не особо важно, но на всякий случай выберем все

А вот теперь важное. Cache policy = caching disabled, Origin request policy = AllViewer - это нужно чтобы CDN передавала все заголовки от клиента на ваш сервер, иначе не заработают вебсокеты.

Web Application Firewall - я отключил.

Готово, нажимаем "Create distribution", и через некоторое время Cloudfront покажет вам ваш новый ресурс и технический домен для него:

Подождите, пока в поле Last modified появится нормальная дата, а не сообщение о том, что данные распространяются на сервера Cloudfront - до этого момента домен возможно уже будет работать, но вебсокеты не заведутся. Не лишним будет еще подождать 5-10 минут для надежности.
Все, а теперь вы можете использовать ваш технический домен *.cloudfront.net из поля "Distribution domain name" слева для подключения к своему прокси через вебсокеты. Все три параметра (адрес сервера, SNI и поле host) должны указывать на этот ваш домен.

А остальное - это ваше домашнее задание :) Существует еще много разных CDN - Microsoft Azure, Akamai, CDNetworks, Edgio, Stackpath, Level3 (его реселлеры
Допускают ли они domain fronting или предоставляют ли хотя бы технические домены - нам еще предстоит проверить. Я предлагаю поучаствовать в этом и вам по мере возможностей (да, могут потребоваться небольшие денежные вложения) и делиться результатами в комментариях к этому посту или на форуме ntc.party.
Транспорт meek от Tor имеет интересную возможность работать через так называемые "рефлекторы" - когда для того, чтобы подключиться к вашему прокси, используется не CDN, а простой скрипт на PHP или Python, который просто 1-в-1 передает пришедшие на него запросы на ваш прокси и обратно. Такой скрипт можно разместить даже на дешевом тупом shared-хостинге (не
Meek является pluggable transport'ом Tor, поэтому его непросто заставить работать отдельно (возможно поможет ptadapter [13] - если кто-то разберется, как заставить его работать с meek, напишите пожалуйста статью или хотя бы мне в ЛС), однако, судя по всему, довольно легко адаптировать его PHP-рефлектор [14] для работы с plain-HTTP-tunnel из GOST [6], а может быть он заработает даже без переделки. Что открывает очередной простор для экспериментов :)
P.S. Если есть желание сказать автору спасибо за все его труды и бессонные ночи — то:
BTC bc1ql2yecwzqtpp5xsmk08tzvyx98rqxf4qs848k54
ETH 0x8563494bd4732D7D7BF202521E7103Ea52d51cE5
USDT (TRC20) TRCUfmKJzn4XRBmEbRc5k87j78vLZKWg2U
Важно: автор не присутствует в Telegram или каких-либо иных месседжерах или соцсетях, не оказывает никаких платных консультаций и не выполняет никаких работ за деньги, а на вопросы отвечает только на Хабре (когда есть время). Остерегайтесь мошенников.
Автор: Surrounded by idiots
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/websocket/388515
Ссылки в тексте:
[1] VPS: https://www.reg.ru/?rlink=reflink-717
[2] 1: https://habr.com/ru/articles/727868/
[3] 2: https://habr.com/ru/articles/731608/
[4] 3: https://habr.com/ru/articles/735536/
[5] рассказывал о разных вариантах проксировать трафик посредством вебсокетов: https://habr.com/ru/articles/761798/
[6] GOST: https://habr.com/ru/articles/777656/
[7] использовал: https://signal.org/blog/looking-back-on-the-front/
[8] meek: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/meek
[9] https://gitlab.torproject.org/legacy/trac/-/wikis/doc/meek: https://gitlab.torproject.org/legacy/trac/-/wikis/doc/meek
[10] что в следущем году такую лафу запретят: https://github.com/net4people/bbs/issues/309
[11] https://developer.fastly.com/learning/concepts/real-time-messaging/websockets-tunnel/: https://developer.fastly.com/learning/concepts/real-time-messaging/websockets-tunnel/
[12] то-то такое умеет HostGator: https://www.hostgator.com/help/article/how-to-setup-and-use-a-shared-ssl-windows
[13] ptadapter: https://github.com/twisteroidambassador/ptadapter
[14] PHP-рефлектор: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/meek/-/tree/main/php?ref_type=heads
[15] Источник: https://habr.com/ru/articles/778134/?utm_source=habrahabr&utm_medium=rss&utm_campaign=778134
Нажмите здесь для печати.