В наше непростое время... Хотя, к чему все это? Все в курсе. Переходим к технической части.
Многие знают, что XRAY умеет получать запрос от клиента на один ip адрес, а отправлять ответ с другого ip адреса. Документации на этот счет в интернете крайне немного (ну или я не умею искать). Есть образцы базовых настроек в примерах на GitHub проекта XTLS и несколько упоминаний о существовании такой фишки в статьях на Хабре без подробностей реализации. Я же попробую описать здесь теорию и настройку разделения входящего и исходящего трафика подробно и с примерами.
Зачем все это нужно?
Теоретически, это усложняет поведенческий анализ трафика со стороны DPI. Паттерны ломаются и, в теории, это помогает обойти блокировки. Но это не точно.
Если такая фича существует, ее нужно запилить и посмотреть как все это работает на практике. Чисто из научного интереса.
На чем будем настраивать?
На сервере стоит Angie (версия 1.11.6) в качестве реверсивного прокси, за ним прячется панель 3x-ui (версия 3.4.0), которая управляет XRAY (версия 26.6.22). Будем исходить из этой конфигурации.
Можно ли реализовать разделение трафика без реверсивного прокси?
Все упирается в расшифровку двух разных потоков SSL в рамках одного входящего подключения в XRAY. Умеет он такое или нет, я информации не нашел. В настройках подключения есть возможность указать несколько SSL сертификатов, но нет возможности указать несколько SNI, так что возможно, это будет работать только для ip без доменных имен. Скажу честно, я не пробовал.
Важная деталь: у Вашего сервера обязательно должно быть два внешних ip адреса. Желательно из разных подсетей, хотя различие подсетей не играет никакой роли. Большинство хостеров раздает несколько ip на один VDS. У меня эта опция стоит 5 руб в день за каждый дополнительный адрес. Можно делать настройки напрямую с ip адресами, но, для красоты и наглядности, предлагаю к каждому ip привязать свой поддомен. У нас это будут upload.domain.com и download.domain.com. Привязка делается в настройках DNS зоны у регистратора доменов. Интересное наблюдение. Несмотря на то, что оба моих ip адреса на одном и том же VDS, выданы одним и тем же хостером и находятся физически в одном и том же датацентре, 2ip.ru показывает, что один ip адрес расположен в Москве, а второй в Новосибирске, что забавно.
Можно использовать разные VDS для разделения трафика. Физически это могут быть разные машины в разных дата-центрах в разных странах на разных континентах. Для этого нужно с проксировать весь входящий трафик с download сервера на upload сервер с помощью любого реверсивного прокси. На download сервере даже XRAY не нужен. О том как запилить такое проксирование есть ролик на замедленном Youtube на примере Caddy. Но тут есть несколько моментов.
Если оба сервера находятся внутри локальной сети в одном дата-центре, то это ничем не отличается от варианта два ip на одном VDS, а если нет разницы, зачем платить больше?
Если оба сервера находятся в разных дата-центрах, мы получаем дополнительные накладные расходы в виде задержек трафика между серверами без видимой целесообразности, ибо DPI ломается от различия ip адресов, а не от их географического расположения. Опять же, два сервера минимум в два раза дороже, чем один сервер с двумя ip адресами.
Поэтому из экономии будем рассматривать вариант один сервер - два ip.
Итак, погнали. Настраиваем Angie.
Создаем файл xray.conf в папке /etc/angie/http.d. Имя файла может быть любым. Расширение строго conf
xray.conf
server { listen x.x.x.1:443 ssl; server_name upload.domain.com; http2 on; ssl_certificate /etc/letsencrypt/live/upload.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/upload.domain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; resolver 1.1.1.1 8.8.8.8 valid=300s; resolver_timeout 5s; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets on; client_header_timeout 5m; keepalive_timeout 5m; location /api/v1/data/ { client_max_body_size 0; proxy_pass http://unix:/dev/shm/xrxhd.socket; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_buffering off; proxy_cache off; proxy_connect_timeout 60s; proxy_read_timeout 315s; proxy_send_timeout 5m; } } server { listen x.x.x.2:443 ssl; server_name download.domain.com; http2 on; ssl_certificate /etc/letsencrypt/live/download.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/download.domain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; resolver 1.1.1.1 8.8.8.8 valid=300s; resolver_timeout 5s; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets on; client_header_timeout 5m; keepalive_timeout 5m; location /api/v1/data/ { client_max_body_size 0; proxy_pass http://unix:/dev/shm/xrxhd.socket; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_buffering off; proxy_cache off; proxy_connect_timeout 60s; proxy_read_timeout 315s; proxy_send_timeout 5m; } }
Пояснения к настройкам:
Для NGINX настройки аналогичные.
Вместо x.x.x.1 и x.x.x.2 пишем внешние ip адреса вашего сервера. Если вы не привязывали доменные имена, поле server_name опускаете (вообще не пишете).
Сертификаты для доменов или ip адресов предварительно нужно получить самостоятельно у Let's Encript или кого угодно еще.
ssl_ciphers и add_header - не догма, пишите как считаете нужным.
Разделы location должны быть аналогичные для обоих ip адресов, включая путь /api/v1/data/ (любой, но одинаковый. И не забудьте слеш в конце) и файл сокета.
Если не хотите использовать сокет, для общения с XRAY, в proxy_pass можно прописать адрес и порт: 127.0.0.1:4443. Порт может быть любым свободным, он дальше будет использоваться при настройке XRAY.
Создаем входящее подключение для XRAY
Через панель 3x-ui: Входящие - Создать подключение.
Вкладка Основное:
Примечание: все что угодно. Это название подключения.
Протокол: vless
Адрес: /dev/shm/xrxhd.socket,0666. Здесь внимательно. Адрес сокета должен совпадать с адресом сокета в настройках реверсивного прокси. После запятой идут права доступа к файлу сокета, их лучше оставить как в примере. Если в настройках реверс прокси вы указывали 127.0.0.1:4443, то здесь пишем 127.0.0.1
Порт. Если используете сокет, ставите 0 или 1, если 127.0.0.1:4443, ставите 4443 (или какой указали в настройках реверсивного прокси).
Вкладка Поток:
Транспорт - XHTTP.
Путь: /api/v1/data - берем из секции location настроек реверсивного прокси. В этом случае без слеша в конце.
Режим: auto - это важно.
Остальное оставляем как есть.
Вкладка Безопасность: выбираем Нет. За расшифровку SSL у нас отвечает реверсивный прокси.
Вкладка Сниффинг: Включить, выбрать все что есть HTTP, TLS, QUIC, FAKEDNS.
Если выше не упомянуты какие-то поля настроек - оставляем их без изменений.
Дальше добавьте клиента в получившееся входящее подключение (раздел панели Клиенты - Добавить клиентов - Привязанные входящие).
В итоге получаем вот такой шаблон входящего подключения:
{ "listen": "/dev/shm/xrxhd.socket,0666", "port": 1, "protocol": "vless", "tag": "in-1-tcp", "settings": { "clients": [ { "id": "xxxxxxxxxxxxxxxx", "email": "xxxxx", "flow": "", "limitIp": 0, "totalGB": 0, "expiryTime": 0, "enable": true, "tgId": 0, "subId": "xxxxxx", "comment": "", "reset": 0, "created_at": 1756652179000, "updated_at": 1782274393000 } ], "decryption": "none", "encryption": "none" }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls", "quic", "fakedns" ] }, "streamSettings": { "network": "xhttp", "xhttpSettings": { "path": "/api/v1/data", "host": "", "mode": "auto", "xPaddingBytes": "100-1000", "scMaxEachPostBytes": "1000000", "scMaxBufferedPosts": 30, "scStreamUpServerSecs": "20-80" }, "security": "none" } }
На этом с настройками сервера все. Настройка фаервола, маршрутизации в XRAY и прочие настройки на сервере не относятся к делу, а значит выходят за рамки и без того скучной статьи. ИИ в помощь.
Для чистоты эксперимента проверять делится наш трафик или не делится будем на чистом XRAY без графических клиентов. К сторонним клиентам мы еще вернемся. Как известно, бинарник XRAY одновременно является и клиентом и сервером, поэтому качаем последнюю версию под свою платформу (Windows или Linux роли не играет) прямо с GitHub разработчика. Создаем файл конфигурации для клиента config.json.
Примерно такой
{ "log": { "access": "access.log", "error": "error.log", "loglevel": "debug", "dnsLog": true }, "inbounds": [ { "listen": "127.0.0.1", "port": 2080, "protocol": "socks", "settings": { "udp": true }, "tag": "socks-in" }, { "listen": "127.0.0.1", "port": 2081, "protocol": "http", "tag": "http-in" } ], "outbounds": [ { "protocol": "vless", "settings": { "vnext": [ { "address": "upload.domain.com", "port": 443, "users": [ { "id": "xxxxxxxxxxxxx", "security": "auto", "encryption": "none" } ] } ] }, "tag": "vless-out", "streamSettings": { "network": "xhttp", "security": "tls", "tlsSettings": { "allowInsecure": false, "serverName": "upload.domain.com", "alpn": [ "h2", "http/1.1" ], "fingerprint": "firefox" }, "xhttpSettings": { "path": "/api/v1/data", "host": "upload.domain.com", "mode": "auto", "xPaddingBytes": "100-1000", "downloadSettings": { "address": "download.domain.com", "port": 443, "network": "xhttp", "security": "tls", "tlsSettings": { "serverName": "download.domain.com", "alpn": [ "h2", "http/1.1" ], "fingerprint": "firefox" }, "xhttpSettings": { "path": "/api/v1/data", "host": "download.domain.com", "mode": "auto" } } } } } ] }
Что важно пояснить в конфигурации.
Во всех секциях, вне “downloadSettings” указываем домен upload.domain.com или ip адрес x.x.x.1 из настроек реверсивного прокси на сервере. Внутри “downloadSettings” соответственно download.domain.com или ip адрес x.x.x.2.
“mode”: “auto” - во всех случаях. Можно в разделе “xhttpSettings”: для исходящего домена upload.domain.com поэкспериментировать с “mode”: “stream-up” или “mode”: “packet-up”, но auto работает точно. “mode”: “stream-one” в нашем случае гарантированно работать не будет. Такова жизнь.
“loglevel”: “debug” - важно указать именно debug, так как нам нужно проверить разделение трафика, а не только ошибки.
Получившийся файл config.json кладем рядом с бинарником XRAY и запускаем из командной строки. Не забудьте сначала в командной строке перейти в папку, где лежит XRAY (cd ... и вот это вот все).
xray --config config.json
Дальше идет описание проверки из под Windows.
Заходим в настройки Windows -> Сеть и Интернет -> Прокси-сервер -> Настройка прокси вручную -> Настройка. Использовать прокси-сервер -> Вкл. IP адрес прокси-сервера 127.0.0.1. Порт 2081 берем из настроек файла клиента (раздел с “protocol”: “http”). Сохраняем, запускаем браузер, открываем 2ip.ru видим ip адрес сервера. Ну или не видим, но чаще видим. Если не видим, проверяем, что сделали не так.
Теперь открываем файл error.log. Он должен появиться в той же папке, что и бинарник XRAY. В этом файле важно найти строки:
transport/internet/splithttp: XHTTP is dialing to tcp:upload.domain.com:443, mode packet-up, HTTP version 2, host upload.domain.com transport/internet/splithttp: XHTTP is downloading from tcp:download.domain.com:443, mode stream-down, HTTP version 2, host download.domain.com
Должны быть обе строки. Могут идти не подряд, но обязательно должны быть обе. Если в логе есть только первая строка (XHTTP is dialing to tcp ...) - ничего не получилось и весь трафик идет через один ip. Идем в начало статьи, смотрим где накосячили с настройками.
Для тех кто в Linux можно проверить работоспособность нашей поделки через curl. XRAY предварительно должен быть запущен в качестве сервиса или в другом терминале. Номер порта берем из настроек файла клиента (раздел с “protocol”: “socks”).
curl --socks5 127.0.0.1:2080 https://google.com
Дальше, по аналогии с Windows, бежим в логи и ищем две заветные строчки.
Как можно проверить еще, ну вот чтобы вообще на 100%? На примере Windows.
Качаем и запускаем TCPView прямо с сайта Microsoft. В это время у нас уже запущен из командной строки XRAY и включен системный прокси в настройках Windows. В интерфейсе TCPView вверху в поле Search пишем xray, чтобы оставить отображение трафика только одного процеса. Открываем или обновляем в браузере любую страницу. В таблице ниже мы должны увидеть три ip адреса: 127.0.0.1, x.x.x.1 и x.x.x.2. Если видим только два: 127.0.0.1 и x.x.x.1, ничего не работает и день прожит зря. Но, надеюсь, это не про нас.
Что касается графических клиентов для XRAY. Финт с разделением потоков удалось провернуть только на клиенте V2RayN под Windows. Пробовал еще Exclave на Андроиде и Passwall2 на openWRT. В двух последних случаях настройки “downloadSettings” игнорировались и все шло в один поток. Во всех клиентах блок “downloadSettings” я добавлял в раздел "Дополнительные параметры XHTTP (Extra)" в настройках подключения. Просто вставлял блок в соответствующее поле:
"downloadSettings": { "address": "download.domain.com", "port": 443, "network": "xhttp", "security": "tls", "tlsSettings": { "serverName": "download.domain.com", "alpn": [ "h2", "http/1.1" ], "fingerprint": "firefox" }, "xhttpSettings": { "path": "/api/v1/data", "host": "download.domain.com", "mode": "auto" } }
В случае V2RayN это сработало, Exclave и Passwall2 просто проигнорировали эти настройки, хотя само соединение поднималось. Если у кото-то получится разделить трафик на Андроиде или openWRT, будет очень интересно почитать.
В заключении добавлю, что вся информация предоставлена исключительно в образовательных и научных целях. Ни в коем случае не используйте полученные знания для нарушения закона и доступа к богомерзким запрещенным ресурсам в сети интернет. Да прибудет с Вами сила. Всем бобра.
