Статья опубликована под лицензией Creative Commons BY-NC-SA.

Эта статья — заключительная (наконец‑то!) из моего огромного цикла про недетектируемые инструменты для обхода блокировок. В предыдущих публикациях я упоминал, что клиенты и серверы XRay (форк V2Ray) и Sing‑box при использовании протоколов VLESS/VMess/Trojan могут работать через веб‑сокеты и gRPC, что позволяет подключаться к даже заблокированным Роскомнадзором прокси‑серверам через CDN (content delivery или content distribution network) и дает дополнительные преимущества. Сегодня мы поговорим об этом поподробнее.

Для чего?

  1. Если ваш прокси‑сервер попал под ковровую блокировку или стал недоступен по еще какой‑то причине, вы по‑прежнему можете достучаться до него через CDN. Вероятность блокировки целого Cloudflare или Gcore CDN гораздо ниже, потому что на них сидит чуть ли не половина всех сайтов Интернета. Даже в Туркменистане, известном своими драконовскими мерами, до недавнего времени люди умудрялись находить незабаненные адреса балансировщиков CF.

  2. Cloudflare умеет проксировать IPv4-запросы на IPv6-адреса. Таким образом, для того, чтобы запустить свой прокси, достаточно купить копеечный IPv6-only‑сервер (с выходом в IPv4-сеть через NAT), который можно найти меньше чем за доллар в месяц.

  3. Проксирование через веб‑сокеты может оказаться эффективным для пробивания через строгие корпоративные системы, которые анализируют весь передаваемый трафик с man‑in‑the‑middle расшифровкой с подменой сертификата.

Нейрокартинка для отвлечения внимания
Нейрокартинка для отвлечения внимания

Протоколы

Первый, самый простой и самый старый протокол — Websocket. Идея простая — клиент отправляет серверу HTTP‑запрос с просьбой переключить подключение в режим веб‑сокетов, и если сервер не возражает, то HTTP‑подключение становится обычной «трубой», по которой можно слать любые данные туда‑сюда. Формат и порядок передаваемых данных стандартом не регламентирован и может быть любой, поэтому CDN в них не вмешивается, а просто пересылает данные с сервера к клиенту и обратно — самое то, для того чтобы использовать подключение как прокси.

Недостатком использования веб‑сокетов является более долгое время установления подключения (кроме TLS‑хендшейка еще должен пройти вебсокет‑хендшейк), и также тот факт, что при большом желании вебсокет‑хендшейк можно детектировать по передавамым объемам данных в начале каждого соединения.

Разработчики проксей придумали решение этой проблемы под названием «early data». Суть его в том, что вместо того, чтобы сначала попросить сервер перейти в режим websockets, а потом слать запросы на прокси, websocket‑хендшейк уже будет содержать какую‑то часть данных, которую мы отправляем на прокси‑сервер — это и сокращает время установления соединения, и рандомизирует размеры пакетов, усложняя детектирование. Если вы используете клиент на базе XRay, то для использования early data нужно добавить «?ed=XXX» в конец пути вебсокет‑адреса, где XXX — максимально допустимый размер данных, которые могут содержаться в первом запросе (в байтах). У меня без проблем работало с "?ed=2048", при каких‑либо ошибках можно попробовать уменьшить значение. XRay всегда использует для этих данных заголовок «Sec‑Websocket‑Protocol», Sing‑box же позволяет использовать любой заголовок, поэтому если вы подключаетесь клиентом на базе Sing‑Box (например Nekobox) к серверу на базе XRay, то нужно явно указывать имя хедера «Sec‑Websocket‑Protocol» в настройках подключения — чуть позже увидите сами.

Другой протокол — это gRPC. Это протокол для межпроцессного и межсервисного взаимодействия от Google, который в качестве транспорта тоже использует HTTP. Он поддерживается не всеми CDN (об этом чуть позже), зато его использование сложнее детектировать, а еще с его помощью можно организовать мультиплексирование (использовать одно и то же TCP‑подключение для множества сессий с прокси). Где‑то тут в комментариях писали, что gRPC более производителен, чем веб‑сокеты, автор Sing‑box наоборот жалуется, что у gRPC‑клиента «poor performance», я же особой разницы не заметил.

CDN

По идее, можно использовать любые CDN, которые поддерживают проксирование websocket и/или gRPC. Среди популярных CDN, которые умеют такое на бесплатных тарифах, известны Cloudflare и Gcore. Расскажу о них по‑подробнее.

Cloudflare — наверное, самая крупная и известная сеть доставки контента в мире (хотя, может быть Akamai и больше, не проверял). На бесплатном тарифе поддерживает как websocket'ы, так и gRPC. Про веб‑сокеты в хелпе сказано, что если вы будете гонять через них очень‑очень‑много данных на бесплатном тарифе, то CF может связаться с вами и попросить начать платить. Я пробовал гонять много данных, пока не попросили. Про gRPC такого требования нет. Еще одна приятная особенность Cloudflare, как я уже говорил выше — это то, что можно иметь сервер, обладающий только IPv6-адресом, и CF будет принимать IPv4-подключения и перенаправлять их на IPv6-адрес.

Одно но — чтобы гонять через нее трафик, нужно, чтобы у вас был домен, и чтобы этот домен был делегирован на ее нейм‑сервера (NS). Регистрируемся в Cloudflare, добавляем там свой домен — CF скажет вам, на какие именно NS его надо делегировать, и это нужно сделать (если не знаете как, запросите инструкции у вашего регистратора доменов или хостинг‑провайдера). Либо же можно сразу купить домен у Cloudflare, цены у них нормальные, но платить, понятное дело, можно только с иностранных банковских карт.

Дальше всё просто:

Идем в DNS → Records, нажимаем «Add record», и добавляетм запись типа A (если у вас IPv4-адрес) или AAAA (если у вас IPv6), указав в Name поддомен или @ для корневого домена, IP‑адрес, и не забыв отметить галочку «Proxied»:

Также нужно не забыть зайти в настройки "Network" для вашего домена в панели CF, и убедиться, что все три самые важные галочки включены:

Конечному клиенту (браузеру или прокси) Cloudflare демонстрирует свой TLS‑сертификат. Подключение между серверами Cloudflare и вашим сервером по‑хорошему тоже должно быть защищено TLS — для этого не обязательно запрашивать домен через Let's Encrypt, можно использовать самоподписанный сертификат (инструкция будет дальше), либо же сгенерировать «внутренний» сертификат от Cloudflare — он подписан другой цепочкой, поэтому в браузере работать нормально не будет, но для связи между балансировщиками CF и вашим хостом подойдет идеально. Настраивается это в разделе SSL/TLS → Overview: режим Full будет работать с самоподписанным сертификатов, а режим Full (Strict) будет требовать наличие «внутреннего» сертификата Cloudflare на вашем сервере:

как сгенерировать "внутренний" сертификат

Идем в SSL/TLS → Origin server. Нажимаем там Create Certificate

Выбираем домены, для которых нужно сгенерить сертификат, нажимаем волшебную кнопочку Create:

И сохраняем полученное содержимое в два файла для дальнейшего использования.

Дальше у нас по списку идет Gcore. Масштабы у них не такие огромные, как у Cloudflare, поддерживаются только веб‑сокеты, gRPC нет, IPv4-to‑IPv6 тоже нет. Но у gCore есть огромное преимущество — для работы через него не обязательно делегировать на него домен, достаточно просто CNAME‑записи — в теории, можно использовать даже DynDNS‑сервисы с бесплатными доменами, которые позволяют указывать CNAME.

Настраивается все следущим образом. Регистрируетесь в Gcore (Gcore Edge Solutions / Gcore Platform), выбираете бесплатный тариф. В панели выбираете слева «CDN», и нажимаете «Create CDN Resource»:

А дальше надо быть внимательным. Предлагаются два варианта: accelerate entire website, и accelerate only static content. Первый вариант, как и в случае с Cloudflare, требует делегирования вашего домена на неймсервера CDN. Поэтомы мы выбираем второй вариант, а именно, accelerate only static content, хоть это и немного контринтуитивно (веб-сокеты на static content все-таки мало тянут, не правда ли?):


Нажимаем Confirm, идем на следущую страницу, и начинаем заполнять:

Origin source — тут нужно ввести IP‑адрес вашего сервера с префиксом https://, например «https://12.34.56.78». Gcore не умеет проксировать IPv6 на IPv4 (у меня отказалась, по крайней мере), поэтому тут нужен уже IPv4-адрес.

Custom domain — тут укажите ваш домен, который вы будете использовать. Не забудьте включить галочку «Enable HTTPS» и выбрать «Get free Let's Encrypt certificate». Нажимаем Confirm чтобы идти дальше. После этого Gcore скажет вам, какое именно значение надо прописать в поле CNAME для вашего домена — это будет какой‑то адрес, скорее всего заканчивающийся на *.gcdn.co:

На следущей странице Gcore попытается нам помочь настроить движок веб‑сайта, выбираем I don't have CMS и идем дальше:

В самом конце не забываем включить поддержку Websocket'ов:

Ииии... готово!
После создания ресурса, нужно еще поменять режим на HTTPS-only:

Настройка серверов и клиентов

Если вы читаете эту статью, то вероятно настраивали сервер XRay по одному из моих мануалов: Обход блокировок: настройка сервера XRay для Shadowsocks-2022 и VLESS с XTLS‑Vision, Websockets и фейковым веб‑сайтом, Bleeding‑edge обход блокировок с полной маскировкой: настраиваем сервер и клиент XRay с XTLS‑Reality быстро и просто, 3X‑UI: Shadowsocks-2022 & XRay (XTLS) сервер с простой настройкой и приятным интерфейсом.

В первом случае, у вас уже настроен XRay‑сервер, который принимает подключения на 443 порт по TLS, у него есть сертификаты, и при этом не используется XTLS‑Reality, домен только свой. Во втором случае используется XTLS‑Reality, то есть сервер маскируется под какой‑то популярный сайт, принимая подключения с SNI его домена, и отдавая его подлинный TLS‑сертификат. В третьем случае возможно и то и то, смотря как настраивали:)

А если вы планируете использовать Cloudflare, и у вашего сервера есть IPv6-адрес, то возможно вообще настроить websocket/gRPC, не трогая основную инсталляцию и не меняя ничего не ней.

И сейчас мы разберем, что же нужно сделать, чтобы иметь возможность работать через CDN и websockets/gRPC для всех этих вариантов.

Во всех случаях нам понадобится установленный на сервер Nginx. Поскольку суть проксирования через CDN — в маскировке под легитимный HTTPS‑трафик, то нам нужен будет веб‑сервер, чтобы хостить какой‑нибудь безобидный сайтик. Плюс к этому, почему‑то в XRay нельзя задать gRPC‑транспорт как fallback, и здесь нам тоже поможет Nginx. Для работы на одном сервере и WS/gRPC, и XTLS‑Reality нужен будет SNI‑прокси, и Nginx тоже умеет работать в этом режиме. Поэтому устанавливаем Nginx.

Обратите внимание, если у вас на сервере стоит Debian или Ubuntu, то нужно устанавливать не просто пакет nginx, а nginx-full, потому что нам потребуются специфические модули Nginx, которые не входят в стандартную поставку (как оно в других дистрибутивах — не знаю, напишите в комментарии).

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

openssl req -x509 -newkey rsa:4096 -nodes -sha256 -keyout /etc/ssl/private/ssl-cert-snakeoil.key -out /etc/ssl/certs/ssl-cert-snakeoil.pem -days 3650 -subj "/CN=YOUR_DOMAIN_GOES HERE"

Запомните пути к файлам, они вам потом пригодятся.

Далее, для всех трех вариантов нужно будет добавить websocket- и grpc-inbound'ы в конфиг XRay, если их там еще нет. Для всех трех вариантов они будут выглядеть одинаково:

{
        "listen": "127.0.0.1",
        "port": 8888,
        "protocol": "vless",
        "tag": "grpc",
        "settings": {
          "clients": [
            {
              "id": "_UUID_вашего_пользователя"
            }
          ],
          "decryption": "none"
        },
        "streamSettings": {
          "network": "grpc",
          "grpcSettings": {
            "serviceName": "TestChatGRPC"
          }
        }
      },
      {
        "listen": "127.0.0.1",
        "port": 8889,
        "protocol": "vless",
        "tag": "ws",
        "settings": {
          "clients": [
            {
              "id": "_UUID_вашего_пользователя"
            }
          ],
          "decryption": "none"
        },
        "streamSettings": {
          "network": "ws",
          "wsSettings": {
            "path": "TestChatWS"
          }
        }
      },

«TestChatGRPC» и «TestChatWS» должны совпадать с секретными URL'ами, которые мы потом внесем в конфиг Nginx. Лучше не использовать урлы из примера, а придумать свои. Номера портов 8888 и 8889 — тоже должны совпадать с портами, на которые проксирует Nginx (см. дальше).

Если вы используете панель X‑UI или 3X‑UI, то там все аналогично — нужно создать новые inbounds, выбрать тип транспорта grpc или websocket, указать IP‑адрес для входящих подключений 127.0.0.1, соответствующие порты и URL'ы.
Websocket/gRPC на отдельном IPv6-адресе.

Обратите внимание: при подключении через Nginx или CDN, нельзя использовать flow «xtls‑rprx‑vision». Работать не будет.

Приводим конфиг Nginx (например, в /etc/nginx/sites‑enabled/default) к такому виду:

server {
	listen [_тут_ваш_IPv6_адрес]:443 ssl ipv6only=on http2 so_keepalive=on;

    server_name your_domain.com;

    # сюда можно положить какие-нибудь странички фейкового сайта, или использовать proxy_pass чтобы переадресовать запрос на другой сервер
    index index.html;
	root /var/www/html;


    # путь к вашим сертификатам, самоподписанным либо от Cloudflare
	ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
	ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

	
	client_header_timeout 52w;
    keepalive_timeout 52w;
	# замените TestChatGRPC на какую-нибудь секретную строку
    location /TestChatGRPC {
		if ($content_type !~ "application/grpc") {
			return 404;
		}
		client_max_body_size 0;
		client_body_buffer_size 512k;
		grpc_set_header X-Real-IP $remote_addr;
		client_body_timeout 52w;
		grpc_read_timeout 52w;
		grpc_pass grpc://127.0.0.1:8888;
	}

    # аналогично замените TestChatWS на какую-нибудь другую секретную строку
    location /TestChatWS {
		if ($http_upgrade != "websocket") {
			return 404;
		}
		proxy_pass http://127.0.0.1:8889;
		proxy_redirect off;
	    proxy_http_version 1.1;
	    proxy_set_header Upgrade $http_upgrade;
	    proxy_set_header Connection "upgrade";
	    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_read_timeout 52w;
	}
}

Смотрите комментарии к приведенному конфигу — нужно будет указать IPv6-адрес вашего сервера, домен, путь к сертификатам.

Дальше, нужно поменять настройки XRay так, чтобы он прекратил слушать на всех IPv4 и IPv6-адресах, и начал слушать только на одном IPv4-адресе. В конфиге XRay для вашего VLESS‑inbound на 443 порту, добавьте поле "listen": "127.0.0.1", либо измените его, если оно уже есть. Обратите внимание, что нельзя указывать там «0.0.0.0», пытаясь заставить XRay слушать на всех только IPv4-адресах — он толкует это значение своеобразно и слушает на IPv6 тоже.

Проверяем конфиг Nginx командой «nginx ‑t», если есть ошибки — исправляем, если ошибок нет, то перезапускаем сначала XRay (systemctl restart xray если вы ставили по моим инструкциям), и потом Nginx (systemctl restart nginx). Настройка сервера закончена, можно переходить к настройке клиента (будет описана дальше).

Websocket/gRPC на одном адресе с VLESS XRay на 443 порту без XTLS-Reality

Конфигурация XRay или X‑UI/3X‑UI для этого варианта полностью аналогична предыдущему пункту, только с небольшим дополнением. Для основного VLESS‑inbound необходимо задать fallback, если он не задан, например, на 127.0.0.1:8080. В JSON‑конфиге нужно добавить в секцию «settings» этого inbound'а такое:

"fallbacks": [
               {
                 "dest": 8080
               }
             ]

(внимательно с форматированием, если вы добавили новый параметр в конец секции, предыдущий, уже существовавший, должен иметь запятую в конце, т.к. он более не последний элемент структуры).

В интерфейсе X‑UI/3X‑UI тоже есть опции для задания фоллбэков. Фоллбэк должен быть только один, и URL задавать не надо — мы по умолчанию переадресуем абсолютно все не прощедшие VLESS‑аутентификацию подключения на Nginx.

Далее, приводим тот же конфиг Nginx (например, /etc/nginx/sites‑enabled/default) к такому виду — очень похоже на предыдущий пункт, но есть несколько различий:

server {
	listen 127.0.0.1:8080 so_keepalive=on;

    # тут ваш домен
    server_name your_server_name.com

    # сюда накидать каких-нибудь страничек
	index index.html;
	root /var/www/html;
	
	client_header_timeout 52w;
    keepalive_timeout 52w;
	location /TestChatGRPC {
		if ($content_type !~ "application/grpc") {
			return 404;
		}
		client_max_body_size 0;
		client_body_buffer_size 512k;
		grpc_set_header X-Real-IP $remote_addr;
		client_body_timeout 52w;
		grpc_read_timeout 52w;
		grpc_pass grpc://127.0.0.1:8888;
	}

    location /TestChatWS {
		if ($http_upgrade != "websocket") {
			return 404;
		}
		proxy_pass http://127.0.0.1:8889;
		proxy_redirect off;
	    proxy_http_version 1.1;
	    proxy_set_header Upgrade $http_upgrade;
	    proxy_set_header Connection "upgrade";
	    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_read_timeout 52w;
	}
}

Основное отличие — мы слушаем на локалхосте на 8080 порту, и не используем SSL — TLS‑подключение терминируется силами XRay, и в nginx мы получаем уже дешифрованные данные.

Как это работает: входящие подключения от клиентов попадают на XRay, который устанавливает TLS‑соединение. Если клиент аутентифицировал себя как клиент для протокола VLESS «без ничего», то он работает с прокси напрямую. Если нет (например, это браузер, или мы работаем через WS/gRPC) — подключение передается на Nginx, где в зависимости от URL клиенту отдается либо фейковый сайт, либо подключение снова отправляется на XRay, но уже на websocket‑ или grpc‑inbound.

Проверяем конфиг Nginx командой «nginx ‑t», если есть ошибки — исправляем, если ошибок нет, то перезапускаем сначала XRay (systemctl restart xray если вы ставили по моим инструкциям), и потом Nginx (systemctl restart nginx). Настройка сервера закончена, можно переходить к настройке клиента (будет описана дальше).

Websocket/gRPC вместе с XTLS-Reality

Как вы уже знаете из предыдущих статей, суть XTLS‑Reality в том, что прокси‑сервер выдает себя за веб‑сервер какого‑нибудь популярного сайта, переадресовывая все подключения, не прошедшие проверку «свой‑чужой» на него. Поэтому просто так использовать Websocket или gRPC не получится, это ломает всю идею XTLS‑Reality. Но можно использовать хак с SNI‑прокси. Обратите внимание: если у вас на сервере настроен XTLS‑Reality, то через Websocket/gRPC подключаться к нему нужно только через CDN! Иначе для сторонних наблюдаетелей будет немного подозрительно, что на одном и том же IP‑адресе висит сразу и какой‑нибудь microsoft.com, и ваш маленький фейковый никому неизвестный веб‑сайтик.

В первую очередь, редактируем ваш конфиг XRay, сделаем так, чтобы его VLESS/XTLS‑Vision inbound слушал на локалхосте на порту 8443:

"listen": "127.0.0.1",
"port": 8443

Если вы используете X-UI или 3X-UI, там это точно также меняется в настройках inbound'ов.

Далее, настроим Nginx. Конфиг сайта по умолчанию будет похожий на предыдущие варианты, но с небольшими отличиями:

server {
	listen 127.0.0.1:8444 http2 so_keepalive=on;

    # ваш домен
    server_name your_server_domain;

    # сюда накидайте страничек
	index index.html;
	root /var/www/html;


    # путь к сертификатам
	ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
	ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

	
	client_header_timeout 52w;
    keepalive_timeout 52w;
	location /TestChatGRPC {
		if ($content_type !~ "application/grpc") {
			return 404;
		}
		client_max_body_size 0;
		client_body_buffer_size 512k;
		grpc_set_header X-Real-IP $remote_addr;
		client_body_timeout 52w;
		grpc_read_timeout 52w;
		grpc_pass grpc://127.0.0.1:8888;
	}

    location /TestChatWS {
		if ($http_upgrade != "websocket") {
			return 404;
		}
		proxy_pass http://127.0.0.1:8889;
		proxy_redirect off;
	    proxy_http_version 1.1;
	    proxy_set_header Upgrade $http_upgrade;
	    proxy_set_header Connection "upgrade";
	    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_read_timeout 52w;
	}
}

И потом нам надо будет настроить непосредственно SNI proxy, для этого можно использовать тоже Nginx. Одно но — конфиги сайтов из /etc/nginx/sites‑enabled обычно инклудятся в секцию «http» конфига Nginx, а нам нужно настроить секцию «stream», поэтому можно добавить ее прямо в /etc/nginx/nginx.conf:

stream {
  map $ssl_preread_server_name $backend {
      www.microsoft.com        reality;
      your_domain_name         local;
      default                  reality;
  }

  upstream reality {
      server 127.0.0.1:8443;
  }

  upstream local {
      server 127.0.0.1:8444;
  }

  server {
      listen          443 reuseport so_keepalive=on;
      ssl_preread     on;
      proxy_pass      $backend;
  }
}

Тут все просто — сначала идет домен, под который вы маскируетесь с XTLS‑Reality (например, www.microsoft.com), потом идет ваш домен. Подключения c SNI вашего домена Nginx перенаправит на 8444 порт (где обработает его как веб‑сайт, или переадресуется на websocket/grpc‑inbound'ы), а все остальное, включая фейковый домен XTLS‑Reality — на 8443 порт, где слушает XRay.

Проверяем конфиг Nginx командой «nginx ‑t», если есть ошибки — исправляем, если ошибок нет, то перезапускаем сначала XRay (systemctl restart xray если вы ставили по моим инструкциям), и потом Nginx (systemctl restart nginx). Настройка сервера закончена, можно переходить к настройке клиента.

Настройка клиентов

Одинакова для всех трех пунктов. Я просто приведу скриншоты Nekobox, для других клиентов настраивать по аналогии.

Для Websocket:

Для gRPC:

И, понятное дело, значения «Path» должны совпадать с секретными URL'ами, которые вы задали в конфигах Nginx и XRay.

Fair use

Понятное дело, что то, что CDN разрешают на своих бесплатных тарифах проксировать Websockets и gRPC — это такой жест доброй воли от них. Давайте не наглеть и использовать эти возможности только в совсем безвыходных случаях, которые, надеюсь, все‑таки не наступят.

И в заключение

Судя по ныне обсуждаемому законопроекту, запрещающему распространение информации о средствах обхода блокировок, подобному контенту на Хабре жить осталось недолго. Чтобы не потерять — сохраняйте локально копии этой и других статей из цикла и делитесь ими с друзьями и коллегами.

А если есть желание сказать автору спасибо за все его труды — то BTC bc1q6mtfkxj0grqse8cefc4zgw4n9wckpvh5kp3h69

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


  1. MiraclePtr Автор
    19.09.2023 09:35
    +4

    Мне тут пришла в голову еще одна мысль - Nginx не умеет различать HTTP/1.1 и HTTP2 без TLS ALPN. Поэтому по-хорошему, для варианта, когда у вас XRay слушает на 443 порту и терминирует TLS-сессию (без XTLS-Reality и без отдельного IPv6), стоит сделать два fallback'а:

    "fallbacks": [
                   {
                     "alpn": "h2",
                     "dest": "8081"
                   },
                   {
                     "dest": "8080"
                   }
                 ]
    

    и в Nginx в описании сервера должно быть две listen-директивы: llisten 127.0.0.1:8080 so_keepalive=on; listen 127.0.0.1:8081 http2 so_keepalive=on;

    Тогда сервер будет корректно отвечать и на HTTP/2-запросы.


  1. karavan_750
    19.09.2023 09:35

    если у вас на сервере стоит Debian или Ubuntu, то нужно устанавливать не просто пакет nginx, а nginx-full, потому что нам потребуются специфические модули Nginx, которые не входят в стандартную поставку

    Если подключена репа от разработчиков, то годится пакет nginx.


  1. titanrain
    19.09.2023 09:35

    Сначала спасибо за серию статей. Очень помогли. Всё поставилось и работает.

    Возник вопрос есть ли простой способ настроить subscription на правила для клиента? Например панель hiddify после сканирования qr-кода для подписки в Shadowrocket в разделе Config добавляет конфиг и можно его обновлять. Но там в панели не реализовано редактирование правил.

    Хочется такое для знакомых, которые не поймут как на клиенте добавлять заумные правила.


    1. MiraclePtr Автор
      19.09.2023 09:35

      Возник вопрос есть ли простой способ настроить subscription на правила для клиента

      Увы, но нет. Насколько я знаю, пока что не существует механизма подписки на правила.


      1. titanrain
        19.09.2023 09:35

        Жаль что нет чего-то простого и автоматизированного.

        Нашел пример как это реализовать: https://mishatugushev.ru/blog/?go=all/shadowrocket-ios-wireguard/. Правда не понял пока автоматически правила обновляются или нет.

        Сделал себе что-то похожее.


  1. awaydownwego
    19.09.2023 09:35
    +1

    иногда кажется что проще (нет) переместить себя за пределы цензуры чем насроить всё енто дело


    1. MiraclePtr Автор
      19.09.2023 09:35
      +3

      Если все это слишком сложно - то советую Amnezia VPN, он устанавливается на любой сервер двумя кликами в понятном интерфейсе, есть клиенты под все платформы, и они тоже работают над защитой от выявления и блокирования протоколов.

      Но совет насчёт перемещения себя очень правильный.


  1. sawertem
    19.09.2023 09:35

    А для sing-box какие конфиги должны быть ?


    1. MiraclePtr Автор
      19.09.2023 09:35

      Для sing-box то же самое, только формат отличается немного.

      Как-то так
      {
            "tag": "vless-ws",
            "type": "vless",
            "listen": "127.0.0.1",
            "listen_port": 8889,
            "transport": {
              "type": "ws",
              "path": "/TestChatWS"
            },
            "users": [
              {
                "name": "test",
                "uuid": "xxx"
              }
            ]
          },
          {
            "tag": "vless-grpc",
            "type": "vless",
            "listen": "127.0.0.1",
            "listen_port": 8888,
            "transport": {
              "type": "grpc",
              "service_name": "TestChatGRPC",
              "idle_timeout": "15s",
              "ping_timeout": "15s",
              "permit_without_stream": false
            },
            "users": [
              {
                "name": "test",
                "alterId": 0,
                "uuid": "xxx"
              }
            ]
          }
      


  1. MiraclePtr Автор
    19.09.2023 09:35
    +4

    Мне тут пришла в голову еще одна мысль - Nginx не умеет различать HTTP/1.1 и HTTP2 без TLS ALPN. Поэтому по-хорошему, для варианта, когда у вас XRay слушает на 443 порту и терминирует TLS-сессию (без XTLS-Reality и без отдельного IPv6), стоит сделать два fallback'а:

    "fallbacks": [
                   {
                     "alpn": "h2",
                     "dest": "8081"
                   },
                   {
                     "dest": "8080"
                   }
                 ]
    

    и в Nginx в описании сервера должно быть две listen-директивы: llisten 127.0.0.1:8080 so_keepalive=on; listen 127.0.0.1:8081 http2 so_keepalive=on;

    Тогда сервер будет корректно отвечать и на HTTP/2-запросы.


  1. sawertem
    19.09.2023 09:35
    +1

    Насколько использование cdnа подрезает скорость ?


    1. MiraclePtr Автор
      19.09.2023 09:35
      +1

      У меня 30-40 мегабит выдавало без проблем (подключался через телефон, возможно по кабелю выдало бы и больше). Опять же, нужно иметь в виду, что это именно что backup plan, не для каждодневного использования - уже не важно, насколько быстро, там бы хоть что-то работало без блокировок.


  1. freeExec
    19.09.2023 09:35

    Теперь это надо выкладывать в виде PFD чтобы удобно было сохранять до прихода надзора.


  1. Lurn
    19.09.2023 09:35

    Два вопроса по поводу Nekobox:


    1. Как открыть/пробросить порт? Так и не удалось разобраться.
    2. При каждом включении режима "TUN" (он же "VPN") программа подряд трижды (!) требует ввести пароль админа — для установки DNS, доменов и маршрутизации. Дико раздражает делать это каждый раз при включении/переключении серверов. Как отключить требование пароля? Речь о версии под Linux.


    1. MiraclePtr Автор
      19.09.2023 09:35

      Как открыть/пробросить порт?

      Что конкретно имеется в виду? Функционал reverse proxy? В Sing-box его вообще нету, и поэтому в интерфейсе Nekobox настроек для него тоже нет. В XRay (Nekobox теперь умеет его использовать как ядро), в теории можно настроить через Nekobox кастомные JSON-поля для клиента, но там все настолько по-наркомански замудрено, что без бутылки не разобраться, и кажется оно требуется настройки сразу и со стороны клиента, и со стороны сервера.

       Как отключить требование пароля? Речь о версии под Linux.

      TUN-режим требует поднятия нового сетевого интерфейса и установки маршрутов, для этого нужны рутовые права. Как решение - запускать Nekobox сразу от имени рута, тогда спрашивать не должен.


      1. Lurn
        19.09.2023 09:35

        Что конкретно имеется в виду?

        Имеется ввиду следующее. Некоторые программы требуют для внешних соединений открытый порт (port forwarding). Обычно это настраивается на роутере, в случае VPN — в панели управления VPN. А вот где это настраивается в Nekobox я не могу понять. Грубо говоря, мне надо, чтобы на сайте проверки открытости порта вроде portchecker.co для соответствующего порта было написано "открыто".


        Как решение — запускать Nekobox сразу от имени рута, тогда спрашивать не должен.

        А как это настроить? У меня Nekobox запускается автоматически вместе с системой.


  1. sawertem
    19.09.2023 09:35

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


    1. MiraclePtr Автор
      19.09.2023 09:35

      Tun создает устройство на клиенте, но все пакеты, которые попадают на него, заворачиваются на прокси. Shadowsocks, VMess, VLESS, Trojan поддерживают только обычные TCP и UDP в одну сторону. Поэтому клиенты друг друга не видят вообще, пинговать по ICMP не получится вообще (только UDP-пинг, если повезет), пробразывать порты в обратную сторону тоже очень сложно.


      1. sawertem
        19.09.2023 09:35

        какая тогда практическая польза tun мода, если никакой общей сети создаётся?


        1. MiraclePtr Автор
          19.09.2023 09:35
          +1

          Заворачивание на прокси трафика от приложений, которые не умеют или не хотят работать через прокси.


          1. sawertem
            19.09.2023 09:35

            А если использовать системный прокси, тоесть весь трафик передавать, эти приложения тоже не будут работать ?


            1. MiraclePtr Автор
              19.09.2023 09:35

              Да, такое часто бывает. "Системный прокси" устанавливает настройку в системе, а вот использовать эту настройку или нет - это уже дело самого приложения. Приличные программы эту настройку уважают и используют (например браузеры), но многие вообще не умеют подключаться через прокси. Для них и спасает Tun-режим.


              1. sawertem
                19.09.2023 09:35

                Спасибо за разъяснение


  1. olegtsss
    19.09.2023 09:35

    Как думаете, блокировки коснутся ipv6?


    1. MiraclePtr Автор
      19.09.2023 09:35

      Уже.


      1. olegtsss
        19.09.2023 09:35

        Серьезно взялись.


  1. LuigiVampa
    19.09.2023 09:35

    Спасибо огромное за статьи! Очень полезная и актуальная тема.

    UPD: Кстати, было бы интересно если бы вы также смогли дать краткое описание и пример настройки функционала xray bridge для тех кому нужен функционал реверс прокси и прокидывания доступа из внешней сети к домашней


    1. MiraclePtr Автор
      19.09.2023 09:35
      +1

      Я один раз пробовал почитать документацию и понять как такое настроить - ниасилил, там без бутылки не разобраться. Может быть когда-нибудь потом... А пока лучше просто использовать в качестве реакос-прокси SSH-туннель с авторизацией по ключам и автопереподнятием с autossh. А если вдруг забанят, то SSH всегда можно пустить через XRay :)


    1. MiraclePtr Автор
      19.09.2023 09:35
      +2

      Upd: вроде разобрался, ничего прям сложного на самом деле нет, хотя кажется в примерах в документации упущено несколько моментов. Нужно будет в любом случае потестировать, перед тем как писать статью, пока на это времени совсем нет :(


  1. Dervil_Rus
    19.09.2023 09:35

    Большое спасибо за цикл статей! Блягодаря этой статье наконец таки осилин СDN ;) Смог настроить ss,vless-tls+cdn, vless reality но на свой локальный хост.

    Пока не могу разобраться только с одним моментом: Пытаюсь настроить Reality на сторонний сайт и получаю такой результат: с камими то сайтам все работает, но если в браузере ввожу свой домен то вместо переадресами на сторойнний сайт получаю: Invalid URL The requested URL "[no URL]", is invalid. Такое например если указываю в качестве dest www.microsoft.com:443, Server Names: www.microsoft.com. Бывает другой результат. Например, ессли в качестве dest указать mwomercs.com:443б а в качестве Server Names mwomercs.com, то при заходе на свой сайт получаю страницу поддельного, НО прокся перестает соединяться. Во всех описанных вариантах Google Chrome выдает в строке адреса что сертификат недействительный (ну тут наверное логично, т.к. адрес мой, а самое содержимае не мое). Но блин, никак не могу сделать так, чтобы и сайт открывался и соединение станавливалось :(


    1. MiraclePtr Автор
      19.09.2023 09:35

      Ну вроде все нормально. XTLS-Reality работает так: когда сервер не опознает клиента как валидного клиента прокси, он передает подключение на какой-нибудь другой веб-сервер. Поскольку запрос из браузера у вас идет по вашему домену, то есть в SNI и хедере Host фигурирует не www.microsoft.com, а ваш домен, то сервер Microsoft очень удивляется и говорит "что за фигня, ваш URL типа invalid".

      Еслиесть желание проверить как надо, добавьте IP-адрес вашего сервера и домен, под который вы маскируетесь, в hosts-файл (на Linux это /etc/hosts, на Windows это c:\windows\system32\drivers\etc\hosts), например, "38.25.63.10 www.microsoft.com", и после этого попробуйте зайти на этот адрес браузером - должна открыться настоящая страница этого домена с настоящим TLS-сертификатом.

      Другой вариант: использовать CURL.curl -v --resolve www.microsoft.com:443:151.101.65.69 https://www.microsoft.com (вместо 151.101.xx.xx должен быть IP вашего сервера)


      1. Dervil_Rus
        19.09.2023 09:35

        Спасибо большое за ответ. Да, вы правы, все так и есть как вы описали. В данный момент все таки нашел сайт который и открывается и прокся работает как надо. .без изменения hosts. Но это была уже наверное 30-я моя попытка :)

        Щас задумываюсь найти какой нибудь сайтик из адресного пространства моей vps, тогда вообще все клево должно получиться. Единственное не знаю какой еще порт можно настроить. Для ss выделил рандомный. Vless+ ttl + cdn (по второму пункту этой инструкции) на 443 сделал, а вот какой порт сделать для vless + reality что б это все хоть чуть чуть было похоже на правду не понятно, т.к. 443 занят.

        И еще вопросик. Тестировал все типы соединения (пропускал openvpn внутри прокси), наименьший пинг(с разницей несколько мс) получается с ss проксей. Но клиент(NekoRay) на ss соединение пишет что ttl выключено. Это норм? Ss не использует ttl?

        P.s. и еше одно уточнение для ваших инструкций, долго очень искал решения проблемы, везде в xray и в веб панели 3x-ui надо скармливать не файл сертификата, а fullchain.


  1. gist59
    19.09.2023 09:35

    собираетесь ли вы публиковать данные статьи в децентрализованных сетях, если да, где именно? поговаривают, что с марта 2024 собираются блокировать информацию об обходе блокировок


    1. MiraclePtr Автор
      19.09.2023 09:35
      +1

      Я с ними не особо знаком, но если кто-нибудь опубликует, я не буду возражать.
      Все статьи опубликованы под лицензией Creative Commons BY‑NC‑SA.


  1. Rustam94Pr
    19.09.2023 09:35

    Спасибо вам за гайды. К сожалению новичок, в нужной ветке не могу отписать, задам вопрос по XLTS здесь.

    Настроил XLTS Reality через X-ui панель по вашему гайду. Все работает. Но с настройками на клиенте возникла странная трабла. Клиент nekoray для android. На сервере отключил блокировку ру подключений. Установил правила маршрутизации обход для нужных приложений, обход по geoip:ru и обход по domain:ru. И вот с последним возникает странная ситуация.
    1. прокси выключено. Все ру сайты открываются, 2ip.ru выдает русский ip.
    2. включаем прокси и включаем правило по домену. Часть ру сайтов открывается (пикабу например), часть перестает (не работает яндекс, zzap.ru возможно еще какие то). при этом 2ip.ru открывается и выдает русский ip.
    3. включаем прокси но выключаем правило по домену. Все ру сайты открываются, 2ip.ru открывается и выдает ip адрес VPS.

    Что это может быть и как попробовать бороться? Понимаю что простым решением будет выключить прямой маршрут до ру сегмента, но хотелось бы большей устойчивости, а как понял из ваших статей, такой вариант допускает блокировку vps сервера по "косвенным" данным