{"id":47597948,"url":"https://github.com/nozikov/vless-relay-setup","last_synced_at":"2026-04-09T12:18:29.211Z","repository":{"id":344300105,"uuid":"1169868150","full_name":"nozikov/vless-relay-setup","owner":"nozikov","description":"Self-hosted two-hop VPN with traffic masking (VLESS + XTLS-Reality). Automated setup on two VPS servers.","archived":false,"fork":false,"pushed_at":"2026-03-22T14:25:27.000Z","size":203,"stargazers_count":10,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-22T15:07:59.796Z","etag":null,"topics":["3x-ui","bash","censorship-circumvention","self-hosted","vless","vpn","xray","xtls-reality"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nozikov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-01T10:52:06.000Z","updated_at":"2026-03-22T14:29:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nozikov/vless-relay-setup","commit_stats":null,"previous_names":["nozikov/vless-relay-setup"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/nozikov/vless-relay-setup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nozikov%2Fvless-relay-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nozikov%2Fvless-relay-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nozikov%2Fvless-relay-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nozikov%2Fvless-relay-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nozikov","download_url":"https://codeload.github.com/nozikov/vless-relay-setup/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nozikov%2Fvless-relay-setup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3x-ui","bash","censorship-circumvention","self-hosted","vless","vpn","xray","xtls-reality"],"created_at":"2026-04-01T18:30:11.047Z","updated_at":"2026-04-01T18:30:11.934Z","avatar_url":"https://github.com/nozikov.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VLESS Reality Relay — Self-Hosted Encrypted Tunnel\n\nДвухзвенная relay-инфраструктура для зашифрованного соединения между узлами. Автоматическое развёртывание на два VPS-сервера.\n\n\u003e **Правовая оговорка:** Проект предназначен исключительно для законных целей — корпоративная сегментация сетей, исследования в области приватности, резервирование инфраструктуры. Пользователи самостоятельно несут ответственность за соблюдение применимого законодательства.\n\n🇬🇧 [English](README.en.md)\n\n## Как это работает\n\n![Архитектура](./docs/architecture.svg)\n\nRelay-нода обеспечивает сетевую сегментацию: клиент подключается к ближайшему серверу, а выход в интернет идёт через удалённый.\n\n![Сравнение: один хоп и два хопа](./docs/vpn_relay_comparison.svg)\n\nТакая архитектура даёт:\n\n- **Устойчивость** — если exit-нода недоступна, достаточно заменить её в одном месте, клиенты ничего не заметят\n- **Сегментация** — разделение точки входа и выхода: метаданные разнесены по разным хопам\n- **Низкий латенси** — клиент подключается к географически ближайшему серверу\n\n### SelfSteal SNI (опционально)\n\nРежим SelfSteal обеспечивает соответствие домена, IP-адреса и TLS-сертификата сервера. Caddy хостит реальный сайт на вашем домене, устраняя несоответствие SNI/IP.\n\n![SelfSteal: сравнение](./docs/selfsteal-comparison.svg)\n\nSelfSteal полностью опциональный — если не хотите настраивать домен, просто нажмите Enter при установке. Если включён, Caddy также проксирует панель управления и подписки.\n\n![Архитектура с SelfSteal](./docs/selfsteal-architecture.svg)\n\n### CDN Fallback (опционально)\n\nТрафик маршрутизируется через Cloudflare CDN, обеспечивая резервный путь доставки при недоступности прямого соединения.\n\n![CDN: сравнение](./docs/cdn-comparison.svg)\n\nCDN Fallback поддерживает два режима. В асимметричном — исходящий трафик идёт через CDN, а входящий напрямую (быстрее). В симметричном — весь трафик через CDN (максимальная устойчивость). Оба профиля доступны через подписку.\n\n![Архитектура с CDN](./docs/cdn-architecture.svg)\n\nCDN Fallback требует SelfSteal (нужен Caddy) и отдельный домен, подключённый к Cloudflare. Настройка Cloudflare — ручная (инструкция выводится при установке).\n\n### DNS-фильтрация\n\nExit-нода использует AdGuard DNS для фильтрации рекламы и трекеров на уровне DNS. Клиентам ничего настраивать не нужно.\n\n![DNS-фильтрация](./docs/dns-filtering.svg)\n\n### Возможности\n\n- **VLESS + XTLS-Reality** — протокол с TLS 1.3 и минимальным оверхедом\n- **Многоуровневый CDN Fallback** — резервные маршруты через Cloudflare с асимметричным режимом\n- **Адаптивная защита соединений** — паддинг пакетов и мультиплексирование соединений\n- **3X-UI панель** — веб-интерфейс для управления пользователями, лимитами трафика и мониторинга\n- **Подписки** — автоматическое обновление конфигурации на клиентских устройствах\n- **SSH hardening + fail2ban + UFW** — автоматическая настройка безопасности серверов\n- **Backup / Rollback** — резервные копии при каждом обновлении с автоматическим откатом при ошибке\n\n## Требования\n\n- **2 VPS-сервера** с Ubuntu 24.04 LTS (минимум 1 CPU, 512 MB RAM)\n  - Relay — ближайший к клиентам сервер для минимального латенси\n  - Exit — удалённый сервер (другой регион или страна)\n- **SSH-ключи** настроены для доступа к обоим серверам (скрипт отключает вход по паролю)\n- **Домен** (опционально) — для подписок и/или SelfSteal режима\n- **Домен для CDN Fallback** (опционально) — отдельный домен, подключённый к Cloudflare (бесплатный план). Требует SelfSteal\n\n\u003e **Важно:** SSH-ключи должны быть настроены до запуска скриптов.\n\n## Подготовка\n\n### SSH-ключи\n\n```bash\n# 1. Создать ключ (если ещё нет)\nssh-keygen -t ed25519\n\n# 2. Скопировать ключ на сервер (повторить для каждого)\nssh-copy-id root@\u003cIP-сервера\u003e\n```\n\nПосле этого `ssh root@\u003cIP\u003e` должен пускать без пароля.\n\n### Домен (опционально)\n\nЕсли планируете использовать SelfSteal, настройте DNS A-записи **до запуска** скриптов:\n\n| Запись | Назначение | Куда указывает |\n|--------|-----------|----------------|\n| `exit.example.com` | SelfSteal на exit-ноде | IP exit-сервера |\n| `example.com` | SelfSteal на relay-ноде (основной домен) | IP relay-сервера |\n| `panel.example.com` | Панель управления через Caddy | IP relay-сервера |\n| `sub.example.com` | Подписки через Caddy | IP relay-сервера |\n\nБез SelfSteal — достаточно одной A-записи на relay для подписок.\n\n## Установка\n\n![Шаги установки](./docs/installation-flow.svg)\n\n\u003e Всегда начинайте с exit-сервера — relay-серверу нужны его данные.\n\n### Шаг 1. Exit-сервер\n\n```bash\napt-get update \u0026\u0026 apt-get install -y git\ngit clone https://github.com/nozikov/vless-relay-setup.git \u0026\u0026 cd vless-relay-setup\nchmod +x scripts/*.sh scripts/lib/*.sh\nsudo ./scripts/setup.sh exit\n```\n\n\u003e **Повторный запуск:** если exit уже настроен, скрипт предложит `update-exit`. Для переустановки: `--force`. Для пропуска SSH hardening: `--skip-ssh`.\n\nСкрипт запросит настройки:\n\n```\n3X-UI panel port [34821]:              ← Enter для случайного порта\n3X-UI panel secret path [a8Kx...]:     ← Enter для случайного пути\nAdmin username [admin]:                ← имя администратора\nAdmin password:                        ← пароль (не отображается)\nCustom SSH port (Enter for default 22): ← порт SSH\nDomain for SelfSteal SNI (Enter to skip): ← домен или Enter\n```\n\nПри включении SelfSteal скрипт дополнительно установит Caddy, выпустит SSL-сертификат и предложит выбрать контент для сайта. Также спросит про CDN Fallback:\n\n```\nCDN domain for Cloudflare (Enter to skip): ← домен для CDN или Enter\n```\n\nЕсли указать CDN-домен, скрипт настроит CDN-маршрут через Caddy. В конце выведет инструкцию по настройке Cloudflare.\n\nВ конце скрипт выведет параметры подключения — **сохраните их** для настройки relay:\n\n```\n  Exit server IP:       185.x.x.x\n  Exit UUID:            a1b2c3d4-...\n  Exit Reality pubkey:  AbCdEfGh...\n  Exit Reality shortId: 1a2b3c4d\n  Exit Reality SNI:     exit.example.com\n  Exit XHTTP path:     xK9mP2vL\n```\n\nЭти значения также сохраняются в `/root/exit-server-info.txt`.\n\n### Шаг 2. Relay-сервер\n\n```bash\napt-get update \u0026\u0026 apt-get install -y git\ngit clone https://github.com/nozikov/vless-relay-setup.git \u0026\u0026 cd vless-relay-setup\nchmod +x scripts/*.sh scripts/lib/*.sh\nsudo ./scripts/setup.sh relay\n```\n\n\u003e **Повторный запуск:** `--force` для переустановки (все ключи будут пересозданы). `--skip-ssh` для пропуска SSH hardening.\n\nСкрипт запросит параметры exit-сервера (из шага 1), затем настройки панели и (опционально) SelfSteal:\n\n```\nExit server IP:                ← из шага 1\nExit server UUID:              ← из шага 1\n...\nDomain for SelfSteal SNI (Enter to skip): ← домен или Enter\n```\n\nПри включении SelfSteal дополнительно:\n\n```\nDomain for 3X-UI panel (e.g. panel.example.com): ← поддомен для панели\nDomain for subscriptions (Enter to skip):        ← поддомен для подписок\n```\n\nБез SelfSteal — скрипт спросит только домен для подписок (опционально).\n\n### Шаг 3. Добавление пользователей\n\nОткройте панель relay-сервера: `https://\u003crelay-ip\u003e:\u003cport\u003e/\u003cpath\u003e/`\n\n1. **Inbounds** → найдите инбаунд → **+ Add Client**\n2. Укажите email (имя), лимиты трафика и срок действия\n3. Скопируйте subscription-ссылку для пользователя\n\n### Шаг 4. Настройка клиента\n\nПередайте пользователю subscription-ссылку. В приложении: **Подписки → Добавить → Обновить → Подключиться**.\n\n| Платформа | Приложение | Где скачать |\n|-----------|-----------|------------|\n| iOS | Streisand | [App Store](https://apps.apple.com/app/streisand/id6450534064) |\n| Android | v2rayNG | [GitHub](https://github.com/2dust/v2rayNG) |\n| Windows | v2rayN | [GitHub](https://github.com/2dust/v2rayN) |\n| macOS | V2BOX | [App Store](https://apps.apple.com/app/v2box-v2ray-client/id6446814690) |\n\n## Структура проекта\n\n![Структура проекта](./docs/project-structure.svg)\n\n## Управление\n\n### Обновление конфигурации\n\n```bash\ncd ~/vless-relay-setup \u0026\u0026 git pull\n\n# Exit-сервер\nsudo ./scripts/setup.sh update-exit\n\n# Relay-сервер\nsudo ./scripts/setup.sh update-relay\n```\n\nКлючи, UUID, клиенты и статистика **сохраняются**. Обновляется только шаблон конфигурации. Перед обновлением создаётся резервная копия с автоматическим откатом при ошибке.\n\nПри CDN Fallback `update-relay` автоматически синхронизирует CDN-ссылку с текущим exit UUID. Если UUID exit-сервера изменился — достаточно запустить `update-relay`, и подписки обновятся. Пользователям нужно только нажать \"Обновить\" в приложении.\n\nДля обновления бинарников (XRAY, 3X-UI, Caddy) добавьте `--upgrade`:\n\n```bash\nsudo ./scripts/setup.sh update-exit --upgrade\nsudo ./scripts/setup.sh update-relay --upgrade\n```\n\n### Удаление\n\n```bash\nsudo ./scripts/setup.sh uninstall           # с подтверждением\nsudo ./scripts/setup.sh uninstall --force    # без подтверждения\nsudo ./scripts/setup.sh uninstall --purge-certs  # удалить и SSL-сертификаты\n```\n\nSSH-ключи и `sshd_config` не удаляются — доступ к серверу сохраняется.\n\n### Сервисы\n\n```bash\n# Exit-сервер\nsystemctl restart xray \u0026\u0026 systemctl status xray\njournalctl -u xray -f\n\n# Relay-сервер\nx-ui restart \u0026\u0026 x-ui status\nx-ui log\n```\n\n## Флаги командной строки\n\n| Флаг | Где работает | Описание |\n|------|-------------|----------|\n| `--force` | setup, uninstall | Пропустить guard-проверку / подтверждение |\n| `--skip-ssh` | setup, update | Не менять конфигурацию SSH |\n| `--upgrade` | update | Обновить бинарники (XRAY, 3X-UI, Caddy) |\n| `--purge-certs` | uninstall | Удалить SSL-сертификаты и acme.sh |\n\n## Безопасность\n\n| Компонент | Описание |\n|-----------|----------|\n| SSH | Только ключевая аутентификация, пароли отключены, опциональная смена порта |\n| fail2ban | Блокировка IP после 3 неудачных попыток SSH на 1 час |\n| UFW | Открыты только необходимые порты (SSH, 443, панель) |\n| 3X-UI | Случайный порт + секретный URL-путь |\n| Reality | TLS 1.3 с маскировкой SNI под легитимный домен |\n| SelfSteal | Реальный сайт на вашем домене — полное соответствие SNI, IP, сертификата |\n| Routing | Блокировка доступа к приватным подсетям (RFC 1918) через туннель |\n| DNS | AdGuard DNS — фильтрация рекламы и трекеров |\n\n## Устранение неполадок\n\n**Логи установки:**\n```bash\nls -la /var/log/vpn-setup-*.log\ncat \"$(ls -t /var/log/vpn-setup-*.log | head -1)\"\n```\n\n**Не удаётся подключиться:**\n```bash\n# Exit\nsystemctl status xray\njournalctl -u xray --no-pager -n 50\n\n# Relay\nx-ui status\nx-ui log\n```\n\n**Не открывается панель:**\n```bash\nx-ui status\nufw status\n```\n\n**Потерял данные exit-сервера:**\n```bash\ncat /root/exit-server-info.txt\n```\n\n**HTTP 500 при добавлении клиента:**\n```bash\n# Проверить шаблон xray в 3X-UI\nsqlite3 /etc/x-ui/x-ui.db \"SELECT value FROM settings WHERE key='xrayTemplateConfig';\" | jq '.api'\n# Если null — запустите update:\nsudo ./scripts/setup.sh update-relay\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnozikov%2Fvless-relay-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnozikov%2Fvless-relay-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnozikov%2Fvless-relay-setup/lists"}