В этой инструкции настроим личный сервер 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.