Малоизвестные фичи XRay, о которых невозможно молчать

от автора

В этом посте я кратко поведаю о разных интересных возможностях XRay (клиент и сервер для протоколов VMess, VLESS, Trojan и других, в том числе с XTLS-Reality и XTLS-Vision), о которых, кажется, мало кто знает, но которые могут оказаться очень полезными.

Оглавление:

  1. Фрагментирование запросов

  2. QUIC-транспорт

  3. Мониторинг и автоматический выбор outbound’а

  4. Сбор статистики

  5. Browser dialer

Fragment

На фоне недавних событий (замедление Youtube Роскомнадзором), многие открыли для себя инструменты типа GoodbyeDPI и подобных. Они работают с использованием различных трюков при передаче данных по протоколу TCP, благодаря которым цензурирующее оборудование (так называемое ТСПУ) при обработке TLS-handshake оказывается сбитым с толку и не понимает, на какой именно сайт вы пытаетесь попасть (потому что не может прочитать параметр «SNI» при установке TLS-соединения), и в итоге блокировка/замедление не срабатывает. XRay тоже умеет подобное, там это называется «Fragment».

Простейший конфиг XRay для этого будет выглядеть примерно так:

локальный прокси с fragment
{   "inbounds": [     {       "listen": "127.0.0.1",       "port": 1080,       "protocol": "socks",       "tag": "socks"     }   ],   "outbounds": [     {       "tag": "fragment",       "protocol": "freedom",       "settings": {         "fragment": {           "packets": "tlshello",           "length": "100-200",           "interval": "10-20"         }       },       "streamSettings": {         "sockopt": {           "tcpNoDelay": true         }       }     }   ] }

Запустив XRay с таким конфигом и настроив браузер на использование SOCKS-прокси на локальном (127.0.0.1) порту 1080, XRay будет фрагментировать заголовок ClientHello протокола TLS. Доступные параметры:

"packets":может быть «1-3» для фрагментации на уровне TCP (первые 1-3 отправки данных от клиента к серверу) либо «tlshello» для фрагментации TLS handshake;

"length": на кусочки какого размера дробить отправляемые данные;

"interval": пауза между отправкой фрагментов в миллисекундах;

Конкретные требуемые значения параметров могут отличаться в зависимости от типа (и даже версии софта) используемого оборудования DPI у провайдера, поэтому возможно чтобы получить нужный эффект придется с ними поэкспериментировать.

Fragment можно также комбинировать с использованием прокси-протоколов, например VLESS и других, пример конфига есть на github.

QUIC-транспорт

Еще из того, о чем недавно говорили на фоне замедления Youtube — протокол QUIC. Это разработка Google, которая использует UDP вместо TCP при доступе к веб-серверам, нацеленная на уменьшение времени установки соединения и улучшение скорости доступа за счет более эффективной передачи данных. В случае с замедлением Youtube у некоторых пользователей включение QUIC в браузере помогло решить проблему (а у некоторых наоборот, выключение). Причин тут может быть несколько. Во-первых, есть основание предполагать, что определенное оборудование ТСПУ… не умеет нормально разбирать заголовки QUIC-протокола (и из-за этого одно время Роскомнадзор даже резал такие подключения). Во-вторых, в браузере Chrome разработчики намеренно добавили фрагментацию данных при установке соединения — они таким образом пытались заставить разработчиков веб-серверов полностью следовать стандарту протокола, и эта фрагментации дала очень полезный побочный эффект для обхода цензуры (см. предыдущую часть статьи). В третьих, QUIC очень эффективно работает при потерях пакетов, а оборудование РКН замедляет Youtube именно таким образом.

И XRay умеет использовать QUIC в качестве транспорта для своих протоколов (VLESS, VMess, Trojan и другие). Вы можете спросить, зачем использовать QUIC-транспорт, когда можно использовать VLESS безо всяких транспортов (поверх обычного TLS), отвечу — всегда полезно иметь запасной альтернативный вариант, к тому же QUIC в XRay можно использовать по-разному.

Вариант раз — в чистом виде. С QUIC, к сожалению, не получится сделать что-то типа XTLS-Reality, когда вы прикрываетесь чужим доменом. В теории это возможно, но пока что никто такое не реализовал. Поэтому понадобится свой домен и TLS-сертификат для него (подойдет даже бесплатный домен от dynu.com и сертификат от LetsEncrypt). Конфиг XRay для примера:

VLESS c QUIC-транспортом
{   "inbounds": [     {       "port": 443,       "protocol": "vless",       "tag": "quic",       "settings": {         "clients": [           {             "id": "4c3fe585-bb09-89df-b284-e2dada14150f",             "email": "user1"           }         ],         "decryption": "none"       },       "streamSettings": {         "network": "quic",         "quicSettings": {},         "security": "tls",         "tlsSettings": {           "certificates": [           {             "certificateFile": "/etc/letsencrypt/live/yourdomain/fullchain.pem",             "keyFile": "/etc/letsencrypt/live/yourdomain/privkey.pem"           }]         }       },       "sniffing": {         "enabled": true,         "destOverride": [           "quic",           "http",           "tls"         ]       }     }   ],   "outbounds": [     {       "protocol": "freedom",       "tag": "direct"     },     {       "protocol": "blackhole",       "tag": "block"     }   ] }

Потом в клиенте настраиваете VLESS-подключение с нужным UUID, вводите адрес (домен) вашего сервера, выбираете QUIC в качестве транспорта — и все работает. Такое подключение будет со стороны выглядеть как настоящий QUIC на 443 UDP порту, но, к сожалению, настроить fallback (чтобы при заходе на UDP/443 открывался фейковый веб-сайт) в XRay возможности нет.

Второй вариант — использовать обфусцированный QUIC. Домен и сертификат для этого уже не нужны (их все равно никто не увидит). Со стороны передача данных будет выглядить как «нечто непонятное по UDP», примерно как в случае с AmneziaWG.

VLESS + обфусцированный QUIC (что-то непонятное по UDP)
{   "log": {     "loglevel": "debug"   },   "inbounds": [     {       "port": 8443,       "protocol": "vless",       "tag": "quic",       "settings": {         "clients": [           {             "id": "4c3fe585-bb09-89df-b284-e2dada14150f",             "email": "user1"           }         ],         "decryption": "none"       },       "streamSettings": {         "network": "quic",         "quicSettings": {            "security": "aes-128-gcm",            "key": "hellohabr"         }       },       "sniffing": {         "enabled": true,         "destOverride": [           "quic",           "http",           "tls"         ]       }     }   ],   "outbounds": [     {       "protocol": "freedom",       "tag": "direct"     },     {       "protocol": "blackhole",       "tag": "block"     }   ] }

В данном случае используется шифр aes-128-gcm (другой возможный вариант — chacha20-poly1305) с ключом»hellohabr». Клиенты настраиваются аналогично предыдущему случаю, только надо отключить TLS, а вместо этого выбрать шифр и ключ.

И еще один вариант, близкий ко второму — замаскировать QUIC под DTLS (WebRTC, звонки в месседжерах), SRTP (FaceTime) или uTP (BitTorrent). Для этого нужно добавить параметр header:

...       "streamSettings": {         "network": "quic",         "quicSettings": {            "security": "aes-128-gcm",            "key": "hellohabr",            "header": {              "type": "dtls"            }         } ...

«type» может быть «srtp», «utp», «dtls», «wechat-video» и «wireguard». Не забудьте на клиенте выбрать то же самое.

Помните, я в своей статье «Надежный обход блокировок в 2024: протоколы, клиенты и настройка сервера от простого к сложному» (заблокирована на территории РФ, но доступна через иностранные VPN/прокси) советовал mKCP как запасной вариант, работающий по UDP? К сожалению, начиная с какой-то из версий Xray оно сломано и тупит при определенных сценариях — жрет память, жрет процессор и тормозит, вплоть до полной невозможности работы. Транспорт QUIC в XRay работает гораздо стабильнее, и обладает всеми теми же возможностями обфускации.

Недостатка два. Первый, как я уже сказал, когда вы маскируетесь под «чистый» QUIC, нельзя добавить маскировочный сайт. Второй — вся эта красота работает только с клиентами на базе XRay-core, а те что на базе Sing-box в пролете (точнее, sing-box не поддерживает обфусцированный QUIC, чистый в теории должен работать, но не заработал).

Если вам нужен прокси поверх QUIC с маскировкой под сайт или под «непонытно что» и работающий с Sing-box, используйте Hysteria2.

Selectors и observatory — мониторинг и автоматический выбор outbound’а

Некоторые используют XRay для построения цепочек прокси. Например, вы находясь в России подключаетесь сначала к прокси-серверу находящемуся в России, а уже с него куда-нибудь за бугор. XRay позволяет контролировать доступность вышестоящих прокси-серверов (если у вас их несколько) и балансировать запросы между ними. Фичи называются selectors и observatory. Документация здесь.

Расскажу про конфиг вкратце. На верхнем уровне вашего конфига добавляете объект «observatory»:

  "observatory": {     "subjectSelector": [ "outbound1", "outbound2" ],     "probeURL": "http://www.gstatic.com/generate_204",     "probeInterval": "300s",     "enableConcurrency": true   },

В списке «subjectSelector» перечисляете имена outbound’ов которые надо проверять, в «probeURL» задаете адрес для теста, в «probeInterval» периодичность.

А потом в объекте «routing» описываете объект «balancers», например так:

  "routing": {     "domainStrategy": "IPIfNonMatch",     "balancers": [       {         "tag": "mybalancer",         "selector": [ "outbound1", "outbound2" ],         "strategy": {           "type": "leastPing"         },         "fallbackTag": "outbound3"       },

В «selector» перечисляете outbound’ы, через которые можно подключаться «наружу», в fallbackTag можно указать outbound который XRay попытается использовать если все перечисленные выше окажутся недоступные (и он же будет использоваться сразу после старта пока еще не прошли проверки). И дальше вы можете использовать ваш «mybalancer» как обычный outbound — например указать его явно в правилах роутинга.

Сбор статистики

Можно получать в виде JSON статистику — кто из пользователей сколько скачал, по каким inbound’ам/outbound’ам, а если используете observables из предыдущего раздела — смотреть их доступность и время пинга. Удобно для интеграции в системы мониторинга типа Munin, Zabbix или Prometheus. Документация здесь: Метрики | Project X (xtls.github.io)

Browser dialer

Помните про TLS-fingerprint, он же отпечаток? У каждого браузера и каждой TLS-библиотеки он уникальный. В некоторых странах цензоры уже используют его для выявления подключений от прокси-клиентов, потому что у стандартной TLS-библиотеки языка Go он совсем не похож на отпечатки популярных браузеров. XRay может использовать uTLS — специально модифицированную библиотеку, которая умеет «прикидываться» браузерами, например, firefox и chrome, копируя их fingerprint’ы. Есть только проблема — если вы давно не обновляли клиент, fingerprint его может устареть, отставая от актуальных версий браузеров (в некоторых странах так блокировали Cloak, использовавший TLS fingerprint какой-то старой версии Firefox), а во-вторых, даже если фингерпринт похож, все равно какие-то нюансы поведения могут различаться, и цензоры рано или поздно могут вас на этом подловить.

Вы возможно слышали про naiveproxy, разработчику которого в погоне за максимально похожим на «настоящий» TLS fingerprint’ом пришла гениальная идея просто взять часть кода настоящего браузера Chromium и использовать его для установления соединения. У XRay есть идея не хуже — он может использовать настоящий браузер целиком 🙂 Работать оно будет только с websocket- или SplitHttp-транспортом, зато это прямо максимально аутентичная маскировка.

Использовать довольно просто. Конфигурируете XRay как обычно для вебсокетов или splithttp (можно создать подключение в Nekoray и экспортировать конфиг, чтобы проще было), а потом нужно запустить XRay с переменной окружения типа XRAY_BROWSER_DIALER=127.0.0.1:8080 . В Linux ее можно вставить сразу перед командой запуска xray, в Windows задать командой «set» перед запуском.

После этого открываете в браузере адрес http://127.0.0.1:8080 (выглядит оно как пустая страница), и XRay начинает использовать его как промежуточный пункт для соединения с удаленным прокси-сервером — вы можете увидеть в «Developer Tools -> Network» websocket-подключения парами, часть к локальному XRay, а часть к удаленному прокси-серверу.

Два важных нюанса: 1) в браузере, который вы используете как промежуточный транзит, не должно быть задано прокси в настройках (иначе запрос к удаленному прокси попадет снова на XRay, и получится бесконечный цикл); если вы используете TUN-интерфейс, то клиенты обычно делают исключение в маршрутах для адреса прокси назначения, но могут быть свои приколы. 2) количество одновременных вебсокет-подключений в браузере ограничено, поэтому рекомендуется использовать мультиплексирование (mux) в XRay. Между тем, ничто не запрещает открыть в браузере несколько вкладок, они будут использоваться для проксирования одновременно.

И наконец, не обязательно открывать окно браузера, Chrome можно запустить в headless mode (без видимого окна), например как-то так:

"c:\Program Files\Google\Chrome\Application\chrome.exe" --headless=new --remote-debugging-port=0   --no-proxy-server http://127.0.0.1:8080/

Здесь одной командой мы запускаем его в headless-режиме, отправляя сразу на локальный адрес XRay, отключаем использование прокси, и включаем remote debugging, чтобы можно было проверить если что-то вдруг пойдет не так.


ссылка на оригинал статьи https://habr.com/ru/articles/834290/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *