Двухзвенная relay-инфраструктура для зашифрованного соединения между узлами. Автоматическое развёртывание на два VPS-сервера.
Правовая оговорка: Проект предназначен исключительно для законных целей — корпоративная сегментация сетей, исследования в области приватности, резервирование инфраструктуры. Пользователи самостоятельно несут ответственность за соблюдение применимого законодательства.
🇬🇧 English
Relay-нода обеспечивает сетевую сегментацию: клиент подключается к ближайшему серверу, а выход в интернет идёт через удалённый.
Такая архитектура даёт:
- Устойчивость — если exit-нода недоступна, достаточно заменить её в одном месте, клиенты ничего не заметят
- Сегментация — разделение точки входа и выхода: метаданные разнесены по разным хопам
- Низкий латенси — клиент подключается к географически ближайшему серверу
Режим SelfSteal обеспечивает соответствие домена, IP-адреса и TLS-сертификата сервера. Caddy хостит реальный сайт на вашем домене, устраняя несоответствие SNI/IP.
SelfSteal полностью опциональный — если не хотите настраивать домен, просто нажмите Enter при установке. Если включён, Caddy также проксирует панель управления и подписки.
Трафик маршрутизируется через Cloudflare CDN, обеспечивая резервный путь доставки при недоступности прямого соединения.
CDN Fallback поддерживает два режима. В асимметричном — исходящий трафик идёт через CDN, а входящий напрямую (быстрее). В симметричном — весь трафик через CDN (максимальная устойчивость). Оба профиля доступны через подписку.
CDN Fallback требует SelfSteal (нужен Caddy) и отдельный домен, подключённый к Cloudflare. Настройка Cloudflare — ручная (инструкция выводится при установке).
Прямое подключение к exit-серверу без прохождения через relay. Один хоп вместо двух — минимальная задержка. Ссылка добавляется в подписку автоматически с самым низким приоритетом: клиент использует её только если relay и CDN недоступны.
Подписка (порядок приоритета):
① Relay → Exit основной
② CDN Asymmetric резерв (быстрый)
③ CDN Symmetric резерв (устойчивый)
④ Hysteria 2 UDP-канал (Salamander + port hopping)
⑤ Direct Exit самый быстрый, но менее надёжный
Split routing настраивается в клиентском приложении и работает с любым из этих каналов.
UDP-канал через протокол Hysteria 2. Работает поверх QUIC с обфускацией Salamander (трафик неотличим от случайных данных) и port hopping (клиент переключается между портами каждые несколько секунд). Устойчив к блокировке UDP — нет фиксированного порта и нет характерных QUIC-заголовков.
Требует SelfSteal (нужен TLS-сертификат). Ссылка добавляется в подписку автоматически. Hysteria 2 работает как отдельный процесс рядом с XRAY — два канала полностью независимы.
ChatGPT, Claude, Gemini и Cursor блокируют датацентровые IP-адреса. Если ваш exit-сервер на Hetzner / DigitalOcean / AEZA и подобных — AI-сервисы будут отдавать «You are blocked».
Решение: опциональный WARP-outbound на exit. Cloudflare WARP даёт consumer-IP-пул, через который AI-сервисы видят запрос как «обычный домашний пользователь».
На exit добавляется правило маршрутизации:
AI-домены (openai/anthropic/google-gemini/cursor)
→ WARP outbound (Cloudflare consumer-IP)
Остальные домены
→ freedom (как раньше)
Включить при установке: ответить Y на вопрос «Enable WARP outbound for AI services» в setup.sh exit.
Включить на существующем сервере:
sudo ./scripts/setup.sh update-exit --enable-warpВыключить:
sudo ./scripts/setup.sh update-exit --disable-warpПолный снос (включая удаление пакета cloudflare-warp):
sudo ./scripts/setup.sh uninstall --purge-warpОграничения: WARP free даёт примерно 100 Mbps. Для AI-чатов это с запасом, но для тяжёлой работы с большими файлами через AI — может тормозить.
Exit-нода использует AdGuard DNS для фильтрации рекламы и трекеров на уровне DNS. Клиентам ничего настраивать не нужно.
Некоторые российские сервисы (банки, госсервисы, маркетплейсы) могут некорректно работать при подключении с иностранного IP-адреса. Split routing решает эту проблему: трафик к российским ресурсам идёт напрямую через домашнего провайдера, а всё остальное — через VPN.
Подписка + split routing:
YouTube, Instagram, Discord → через VPN (обход замедления)
Сбер, Госуслуги, Яндекс, VK → напрямую (домашний IP)
Настройка зависит от клиентского приложения — у каждого свой формат правил маршрутизации (пресеты, remote config, ручные правила). Для Shadowrocket sub-proxy отдаёт готовые конфиги по URL подписки с параметром ?conf=ru (российские ресурсы напрямую) или ?conf=full (весь трафик через VPN).
Split routing не требует дополнительной настройки сервера — это функция клиентских приложений.
- VLESS + XTLS-Reality — сквозное шифрование TLS 1.3. Client→relay через XHTTP-транспорт; relay→exit и Direct Exit через RAW + xtls-rprx-vision (CPU-экономия на exit-сервере)
- Многоуровневый CDN Fallback — резервные маршруты через Cloudflare с асимметричным режимом
- Адаптивная защита соединений — паддинг пакетов и мультиплексирование соединений
- Hysteria 2 (UDP) — резервный канал с обфускацией Salamander и port hopping
- Split Routing — раздельная маршрутизация: российские сервисы напрямую, остальное через VPN. Готовые конфиги для Shadowrocket (
?conf=ru) - 3X-UI панель — веб-интерфейс для управления пользователями, лимитами трафика и мониторинга
- Подписки — автоматическое обновление конфигурации на клиентских устройствах
- SSH hardening + fail2ban + UFW — автоматическая настройка безопасности серверов
- Performance-тюнинг сервера — BBR congestion control + повышенные лимиты файловых дескрипторов
- Backup / Rollback — резервные копии при каждом обновлении с автоматическим откатом при ошибке
- 2 VPS-сервера с Ubuntu 24.04 LTS (минимум 1 CPU, 512 MB RAM)
- Relay — ближайший к клиентам сервер для минимального латенси
- Exit — удалённый сервер (другой регион или страна)
- SSH-ключи настроены для доступа к обоим серверам (скрипт отключает вход по паролю)
- Домен (опционально) — для подписок и/или SelfSteal режима
- Домен для CDN Fallback (опционально) — отдельный домен, подключённый к Cloudflare (бесплатный план). Требует SelfSteal
Важно: SSH-ключи должны быть настроены до запуска скриптов.
# 1. Создать ключ (если ещё нет)
ssh-keygen -t ed25519
# 2. Скопировать ключ на сервер (повторить для каждого)
ssh-copy-id root@<IP-сервера>После этого ssh root@<IP> должен пускать без пароля.
Если планируете использовать SelfSteal, настройте DNS A-записи до запуска скриптов:
| Запись | Назначение | Куда указывает |
|---|---|---|
exit.example.com |
SelfSteal на exit-ноде | IP exit-сервера |
example.com |
SelfSteal на relay-ноде (основной домен) | IP relay-сервера |
panel.example.com |
Панель управления через Caddy | IP relay-сервера |
sub.example.com |
Подписки через Caddy | IP relay-сервера |
Без SelfSteal — достаточно одной A-записи на relay для подписок.
Всегда начинайте с exit-сервера — relay-серверу нужны его данные.
apt-get update && apt-get install -y git
git clone https://github.com/nozikov/vless-relay-setup.git && cd vless-relay-setup
chmod +x scripts/*.sh scripts/lib/*.sh
sudo ./scripts/setup.sh exitПовторный запуск: если exit уже настроен, скрипт предложит
update-exit. Для переустановки:--force. Для пропуска SSH hardening:--skip-ssh.
Скрипт запросит настройки:
3X-UI panel port [34821]: ← Enter для случайного порта
3X-UI panel secret path [a8Kx...]: ← Enter для случайного пути
Admin username [admin]: ← имя администратора
Admin password: ← пароль (не отображается)
Custom SSH port (Enter for default 22): ← порт SSH
Domain for SelfSteal SNI (Enter to skip): ← домен или Enter
При включении SelfSteal скрипт дополнительно установит Caddy, выпустит SSL-сертификат и предложит выбрать контент для сайта. Также спросит про CDN Fallback:
CDN domain for Cloudflare (Enter to skip): ← домен для CDN или Enter
Hysteria 2 UDP port (Enter to skip): ← порт для Hysteria 2 или Enter
Если указать CDN-домен, скрипт настроит CDN-маршрут через Caddy. В конце выведет инструкцию по настройке Cloudflare. Hysteria 2 устанавливается как отдельный процесс рядом с XRAY (UDP, port hopping + Salamander).
В конце скрипт выведет параметры подключения — сохраните их для настройки relay:
Exit server IP: 185.x.x.x
Exit UUID: a1b2c3d4-...
Exit Reality pubkey: AbCdEfGh...
Exit Reality shortId: 1a2b3c4d
Exit Reality SNI: exit.example.com
Эти значения также сохраняются в /root/exit-server-info.txt.
apt-get update && apt-get install -y git
git clone https://github.com/nozikov/vless-relay-setup.git && cd vless-relay-setup
chmod +x scripts/*.sh scripts/lib/*.sh
sudo ./scripts/setup.sh relayПовторный запуск:
--forceдля переустановки (все ключи будут пересозданы).--skip-sshдля пропуска SSH hardening.
Скрипт запросит параметры exit-сервера (из шага 1), затем настройки панели и (опционально) SelfSteal:
Exit server IP: ← из шага 1
Exit server UUID: ← из шага 1
...
Domain for SelfSteal SNI (Enter to skip): ← домен или Enter
При включении SelfSteal дополнительно:
Domain for 3X-UI panel (e.g. panel.example.com): ← поддомен для панели
Domain for subscriptions (Enter to skip): ← поддомен для подписок
Без SelfSteal — скрипт спросит только домен для подписок (опционально).
Откройте панель relay-сервера: https://<relay-ip>:<port>/<path>/
- Inbounds → найдите инбаунд → + Add Client
- Укажите email (имя), лимиты трафика и срок действия
- Скопируйте subscription-ссылку для пользователя
Передайте пользователю subscription-ссылку. В приложении: Подписки → Добавить → Обновить → Подключиться.
| Платформа | Приложение | Где скачать | Split routing |
|---|---|---|---|
| Android | v2rayNG | GitHub | Settings → Routing → preset Russia |
| Android | Happ | GitHub | Routing → добавить RU profile |
| iOS | Shadowrocket | App Store | Config → Remote → ?conf=ru |
| iOS | Happ | App Store | Routing → добавить RU profile |
| iOS | Streisand | App Store | Routing rules в UI |
| Windows | v2rayN | GitHub | Settings → Regional presets → Russia |
| macOS | v2rayN | GitHub | Settings → Regional presets → Russia |
Чтобы российские сервисы (банки, госсервисы, маркетплейсы) работали корректно, настройте раздельную маршрутизацию в клиентском приложении:
v2rayN (Windows / macOS / Linux):
- Settings → Regional presets → Russia
- Выбрать «All, except RU»
- Готово — российские сайты идут напрямую, остальное через VPN
v2rayNG (Android):
- Settings → Routing Settings
- Выбрать пресет Russia или импортировать правила
- Готово
Happ (Android / iOS / десктоп):
- Открыть раздел Routing (меню ⊙ в правом верхнем углу)
- Включить «Use routing»
- Добавить profile — вручную или через deeplink с roscomvpn-routing
Shadowrocket (iOS):
- Добавить подписку как обычно (серверы)
- Config → нажать + → Remote Files
- Вставить URL подписки с параметром
?conf=ru, например:https://sub.example.com/sub/path/?conf=ru - Скачать → выбрать этот конфиг → Global Routing: Config
- Для переключения на «всё через VPN» — заменить
?conf=ruна?conf=full
Streisand (iOS):
- Настройки → Routing → добавить правила вручную
- Добавить:
GEOIP,RU,DIRECTиDOMAIN-SUFFIX,ru,DIRECT
После установки или обновления автоматически выполняется самопроверка — selfcheck. Она показывает зелёные/красные галочки по сервисам и портам, плюс делает «hairpin probe» (curl на собственный публичный IP) чтобы убедиться что Reality маска отвечает снаружи как настоящий сайт.
Запустить вручную в любой момент:
sudo ./scripts/setup.sh selfcheckВозвращает exit code 1 если что-то сломано — удобно для cron:
# /etc/cron.d/vpn-selfcheck — пример (не настраивается автоматически)
0 * * * * root /path/to/setup.sh selfcheck >> /var/log/selfcheck.log 2>&1
На relay-сервере есть команда vpn — bash-обёртка над БД 3X-UI:
vpn add alice # создать клиента, напечатать ссылку на подписку
vpn list # таблица: имя | UUID | enable | трафик ↑↓
vpn link alice # вывести ссылку на подписку этого клиента
vpn remove alice # удалить (с подтверждением; -f скипает)
vpn help # справкаИзменения видны в веб-панели после рефреша. CDN-инбаунд синкается автоматически. Если xray не поднялся после изменений — auto-rollback на исходное состояние.
Каждый клиент получает универсальную ссылку (vpn link <name>). Если открыть её в браузере на телефоне — увидишь страницу с QR-кодом, тремя кнопками one-tap импорта (Happ, v2rayTun, Shadowrocket) и короткой инструкцией. Та же ссылка работает как стандартная подписка для VPN-клиентов.
Кидаешь ссылку другу в мессенджер — он открывает на телефоне, тапает «Открыть в Happ», импорт прошёл, VPN включён.
cd ~/vless-relay-setup && git pull
# Exit-сервер
sudo ./scripts/setup.sh update-exit
# Relay-сервер
sudo ./scripts/setup.sh update-relayКлючи, UUID, клиенты и статистика сохраняются. Обновляется только шаблон конфигурации. Перед обновлением создаётся резервная копия с автоматическим откатом при ошибке.
При CDN Fallback update-relay автоматически синхронизирует CDN-ссылку с текущим exit UUID. Если UUID exit-сервера изменился — достаточно запустить update-relay, и подписки обновятся. Пользователям нужно только нажать "Обновить" в приложении.
Если Hysteria 2 был добавлен на exit после первоначальной настройки relay, передайте параметры через update-relay:
sudo ./scripts/setup.sh update-relay \
--hysteria-port 34821 \
--hysteria-port-end 35821 \
--hysteria-obfs mypasswordЗначения — из exit-server-info.txt. --hysteria-port-end можно не указывать (по умолчанию port + 1000).
Для обновления бинарников (XRAY, 3X-UI, Caddy) добавьте --upgrade:
sudo ./scripts/setup.sh update-exit --upgrade
sudo ./scripts/setup.sh update-relay --upgradesudo ./scripts/setup.sh uninstall # с подтверждением
sudo ./scripts/setup.sh uninstall --force # без подтверждения
sudo ./scripts/setup.sh uninstall --purge-certs # удалить и SSL-сертификатыSSH-ключи и sshd_config не удаляются — доступ к серверу сохраняется.
# Exit-сервер
systemctl restart xray && systemctl status xray
journalctl -u xray -f
# Relay-сервер
x-ui restart && x-ui status
x-ui log| Флаг | Где работает | Описание |
|---|---|---|
--force |
setup, uninstall | Пропустить guard-проверку / подтверждение |
--skip-ssh |
setup, update | Не менять конфигурацию SSH |
--upgrade |
update | Обновить бинарники (XRAY, 3X-UI, Caddy) |
--purge-certs |
uninstall | Удалить SSL-сертификаты и acme.sh |
--hysteria-port |
update-relay | Порт Hysteria 2 на exit-сервере |
--hysteria-port-end |
update-relay | Конец диапазона портов (по умолчанию port + 1000) |
--hysteria-obfs |
update-relay | Пароль обфускации Salamander |
| Компонент | Описание |
|---|---|
| SSH | Только ключевая аутентификация, пароли отключены, опциональная смена порта |
| fail2ban | Блокировка IP после 3 неудачных попыток SSH на 1 час |
| UFW | Открыты только необходимые порты (SSH, 443, панель) |
| 3X-UI | Случайный порт + секретный URL-путь |
| Reality | TLS 1.3 с маскировкой SNI под легитимный домен |
| SelfSteal | Реальный сайт на вашем домене — полное соответствие SNI, IP, сертификата |
| Routing | Блокировка доступа к приватным подсетям (RFC 1918) через туннель |
| DNS | AdGuard DNS — фильтрация рекламы и трекеров |
Логи установки:
ls -la /var/log/vpn-setup-*.log
cat "$(ls -t /var/log/vpn-setup-*.log | head -1)"Не удаётся подключиться:
# Exit
systemctl status xray
journalctl -u xray --no-pager -n 50
# Relay
x-ui status
x-ui logНе открывается панель:
x-ui status
ufw statusПотерял данные exit-сервера:
cat /root/exit-server-info.txtHTTP 500 при добавлении клиента:
# Проверить шаблон xray в 3X-UI
sqlite3 /etc/x-ui/x-ui.db "SELECT value FROM settings WHERE key='xrayTemplateConfig';" | jq '.api'
# Если null — запустите update:
sudo ./scripts/setup.sh update-relayMIT