VLESS через XHTTP и gRPC: установка и настройка
XHTTP и gRPC упаковывают VLESS в обычные HTTP/2-запросы к вашему сайту. Снаружи работает nginx с настоящим сертификатом и настоящей страницей, а Xray получает только запросы на секретный адрес. Такой вход пригодится, когда прямой VLESS по TCP у вашего провайдера подвисает или рвётся.
Ниже настройка с чистого сервера: один nginx на порту 443 и оба транспорта рядом, чтобы переключаться между ними простой заменой ссылки в клиенте.
XHTTP, gRPC и Reality на OBLAKO
Эти транспорты, как и Reality, на OBLAKO разрешены для личного VPN для себя и своего домашнего круга, если сервер настроен по нашим инструкциям, а в SNI стоит ваш собственный домен. Сервер, который показывает сертификат популярного чужого сайта, система выключает автоматически. Полные правила описаны в AUP.
Все конфиги из статьи мы запускали на Ubuntu 24.04 с nginx 1.24 и Xray 26.10.31 в ноябре 2026 года. В каждом варианте через туннель прошло по 20 МБ в обе стороны без искажений, а соединение пережило 130 секунд простоя. Это проверка настройки, а не обхода блокировок: реальное поведение зависит от оператора.
XHTTP или gRPC
| XHTTP | gRPC | |
|---|---|---|
| Статус в Xray | основной транспорт, развивается | объявлен устаревшим, может быть удалён |
| Настройка за nginx | секретный путь | секретное имя сервиса |
| Выбор режима | packet-up, stream-up, stream-one | gun, multi |
| Клиенты | на ядре Xray | на ядре Xray и sing-box |
Начинайте с XHTTP. При запуске с gRPC сам Xray пишет в лог прямое предупреждение:
The feature gRPC transport (with unnecessary costs, etc.) is deprecated, not recommended
for using and might be removed. Please migrate to XHTTP stream-up H2 as soon as possible.gRPC пока работает, и добавить его почти ничего не стоит: это ещё один блок в конфигах. Держите его как запасной вход и для клиентов без поддержки XHTTP, но проверяйте описание релиза перед обновлением Xray.
Что известно о работе в России
Данных мало, и почти все они взяты из отдельных сообщений пользователей. Гарантий не даёт ни один транспорт.
- Оба транспорта не бессмертны. На Хабре сообщали, что по состоянию на 5 июня 2026 года XHTTP и gRPC уже попадали под частичные блокировки в Сибири.
- Иногда спасает смена транспорта. 13 апреля пользователь ntc.party описал, как на сервере в Германии обрывался XHTTP с Reality, а gRPC с Reality на том же адресе заработал.
- Иногда не спасает. В той же теме другой пользователь рассказал, что его gRPC за nginx не работал примерно сутки, с вечера 10 апреля до вечера 11 апреля.
- Ограничение по адресу транспортом не лечится. В заметке о транспортах от 4 ноября отмечено, что некоторые подсети попадают под блок на 16 КБ. Как это проверить, показано ниже.
- Много параллельных соединений заметно. Участники обсуждения на net4people в конце 2025 года связывали срабатывание с числом одновременных TLS-соединений к одному хосту. Выводы там предварительные, но держать доступ личным и не раздавать его десяткам устройств полезно в любом случае.
Если на мобильном интернете включены белые списки, не поможет ни один из этих вариантов. Про этот случай есть отдельная статья: белые списки и каскад.
Что нужно перед началом
- VPS с Ubuntu 22.04, 24.04 или Debian 12 и доступ по SSH.
- Свой домен, A-запись которого указывает на IP сервера. CDN не включайте. Как выбрать подходящее имя, рассказано в статье Домен для self-steal. Слова
vpn,proxy,nodeв имени использовать нельзя.
В командах и конфигах встречаются четыре значения, которые нужно заменить на свои:
| Значение | Откуда взять |
|---|---|
ВАШ_ДОМЕН | ваш домен или поддомен |
ВАШ_UUID | команда xray uuid на шаге 3 |
ПУТЬ_XHTTP | команда openssl rand -hex 8 |
ИМЯ_GRPC | ещё один запуск openssl rand -hex 8 |
Путь и имя сервиса работают как второй пароль: кто их не знает, увидит только ваш сайт. Не используйте /xhttp, /grpc или примеры из чужих инструкций.
Шаг 1. Получите сертификат
apt update && apt upgrade -y
apt install -y nginx certbot
certbot certonly --webroot -w /var/www/html -d ВАШ_ДОМЕН --deploy-hook "systemctl reload nginx"На этом этапе отвечает стандартная страница nginx, через неё certbot и подтверждает домен.
Сразу создайте страницу, которую увидит случайный посетитель. Лучше написать пару осмысленных строк о себе или проекте, чем оставлять заглушку:
mkdir -p /var/www/site
nano /var/www/site/index.htmlШаг 2. Настройте nginx
В этой схеме TLS целиком держит nginx. Xray не работает с сертификатами и слушает только локальные порты, поэтому ему не нужен доступ к ключам Let's Encrypt.
Удалите стандартный сайт и создайте /etc/nginx/sites-available/site:
rm /etc/nginx/sites-enabled/default
nano /etc/nginx/sites-available/siteserver {
listen 80;
server_name ВАШ_ДОМЕН;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name ВАШ_ДОМЕН;
ssl_certificate /etc/letsencrypt/live/ВАШ_ДОМЕН/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ВАШ_ДОМЕН/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/site;
index index.html;
client_header_timeout 5m;
keepalive_timeout 5m;
location /ПУТЬ_XHTTP/ {
client_max_body_size 0;
client_body_timeout 1h;
grpc_read_timeout 1h;
grpc_send_timeout 1h;
grpc_pass grpc://127.0.0.1:10080;
}
location /ИМЯ_GRPC/ {
if ($content_type !~ "^application/grpc") {
return 404;
}
client_max_body_size 0;
client_body_timeout 1h;
grpc_read_timeout 1h;
grpc_send_timeout 1h;
grpc_pass grpc://127.0.0.1:10081;
}
}Что здесь важно:
grpc_passстоит в обоих блоках, в том числе для XHTTP. Так nginx говорит с Xray по HTTP/2, этот вариант рекомендует автор XHTTP.client_max_body_size 0снимает ограничение на размер запроса. Со стандартным лимитом в 1 МБ отправка больших файлов обрывается вstream-upи gRPC.- Без увеличенных таймаутов nginx закрывает простаивающий туннель уже через минуту.
- Проверка
$content_typeпрячет имя сервиса gRPC от обычных запросов: браузер получит 404. - Запись
listen ... http2на новых версиях nginx вызывает предупреждение. Это не ошибка, зато такой конфиг понимает nginx из репозиториев всех перечисленных систем.
Включите сайт:
ln -s /etc/nginx/sites-available/site /etc/nginx/sites-enabled/site
nginx -t && systemctl reload nginxШаг 3. Установите Xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
xray version
xray uuidВерсия должна быть не ниже 26.10.31: в ней закрыта серьёзная уязвимость, подробности в статье Xray в 2026.
Шаг 4. Настройте Xray
Откройте /usr/local/etc/xray/config.json и вставьте конфиг целиком. Если на сервере уже работает Xray, ничего не перезаписывайте: добавьте два объекта из inbounds к своим.
{
"log": { "loglevel": "warning" },
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10080,
"protocol": "vless",
"settings": {
"clients": [{ "id": "ВАШ_UUID" }],
"decryption": "none"
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": { "path": "/ПУТЬ_XHTTP/" }
}
},
{
"listen": "127.0.0.1",
"port": 10081,
"protocol": "vless",
"settings": {
"clients": [{ "id": "ВАШ_UUID" }],
"decryption": "none"
},
"streamSettings": {
"network": "grpc",
"grpcSettings": { "serviceName": "ИМЯ_GRPC" }
}
}
],
"outbounds": [
{ "protocol": "freedom", "tag": "direct" }
]
}Блока security здесь нет намеренно: снаружи шифрование обеспечивает nginx, а эти порты доступны только с самого сервера. Строка flow тоже не нужна, Vision на этих транспортах без VLESS Encryption не работает.
Запустите Xray и откройте порты, если включён UFW:
xray run -test -c /usr/local/etc/xray/config.json
systemctl restart xray
ufw allow 80/tcp
ufw allow 443/tcpШаг 5. Проверьте сервер
Запросы должны вернуть три разных кода:
curl -s -o /dev/null -w "%{http_code}\n" https://ВАШ_ДОМЕН/
curl -s -o /dev/null -w "%{http_code}\n" https://ВАШ_ДОМЕН/ПУТЬ_XHTTP/
curl -s -o /dev/null -w "%{http_code}\n" https://ВАШ_ДОМЕН/ИМЯ_GRPC/Tun| Адрес | Ожидаемый код | Что значит |
|---|---|---|
| сайт | 200 | nginx и сертификат работают |
| путь XHTTP | 400 | запрос дошёл до Xray и отклонён как неполный |
| путь gRPC | 404 | сработала проверка $content_type |
Код 502 на пути XHTTP означает, что nginx не достучался до Xray: проверьте systemctl status xray.
Шаг 6. Подключите клиента
Импортируйте ссылку в клиент на ядре Xray, например v2rayN или v2rayNG. Косая черта в пути записывается как %2F.
XHTTP:
vless://ВАШ_UUID@ВАШ_ДОМЕН:443?encryption=none&security=tls&sni=ВАШ_ДОМЕН&fp=chrome&alpn=h2&type=xhttp&path=%2FПУТЬ_XHTTP%2F&mode=stream-up#site-xhttpgRPC:
vless://ВАШ_UUID@ВАШ_ДОМЕН:443?encryption=none&security=tls&sni=ВАШ_ДОМЕН&fp=chrome&alpn=h2&type=grpc&serviceName=ИМЯ_GRPC&mode=gun#site-grpcВ приложении с ручным вводом значения те же: транспорт xhttp или grpc, TLS, ALPN h2, SNI с вашим доменом. Клиенты на чистом sing-box, в частности Hiddify, могут не принять XHTTP. Для них подойдёт ссылка gRPC.
Какой режим выбрать
Сервер принимает любой режим XHTTP, поэтому менять его можно только в ссылке клиента, параметром mode:
| Режим | Как передаёт данные | Когда брать |
|---|---|---|
stream-up | отправка и получение двумя долгими запросами | основной вариант, его советует само предупреждение Xray |
packet-up | отправка множеством коротких запросов | если посредник буферизует долгие запросы и туннель зависает |
stream-one | всё в одном запросе | запасной вариант, если не проходят первые два |
В нашем тесте packet-up отправлял данные примерно на треть медленнее остальных режимов: 11,8 МБ/с против 19 МБ/с. Абсолютные цифры сняты на одной машине, важно только соотношение.
Значение auto лучше не оставлять без причины. В обсуждении автора указано, что с TLS и HTTP/2 оно выбирает stream-up, но Xray 26.10.31 в нашей проверке выбирал packet-up.
Для gRPC оставьте gun. Режим multi документация Xray считает экспериментальным, а прибавки к скорости в нашем тесте он не дал.
Вариант с Reality
Если вы настроили self-steal, XHTTP и gRPC можно включить прямо внутри Reality, без grpc_pass. Такой вход занимает порт целиком, так что на 443 поместится только один из них. Остальные настройки self-steal не меняются, nginx по-прежнему отвечает на 127.0.0.1:8443.
В существующем подключении уберите flow у пользователя и замените streamSettings. Ключи и shortIds оставьте свои.
Для XHTTP:
"streamSettings": {
"network": "xhttp",
"xhttpSettings": { "path": "/ПУТЬ_XHTTP/" },
"security": "reality",
"realitySettings": {
"target": "127.0.0.1:8443",
"serverNames": ["ВАШ_ДОМЕН"],
"privateKey": "ВАШ_PRIVATE_KEY",
"shortIds": ["ВАШ_SHORT_ID"]
}
}Для gRPC замените первые две строки:
"network": "grpc",
"grpcSettings": { "serviceName": "ИМЯ_GRPC" },Ссылки для клиента:
vless://ВАШ_UUID@ВАШ_ДОМЕН:443?encryption=none&security=reality&sni=ВАШ_ДОМЕН&fp=chrome&pbk=ВАШ_PUBLIC_KEY&sid=ВАШ_SHORT_ID&type=xhttp&path=%2FПУТЬ_XHTTP%2F&mode=stream-one#site-reality-xhttp
vless://ВАШ_UUID@ВАШ_ДОМЕН:443?encryption=none&security=reality&sni=ВАШ_ДОМЕН&fp=chrome&pbk=ВАШ_PUBLIC_KEY&sid=ВАШ_SHORT_ID&type=grpc&serviceName=ИМЯ_GRPC&mode=gun#site-reality-grpcВ обоих случаях в SNI и serverNames стоит только ваш домен. С чужим доменом сервер будет выключен автоматически, какой бы транспорт ни использовался.
Если провайдер мешает
Прежде чем перебирать настройки, выясните, что именно ограничено. Положите на сервер файл размером 1 МБ:
head -c 1M /dev/urandom > /var/www/site/test.binС проблемного интернета, с выключенным VPN, выполните:
curl -o /dev/null -w "%{http_code} %{size_download}\n" --max-time 30 https://ВАШ_ДОМЕН/test.bin| Результат | Вероятная причина | Что делать |
|---|---|---|
200 1048576 | адрес доступен, мешают протокол или поведение | сменить транспорт или режим, попробовать fp=firefox |
| Обрыв примерно на 16 КБ | ограничение на адрес или подсеть | перейти к статье про проверку блокировки IP |
| Таймаут сразу | адрес не отвечает с этой сети | проверить другие сети по той же статье |
| Не открываются никакие зарубежные сайты | на мобильной сети включены белые списки | смотреть статью про каскад |
Закончив проверку, удалите файл: rm /var/www/site/test.bin.
Обратите внимание, что обычная страница сайта помещается в 16 КБ и откроется даже при таком ограничении. Поэтому открывшийся сайт ещё не доказывает, что с адресом всё в порядке.
Частые ошибки
| Симптом | Причина и решение |
|---|---|
| Сайт открывается, а клиент не подключается ни по одной ссылке | Нет HTTP/2 в listen. Строка должна быть listen 443 ssl http2; |
| Сайт открывается, VPN подключается, но трафика нет | Путь или имя сервиса различаются в nginx, Xray и ссылке. В serviceName не ставьте косую черту |
| Туннель обрывается примерно через минуту простоя | В location нет grpc_read_timeout и client_body_timeout |
| Большие файлы не отправляются | В location нет client_max_body_size 0 |
Через VPN не открываются адреса вида 127.0.0.1 или 192.168.x.x | Xray по умолчанию не пускает трафик клиентов на частные адреса. В логе видно blocked target. Так и задумано, разрешать это без необходимости не стоит |
Клиент пишет про неизвестный транспорт xhttp | Клиент на старом ядре или на sing-box. Обновите его или используйте ссылку gRPC |
Xray с Reality и mode=auto даёт unexpected response version | Такое встречалось на старых версиях. Обновите Xray и укажите mode=stream-one |
В journalctl -u xray предупреждение про gRPC | Это не ошибка, gRPC работает. Текст разобран выше |
Если вход работает у одного оператора и не работает у другого, сравните со статьёй VLESS Reality перестал работать: порядок диагностики там тот же, хотя транспорт другой.