Как поднять свой VPN-сервер на Trojan через Xray

1965
Как поднять свой VPN-сервер на Trojan через Xray

В этой инструкции настроим личный сервер Trojan через Xray-core на VPS с Ubuntu 24.04 LTS. Сервер будет принимать подключения на 443/tcp, использовать TLS-сертификат Let’s Encrypt и отдавать обычную веб-страницу через fallback, если на домен зайдёт браузер.

Trojan не является классическим VPN-протоколом уровня WireGuard или OpenVPN. Trojan работает как защищённый прокси поверх TLS. На клиенте можно включить системный proxy, TUN-режим или VPN-профиль, поэтому для пользователя результат часто выглядит как обычный VPN.

Что получится в итоге

Схема будет такой. Xray слушает 443/tcp, принимает Trojan-подключения, проверяет пароль и выпускает трафик наружу через outbound freedom. Если пришёл обычный HTTPS-запрос из браузера или запрос с неверным Trojan-паролем, Xray отправляет соединение на локальный Nginx на 127.0.0.1:8080.

Компонент Задача
Xray-core Принимает Trojan-подключения на 443/tcp
Nginx Отдаёт страницу OK для fallback и обслуживает ACME-проверку на 80/tcp
acme.sh Выпускает и обновляет сертификат Let’s Encrypt
UFW Открывает только SSH, HTTP и HTTPS

Для текущего Xray в серверной конфигурации используем транспорт raw. В клиентских интерфейсах тот же вариант может называться TCP, raw или tcp/raw.

Что понадобится

  • VPS с Ubuntu 24.04 LTS. На Debian 12 команды почти такие же, но названия пакетов и UFW-профили лучше проверить отдельно.
  • Публичный IPv4-адрес VPS.
  • Домен или поддомен, например vpn.example.com.
  • Доступ по SSH с правами root или пользователь с sudo.
  • Открытые входящие порты 22/tcp, 80/tcp и 443/tcp в панели VPS-провайдера.
  • Клиент с поддержкой Trojan, например v2rayN, NekoBox, Clash Meta, Shadowrocket, Stash или другой совместимый клиент.

Подготовьте домен и DNS

Создайте у DNS-провайдера A-запись. В примере используется домен vpn.example.com и IP 203.0.113.10. Замените значения на свои.

Тип Имя Значение
A vpn 203.0.113.10

Если домен обслуживает Cloudflare, отключите проксирование для этого поддомена. В панели Cloudflare запись должна работать в режиме DNS only, а не через оранжевое облако. Обычный Trojan TCP TLS должен приходить напрямую на VPS.

Если у поддомена есть AAAA-запись, настройте IPv6 на сервере или удалите AAAA. Иначе часть клиентов попробует подключиться по IPv6 и не попадёт на Xray, который в этой инструкции слушает IPv4.

Проверьте DNS с локального компьютера или с сервера.

dig +short A vpn.example.com
 dig +short AAAA vpn.example.com

Ожидаемый результат. Команда для A возвращает IP вашего VPS. Команда для AAAA ничего не возвращает, если IPv6 не настроен.

Подготовьте VPS

Войдите на сервер

Подключитесь по SSH.

ssh root@203.0.113.10

Если вошли обычным пользователем, получите root-сессию.

sudo -i

Задайте переменные

Замените домен и email на свои значения.

export DOMAIN="vpn.example.com"
 export EMAIL="admin@example.com"

Проверьте, что переменные не пустые.

echo "$DOMAIN"
 echo "$EMAIL"

Обновите систему и поставьте пакеты

apt update
 apt upgrade -y
 apt install -y curl wget unzip nginx openssl ufw dnsutils ca-certificates

Ожидаемый результат. Команды завершаются без ошибок, а nginx -v показывает установленную версию Nginx.

Настройте firewall

ufw default deny incoming
 ufw default allow outgoing
 ufw allow OpenSSH
 ufw allow 80/tcp
 ufw allow 443/tcp
 ufw --force enable
 ufw status verbose

Ожидаемый результат. В статусе UFW видны правила для OpenSSH, 80/tcp и 443/tcp.

Создайте fallback-сайт на Nginx

Создайте каталог и простую страницу. Страница пригодится для проверки домена, ACME-выпуска сертификата и fallback.

mkdir -p /var/www/trojan-site/.well-known/acme-challenge
 
 cat > /var/www/trojan-site/index.html <<'EOF'
 OK
 EOF

Создайте конфигурацию Nginx. Первый блок слушает публичный 80/tcp. Второй блок слушает только 127.0.0.1:8080, туда Xray будет отправлять fallback-запросы.

cat > /etc/nginx/sites-available/trojan-fallback <<EOF
 server {
     listen 80;
     server_name ${DOMAIN};
 
     root /var/www/trojan-site;
     index index.html;
 
     location /.well-known/acme-challenge/ {
         root /var/www/trojan-site;
     }
 
     location / {
         try_files $uri $uri/ =404;
     }
 }
 
 server {
     listen 127.0.0.1:8080;
     server_name ${DOMAIN};
 
     root /var/www/trojan-site;
     index index.html;
 
     location / {
         try_files $uri $uri/ =404;
     }
 }
 EOF
 
 rm -f /etc/nginx/sites-enabled/default
 ln -sf /etc/nginx/sites-available/trojan-fallback /etc/nginx/sites-enabled/trojan-fallback
 nginx -t
 systemctl reload nginx

Проверьте HTTP-ответ с сервера.

curl -I "http://${DOMAIN}"
 curl "http://127.0.0.1:8080"

Ожидаемый результат. Первый запрос возвращает HTTP/1.1 200 OK, второй запрос выводит OK.

Выпустите TLS-сертификат

Установите acme.sh. Email попадёт в настройки ACME-клиента.

curl https://get.acme.sh | sh -s email="$EMAIL"

Выберите Let’s Encrypt и выпустите ECC-сертификат через webroot-проверку.

~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
 ~/.acme.sh/acme.sh --issue -d "$DOMAIN" -w /var/www/trojan-site --keylength ec-256

Ожидаемый результат. В выводе есть сообщение об успешном выпуске сертификата и пути к файлам.

Установите Xray и настройте Trojan

Установите Xray-core

Установите Xray официальным скриптом XTLS. Скрипт создаёт systemd-сервис xray.service, кладёт бинарник в /usr/local/bin/xray, конфиг в /usr/local/etc/xray/ и запускает сервис от пользователя nobody при новой установке.

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install

Проверьте установку и остановите сервис до настройки.

xray version
 systemctl stop xray
 systemctl status xray --no-pager

Подготовьте каталог сертификатов для Xray

Определите пользователя, от которого запускается Xray. На новой установке обычно используется nobody.

XRAY_USER="$(systemctl show -p User --value xray)"
 [ -z "$XRAY_USER" ] && XRAY_USER="nobody"
 XRAY_GROUP="$(id -gn "$XRAY_USER")"
 
 mkdir -p /etc/xray/cert
 touch /etc/xray/cert/xray.crt /etc/xray/cert/xray.key
 chown -R "$XRAY_USER:$XRAY_GROUP" /etc/xray/cert
 chmod 755 /etc/xray/cert
 chmod 644 /etc/xray/cert/xray.crt
 chmod 640 /etc/xray/cert/xray.key

Скопируйте сертификат и ключ в рабочий каталог Xray. Команда --reloadcmd перезапустит Xray после автоматического продления сертификата.

~/.acme.sh/acme.sh --install-cert -d "$DOMAIN" --ecc 
   --fullchain-file /etc/xray/cert/xray.crt 
   --key-file /etc/xray/cert/xray.key 
   --reloadcmd "systemctl restart xray"
 
 chown "$XRAY_USER:$XRAY_GROUP" /etc/xray/cert/xray.crt /etc/xray/cert/xray.key
 chmod 644 /etc/xray/cert/xray.crt
 chmod 640 /etc/xray/cert/xray.key

Проверьте права.

ls -l /etc/xray/cert

Ожидаемый результат. Файл xray.key не доступен для чтения всем пользователям, а владелец совпадает с пользователем сервиса Xray.

Создайте пароль Trojan

Сгенерируйте пароль в hex-формате. Такой пароль проще вставлять в клиенты и URI, потому что в нём нет символов +, / и =.

TROJAN_PASSWORD="$(openssl rand -hex 32)"
 echo "$TROJAN_PASSWORD" > /root/trojan-password.txt
 chmod 600 /root/trojan-password.txt
 cat /root/trojan-password.txt

Скопируйте пароль в менеджер паролей. Если пароль потеряется, придётся создать новый профиль на сервере и в клиенте.

Создайте конфигурацию Xray

Конфигурация поднимает Trojan на 443/tcp, включает TLS и отправляет fallback-трафик на локальный Nginx.

cat > /usr/local/etc/xray/config.json <<EOF
 {
   "log": {
     "loglevel": "warning"
   },
   "inbounds": [
     {
       "tag": "trojan-raw-tls",
       "listen": "0.0.0.0",
       "port": 443,
       "protocol": "trojan",
       "settings": {
         "users": [
           {
             "password": "${TROJAN_PASSWORD}",
             "email": "user1@${DOMAIN}",
             "level": 0
           }
         ],
         "fallbacks": [
           {
             "dest": 8080
           }
         ]
       },
       "streamSettings": {
         "network": "raw",
         "security": "tls",
         "tlsSettings": {
           "alpn": [
             "http/1.1"
           ],
           "certificates": [
             {
               "certificateFile": "/etc/xray/cert/xray.crt",
               "keyFile": "/etc/xray/cert/xray.key"
             }
           ]
         }
       }
     }
   ],
   "outbounds": [
     {
       "tag": "direct",
       "protocol": "freedom"
     },
     {
       "tag": "block",
       "protocol": "blackhole"
     }
   ],
   "routing": {
     "rules": [
       {
         "type": "field",
         "ip": [
           "geoip:private"
         ],
         "outboundTag": "block"
       }
     ]
   }
 }
 EOF

Проверьте конфигурацию и запустите Xray.

xray run -test -config /usr/local/etc/xray/config.json
 systemctl enable xray
 systemctl restart xray
 systemctl status xray --no-pager

Ожидаемый результат. Проверка конфигурации проходит без ошибок, а systemctl status показывает active.

Проверьте порт 443

ss -ltnp | grep ':443'

Ожидаемый результат. Порт 443 слушает процесс xray. Если порт занял nginx, значит в Nginx остался блок listen 443 или другой сайт с HTTPS.

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

Создайте новый профиль Trojan в клиенте. Интерфейсы меняются, поэтому ориентируйтесь на поля, а не на точные названия меню.

Поле клиента Значение
Protocol Trojan
Address, Server или Host vpn.example.com
Port 443
Password значение из /root/trojan-password.txt
Security или TLS TLS, включено
SNI или Server Name vpn.example.com
Transport, Network или Type TCP или raw, зависит от клиента
Allow insecure выключено
ALPN http/1.1, если клиент просит указать вручную

Если клиент поддерживает импорт URI, можно собрать ссылку. Замените PASSWORD и домен на свои значения.

trojan://PASSWORD@vpn.example.com:443?security=tls&sni=vpn.example.com&type=tcp#my-trojan-vps

Если клиент не принимает ссылку, заполните профиль вручную. Формат Trojan URI в разных клиентах поддерживается неодинаково, ручной ввод надёжнее.

Проверьте результат

Проверьте fallback в браузере

Откройте адрес в браузере.

https://vpn.example.com

Ожидаемый результат. Браузер показывает страницу OK без ошибки сертификата. Такой ответ означает, что TLS работает, а обычный HTTPS-запрос ушёл в fallback.

Проверьте сертификат из консоли

openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" < /dev/null

Ожидаемый результат. В выводе есть сертификат для вашего домена, а не самоподписанный или чужой сертификат.

Проверьте логи Xray

journalctl -u xray -n 100 --no-pager

Ожидаемый результат. В логах нет постоянных ошибок чтения ключа, занятости порта, неверного JSON или падений сервиса.

Проверьте внешний IP

Включите клиент и откройте любой сервис проверки IP. Внешний адрес должен совпадать с IP вашего VPS. Если клиент работает только как локальный proxy, проверьте приложение, которое действительно отправляет трафик через этот proxy.

Обслуживание сервера

Обновление системы и Xray

Периодически обновляйте пакеты и Xray.

apt update
 apt upgrade -y
 bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
 systemctl restart xray

После обновления проверьте статус сервиса и подключение клиента.

systemctl status xray --no-pager
 journalctl -u xray -n 50 --no-pager

Смена пароля

Если пароль утёк или доступ больше не нужен старому устройству, создайте новый пароль.

NEW_PASSWORD="$(openssl rand -hex 32)"
 echo "$NEW_PASSWORD"

Замените значение password в /usr/local/etc/xray/config.json, затем перезапустите Xray.

xray run -test -config /usr/local/etc/xray/config.json
 systemctl restart xray

После смены пароля старые клиенты перестанут подключаться. Обновите профиль на своих устройствах.

Частые проблемы и диагностика

Проблема Как проверить Как исправить
Клиент не подключается, тайм-аут ufw status verbose, ss -ltnp | grep ':443', firewall в панели VPS Откройте 443/tcp, проверьте DNS A-запись, убедитесь, что Xray слушает порт
Ошибка сертификата openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" < /dev/null Проверьте SNI в клиенте, домен в сертификате и пути к xray.crt и xray.key
xray не стартует journalctl -u xray -n 100 --no-pager Исправьте JSON, права на ключ, занятый порт или неверный путь к сертификату
В браузере не открывается https://домен curl http://127.0.0.1:8080 и journalctl -u xray -n 50 --no-pager Проверьте локальный Nginx, fallback dest, сертификат и статус Xray
Let’s Encrypt не выдаёт сертификат curl -I "http://${DOMAIN}" и dig +short A "$DOMAIN" Проверьте DNS, порт 80/tcp, webroot /var/www/trojan-site, режим DNS only и лимиты Let’s Encrypt
Домен работает у одних клиентов и не работает у других dig +short AAAA "$DOMAIN" Удалите AAAA-запись или настройте Xray и firewall для IPv6
Подключение есть, но сайты не открываются Проверьте режим клиента, TUN, system proxy и DNS в клиенте Включите правильный режим маршрутизации, проверьте DNS клиента и ограничения исходящего трафика у VPS-провайдера

Команды для быстрой проверки

systemctl status xray --no-pager
 journalctl -u xray -n 100 --no-pager
 nginx -t
 systemctl status nginx --no-pager
 ss -ltnp
 ufw status verbose
 dig +short A "$DOMAIN"
 dig +short AAAA "$DOMAIN"
 openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" < /dev/null

Безопасность и приватность

  • Не публикуйте пароль Trojan в открытых чатах, каналах и репозиториях.
  • Не выдавайте один пароль всем пользователям. Для нескольких людей добавляйте отдельные записи в users с разными паролями и разными email.
  • Не включайте allowInsecure в клиенте. Если сертификат не проходит проверку, надо чинить сертификат и SNI, а не отключать проверку.
  • Не храните постоянный access log без причины. Логи помогают в диагностике, но раскрывают факт подключений и занимают диск.
  • Не запускайте публичную раздачу доступа без правил и мониторинга. Жалобы на трафик часто заканчиваются блокировкой VPS.
  • Следите за уведомлениями хостинга. Если сервер попал в abuse, сначала остановите Xray и смените пароль.

Когда выбрать другой вариант

Сценарий Что выбрать
Нужен простой личный туннель между своими устройствами WireGuard часто проще и быстрее
Нужна схема именно с TLS, доменом и fallback Trojan через Xray подходит
Нужна современная маскировка без обычного сертификата на своём домене Изучите VLESS Reality как отдельный сценарий
Нужна панель для пользователей и лимитов Смотрите Marzban, 3x-ui или Remnawave, но проверяйте риски панели отдельно

Как откатить изменения

Откат удалит Xray, конфигурацию Nginx для fallback-сайта, файлы сертификата в рабочем каталоге Xray и правила firewall для HTTP и HTTPS. Если на сервере был другой сайт, не выполняйте команды вслепую.

mkdir -p /root/trojan-backup
 cp -a /usr/local/etc/xray /root/trojan-backup/xray-config 2>/dev/null || true
 cp -a /root/trojan-password.txt /root/trojan-backup/trojan-password.txt 2>/dev/null || true
 cp -a /etc/nginx/sites-available/trojan-fallback /root/trojan-backup/nginx-trojan-fallback 2>/dev/null || true

Остановите и удалите Xray.

systemctl stop xray || true
 bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove --purge

Удалите fallback-конфигурацию и рабочие файлы сертификата.

rm -f /etc/nginx/sites-enabled/trojan-fallback
 rm -f /etc/nginx/sites-available/trojan-fallback
 rm -rf /var/www/trojan-site
 rm -rf /etc/xray/cert
 
 nginx -t
 systemctl reload nginx || true

Удалите сертификат из списка продления acme.sh и уберите правила firewall.

~/.acme.sh/acme.sh --remove -d "$DOMAIN" --ecc || true
 
 ufw --force delete allow 80/tcp || true
 ufw --force delete allow 443/tcp || true
 ufw status verbose

Если Nginx ставили только для этой инструкции, удалите пакет.

apt purge -y nginx nginx-common
 apt autoremove -y

Не отключайте UFW, если firewall защищает SSH или другие сервисы на сервере.

Официальные источники для проверки

FAQ

Можно ли поднять Trojan без домена?

Для нормальной TLS-проверки лучше не надо. Используйте домен или поддомен, который указывает на VPS.

Почему в серверном конфиге указан raw, а клиент показывает TCP?

В актуальной конфигурации Xray транспорт называется raw. Многие клиенты по привычке называют тот же режим TCP.

Можно ли включить Cloudflare proxy для домена?

Для этой схемы нет. Запись должна работать в режиме DNS only, иначе Trojan TCP TLS не придёт напрямую на VPS.

Нужно ли включать allowInsecure в клиенте?

Нет. Если без allowInsecure подключение не работает, проверьте сертификат, SNI и домен.

Можно ли добавить второго пользователя?

Да. Добавьте второй объект в массив users с отдельным password и уникальным email, затем перезапустите Xray.

Почему браузер показывает страницу OK на VPN-домене?

Так работает fallback. Браузер отправляет обычный HTTPS-запрос, Xray не принимает его как Trojan и передаёт запрос в Nginx.

Что делать, если пароль утёк?

Сгенерируйте новый пароль, замените password в конфигурации Xray, перезапустите сервис и обновите профиль клиента.

Можно ли использовать порт не 443?

Можно, но 443/tcp обычно проще для TLS-сценария. Если меняете порт, откройте новый порт в firewall и укажите тот же порт в клиенте.

Что лучше, Trojan или WireGuard?

Для личного туннеля между своими устройствами WireGuard проще. Для схемы с TLS, доменом и fallback удобнее Trojan через Xray.

Trojan VPN Xray vps TLS ubuntu
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
MAX
MAX
[ confession.log ]
Не спрашивайте, почему
мы в MAX
Мы и сами не гордимся. Но раз уж вы здесь —
$ whoami
securitylab
$ reason?
unknown
Смотреть →
реклама

Николай Нечепуренков

Я – ваш цифровой телохранитель и гид по джунглям интернета. Устал видеть, как хорошие люди попадаются на уловки кибермошенников, поэтому решил действовать. Здесь я делюсь своими секретами безопасности без занудства и сложных терминов. Неважно, считаешь ты себя гуру технологий или только учишься включать компьютер – у меня найдутся советы для каждого. Моя миссия? Сделать цифровой мир безопаснее, а тебя – увереннее в сети.