На самом деле пишу для себя, так как в процессе настройки потратил большое количество времени, да еще и пришлось поболтать с ИИ.
Что такое 3X-UI? А это веб-панель для управления Xray.
Запрещенного тут нет ничего, это просто доступ к своей внутренней сети.
Вот так у меня это устроено
Внешний клиент
↓
Белый IP:443 (роутер)
↓
Проброс порта 443 → 192.168.10.100:443 (Nginx)
↓
Nginx на 192.168.10.100 проксирует запросы на 192.168.10.150:443
↓
3x-ui на 192.168.10.150 обрабатывает VPN-подключение
Вроде как красиво. Но в моеми случаее nginx не простой, а это панель управления хостингом. Да да, тут крутятся сайты, поэтому будем использовать дополнительно возможности панели управления.
А теперь по шагам.
1. Так как доменное имя у меня уже есть, бегу в панель управления DNS и добавляю себе A запись с именем, пусть будет, xray.umvr.ru на мой публичный IP адрес (если хочется получить имя забесплатно, можно воспользоваться сервисом dot.tk, но там бесплатно 1й год, а дальше как повезет).
2. Пока ждем обновления DNS записией можно приступить к разворачиванию панели управления 3X-UI. Установка очень проста
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
Едиственное, не получаем сертификаты, так как шифрованием будет заниматься nginx.
3. Предположим, что DNS записи уже обновились, и можно добавлять web сайт в панели хостинга. У меня это hestiacp, добавляю домен и сразу ставлю галочки для получения сертификатов Let's Encrypt.
Обновлением сертификатов для https и шифрования будет заниматься hestia. Онаже и будет пробрасывать весь трафик снаружи вовнутрь.
4. Нужно подготовить шаблон для проксирования reverse proxy.
В каталоге
/usr/local/hestia/data/templates/web/nginx
создадим 2 файла my3uix.tpl и my3uix.stpl со следующим содержимым
my3uix.tpl
server {
listen %ip%:%proxy_port%;
server_name %domain_idn% %alias_idn%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
location / {
proxy_pass http://%ip%:%web_port%;
location ~* ^.+\.(%proxy_extensions%)$ {
try_files $uri @fallback;
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
}
location @fallback {
proxy_pass http://%ip%:%web_port%;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
}
my3uix.stpl
server {
listen %ip%:%proxy_ssl_port% ssl http2;
server_name %domain_idn% %alias_idn%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
ssl_certificate %ssl_pem%;
ssl_certificate_key %ssl_key%;
# OCSP отключен (Lets Encrypt закончил поддержку OCSP в 2025)
<div class="adinsertion"></div>
# TLS 1.3 0-RTT anti-replay
if ($anti_replay = 307) { return 307 https://$host$request_uri; }
if ($anti_replay = 425) { return 425; }
include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
# Защита скрытых файлов
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
# --- Прокси для панели 3x-ui ---
location /xQOcn25leDC6G5Q6Q6/ {
proxy_pass http://192.168.10.150:41658/xQOcn25leDC6G5Q6Q6/; # <-- Адрес Админки 3X-UI
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_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# --- Прокси для подписок ---
location /sub/ {
proxy_pass http://192.168.10.150:2096/sub/; # <-- Управление подписками
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_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
# Увеличенные таймауты для WebSocket
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# --- ОСНОВНОЙ WebSocket ПРОКСИ для Xray (VLESS+WS) ---
location /mywss/ { # <-- INBOUND PATH
proxy_pass http://192.168.10.150:443; # <-- INBOUND
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_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_buffering off;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
# Включаем дополнительные конфиги для домена
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
}
Далее указываем этот шаблон как шаблон прокси для домена.
А дальше все просто. Выполняем небольшие настройки в панели - Создать Входящее подключение следующие настройки
Protocol = vless Share address strategy = custom Custom share address = DNS имя домена Port = 443 Transmission = WebSocket Host = DNS имя домена Path = как INBOUND PATH в конфиге Sockopt = Cloudflare CDN Trusted X-Forwarded-For = X-Real-IP Security = None
Обязательно Security = None, так как ssl поднимает nginx reverse proxy.
Далее Panel Settings => General => Trusted proxy CIDRs, добавить свою доверенную сеть
, 192.168.10.0/24
Далее настроить подписки Panel Settings => Subscription => Reverse Proxy URI указываем наш домен и URI Path
https://xray.umvr.ru/sub/
Вроде как все, теперь можно создать пользователя и попытаться подключиться, но рабоать не будет, так как клиент быдет пытыться подключиться по ws, а панель ждет пользователя позащищенному wss, можно поменять с TLS = none на TLS = TLS клиенте и убедиться что все работает.
После можно выполнить настройку переопределения в панели, для этого в меню панели Hosts => Add host и указать настройки
Inbound = выбрать ранее созданный Address = xray.umvr.ru (ранее созданое DNS имя) Security = TLS
Теперь и в подписках будет TLS по умолчанию и не потребуется выполнять настройки дополнительно на клитенте.
