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

Комментарии (6)


  1. Antania
    06.08.2024 18:56
    +2

    Большое спасибо за ваши статьи. Сохранил)


  1. 0mogol0
    06.08.2024 18:56
    +1

    Удобно для интеграции в системы мониторинга типа Munin, Zabbix или Prometheus.

    Настроить выдачу метрик и статистики я сумел, а вот прикрутить к Prometheus пока не получилось. Так как почему-то документацию для неё порезали и найти концов пока не получается.


    1. vsviridov
      06.08.2024 18:56

      Есть xray Prometheus exporter


      1. 0mogol0
        06.08.2024 18:56

        Есть xray Prometheus exporter

        Гугл даёт ссылку на Xray от JFrog, который не про VPN, а про сканирование артефактов на уязвимости.


        1. vsviridov
          06.08.2024 18:56
          +1

          Прошу прощения за введение в заблуждение... У меня v2ray-exporter


  1. kelevra
    06.08.2024 18:56

    Подскажите, можно ли отправлять клиента по каким-нибудь из признаков через определённый Outbound? Пока сделал в routing rules через поименное перечисление клиентов. Этот способ хоть и рабочий, но не нравится тем, что xray приходится перезапускать для добавления клиентов. Вообще хотелось бы всё-таки где-то на записи клиента видеть, через какой outbound он будет отправлен

    Моя схема – это пачка Outbound, которые подключаются к разным странам ProtonVPN по Wireguard. Через них я подключаюсь к банкам этих стран через их страну в ProtonVPN, что бы не смущать их лишний раз подключениями из РФ. Заодно к дешёвому турецкому аккаунту Spotify через Турцию, что бы не разлогинивало раз в две недели