Кратко про XHTTP для VLESS: что, зачем и как

02ea1e09ca7e1499758c4f3cc683b9e9

Просили нас тут рассказать про протокол технологию XHTTP в контексте XRay, VLESS и прочих. Просили — рассказываем!

К сожалению, официальной документации по XHTTP практически нет, кроме весьма упоротого поста на гитхабе, который написан довольно своеобразно и не очень понятен людям «не в теме». Там есть еще в комментариях русский перевод с китайского, но он настолько плох, что лучше бы его не было (хотя можно читать ради здорового смеха — одна только »блокировка головки TCP» чего стоит).

Для начала немного истории. Классическое использование VLESS и подобных прокси-протоколов (в том числе с использование XTLS-Reality) предполагает подключение клиента напрямую к прокси-серверу, который крутится на каком-нибудь VPS. Однако во многих странах (и в России тоже) под блокировки (или замедления) начали попадать подсети популярных хостеров целиком, а в других странах цензоры начали отслеживать подключения к «одиночным» адресам с большим объемом трафика. Поэтому еще с давних времен обдумывались и проверялись идеи подключения к прокси-серверам через CDN (сети доставки трафика). Чаще всего для этого использовался websocket-транспорт, но у этого варианта есть два больших недостатка: у него есть один характерный признак (не буду указывать его тут, чтобы не облегчать работу РКН), а во-вторых, число CDN, которые поддерживают проксирование вебсокетов, не так уж велико, и хотелось бы иметь возможность проксироваться и через те, что не умеют.

Поэтому сначала в известном проекте Tor для бриджей (мостов) придумали транспорт meek, который позволял передавать данные с помощью многочисленные запросов-ответов по HTTP, и таким образом позволял подключаться к мостам (прокси) через любые CDN. Чуть позже этот же транспорт реализовали в ненадолго воскресшем из мертвых V2Ray. Но у meek есть два очень существенных недостатка, которые вытекают из его принципа работы: скорость работы очень низкая (по сути дела у нас полудуплексная передача и огромный оверхед на постоянные запросы-ответы), и из-за огромного количества GET/POST-запросов каждую секунду, бесплатные CDN довольно быстро могут нас выгнать на мороз, а платные — выкатить солидный счет.

Авторам XRay же в голову пришла отличная идея, как улучшить этот механизм:, а что если разделить прием и передачу на два соединения — одно для приема, одно для передачи? Так появился транспорт SplitTunnel, который в результате дальнейшего развития превратился в XHTTP.

Сразу уточню две вещи. Первое, XHTTP — это не протокол, а именно транспорт. Обычно его используют для всем известного протокола VLESS, хотя в теории можно использовать и для других. Второе, XHTTP изначально придумывался для работы через CDN, но по факту он может использоваться и без CDN для прямого подключения к серверу, и это тоже дает определенные преимущества.

XHTTP имеет три режима работы:

  1. packet-up — режим наиболее медленный (но все равно гораздо быстрее чем meek), но совместимый практически со всеми веб-серверами и CDN. Используется одно соединение для передачи данных от сервера к клиенту, и множество короткоживущих соединений для передачи данных от клиента к серверу
    (здесь и далее под «соединение» понимается не конкретно TCP-соединения, а сессия «запрос-ответ» в HTTP, множество которых может жить внутри одно TCP-соединения, но в любом случае, TCP-соединения для трафика «туда» и «обратно» будут разные)

  2. stream-up — более скоростной, но с худшей совместимостью — пролезает только через определенные (или определенно настроенные) веб-сервера. Одно долгоживущее соединение для передачи «клиент→сервер», одно долгоживущее соединение для передачи «сервер→клиент».

  3. stream-one — единственный режим, который не разделяет соединения для «туда» и «обратно», а всегда передает данные в обе стороны внутри только одного соединения. По сути дела то же самое, что обычный VLESS с HTTP-заголовком (был такой транспорт в XRay раньше). Пролезает только через Nginx с директивой grpc_pass и через Cloudflare с включенной фичей gRPC (по факту gRPC там на самом деле не используется, это только обманка, чтобы Nginx и CF не вмешивались в передаваемые запросы-ответы).

Какие же преимущества дает XHTTP?

  1. Возможность подключаться к серверу не только по HTTPS, но и через QUIC (надо на клиенте явно поставить ALPN h3) — может работать более эффективно при нестабильном канале связи или если HTTPS заблокирован, а QUIC заблокировать забыли;

  2. Возможность подключаться к прокси-серверу используя TLS v1.2, при этом имея фингерпринт настоящего веб-сервера. Тут поясню чуть подробнее. Фингерпринт — «отпечаток», набор определенных характеристик в реализации TLS и поведения веб-сервера в целом, отличительные черты, так сказать. Fingerprint’ы у сервера XRay и у настоящего веб-сервера (например, Nginx, Caddy, и др.) разные, и это может использоваться для детектирования прокси. Обычно для избежания этого используют XTLS-Reality в так называемом режиме «steal from yourself» — когда вы маскируетесь по свой же собственный веб-сервер, работающий на том же хосте. Проблема в том, что XTLS-Reality работает только через TLS v1.3, а РКН уже не раз ловили на том, что они блокировали TLS v1.3 в стороны популярных хостеров. Используя XHTTP вы можете подключаться к прокси по TLS v1.2, при этом фингерпринт сервера будет аутентичным — потому что на 443 порту у вас будет слушать настоящий Nginx, а XRay будет стоят уже позади него.

  3. Возможность подключаться через CDN, в том числе которые не поддерживают Websockets и gRPC. При этом некоторые CDN до сих пор разрешают domain fronting, о котором рассказывал в своей статье MiraclePtr. Таким образом, вы можете маскироваться под чужой домен даже еще лучше, чем это было с XTLS-Reality — теперь когда вы подключаетесь к прокси, вы не только подключаетесь с SNI какого-нибудь чужого домена и получаете его настоящий сертификат в ответ, но и более того — вы подключаетесь именно к тому IP-адресу, в который резолвится этот самый домен, и вы такой не один — к этому адресу с тем же SNI подключаются еще тысячи людей со всей страны. Идеально.

  4. Можно использовать browser dialer. Это решает схожую с п.2 проблему с fingerprint’ом, но уже не сервера, а клиента. XRay и подобные используют библиотеку uTLS чтобы маскироваться под fingerprint’ы популярных браузеров, но эта маскировка не стопроцентная. А с browser dialer схема выглядит так: вы открываете в браузере страницу со специальным скриптом, и ваш XRay-клиент подключается не напрямую к прокси, а сначала к браузеру, а уже скрипт из браузера подключается к прокси. В итоге fingerprint и поведение клиента похоже на настоящий браузер настолько, насколько это вообще возможно — потому что фактически клиентом является сам настоящий браузер.

  5. И наконец, самое вкусное. В режимах packet-up и stream-up передаваемые данные разделяются как минимум на два подключения «туда» и «обратно», и это очень сильно затрудняет анализ паттернов трафика и всяких там TLS-inside-TLS. Но это еще не все. Кто сказал, что эти два подключения «туда» и «обратно» должны устанавливаться одинаковым образом и к одному и тому же адресу? XRay позволяет настроить их независимо. В итоге вы можете передавать данные «туда» через QUIC, а обратно получать через HTTPS. Или передавать данные «туда» по IPv6, а обратно получать их под IPv4. Или соединяться «туда» и «обратно» на разные IPv6-адреса. Можно даже вообще иметь два подключения к двум разным серверам у разных хостеров в разных странах. Можно слать данные в одну сторону напрямую, а в другую сторону через CDN. И естественно во всех этих случаях использовать разные домены. Короче, насколько хватит фантазии. Все это многократно усложняет анализ и блокировки.

    Несколько важных моментов:

    1. Вместе с XHTTP появился новый алгоритм мультиплексирования XMUX. Там ничего особо интересного, но и ничего сложного — интересующиеся могут перевести статью с гитхаба по ссылке выше автопереводчиком на английский, там все почти понятно

    2. XHTTP нельзя использовать с XTLS-Vision. Защита от детектирования tls-inside-tls обеспечивается за счет мультиплексирования (тот самый XMUX из предыдущего пункта) и разделения потоков «туда-обратно» (об этом чуть ниже)

    3. XHTTP можно использовать с XTLS-Reality

    4. XHTTP активно развивается, поэтому важно, чтобы версии XRay на клиенте и сервере были одинаковые — иначе могут быть странные глюки, либо вообще ничего не заработает

    5. Клиенты на базе Sing-box не умеют в XHTTP. На базе XRay — пожалуйста. v2raN и v2rayNG работают без проблем

    6. Пример конфигурации XHTTP для клиента и сервера XRay, а также для Nginx можно найти в репе xtls-examples: https://github.com/XTLS/Xray-examples/tree/main/VLESS-XHTTP3-Nginx

Вместо заключения

За последний год мы наблюдаем, что РКН, не справляясь с детектирование протоколов (которые можно детектировать, но для этого нужны мозги и деньги, и если деньги есть, то с мозгами, видимо, не очень), перешел на более топорные меры с более сильным побочным эффектом, которые мы могли иногда наблюдать в некоторых регионах: блокирование HTTPS в сторону популярных хостеров, блокирование TLS v1.3 к ним же, блокирование некоторых CDN, блокирование неопознанных протоколов, шейпинг SSH-подключений после превышения определенного объема переданных данных, и даже временное (от 15 минут до пары дней) усиление блокировок для конкретных абонентов, которые триггернули каие-либо эвристики ТСПУ.

Поэтому напрашивается вывод, что дальнейшая тактика борьбы с цензурой должна строиться не на выдумывании более навороченных протоколов и методов маскировки, а на использовании особенностей самих механизмов блокировок — по крайней мере так, чтобы их эксплуатация была все дороже и дороже, а делать их было все сложнее и сложнее. Например, сейчас в большинстве случаев детектирования и блокировки не применяются для трафика внутри страны. Напрашивается вариант, что первым пунктом назначения при подключении к прокси может быть какой-нибудь дешевый отечественный VPS, а уже с него трафик будет идти на прокси за границей. А если у хостера тоже окажется ТСПУ и он начнет зверствовать — вспоминаем про механизм reverse proxy, bridge, portals, про которые тоже рассказывал MiraclePtr — потому что трафик «в обратную сторону» обычно тоже не фильтруется, и его фильтрация потребует гораздо больше ресурсов. И кстати, раз в статье упомянуты CDN, то еще подсказочка: CDN не обязательно должны быть иностранные. Think about it.

Habrahabr.ru прочитано 40163 раза