Минимальные патчи VPnBot поверх официального XTLS/Xray-core: точное прекращение активных сессий удалённого пользователя и воспроизводимые Linux-сборки. https://git2.zapret.moe/zapretdiscordyoutube/vpnbot-xray-patches/releases
  • Python 93.6%
  • Shell 6.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
loop-uh bfdb1ee274
All checks were successful
Follow official Xray dev releases / candidate (push) Successful in 1m38s
Test and build VPnBot Xray patches / test-and-build (push) Successful in 3m32s
CI патчей Xray: источник — тот же discover, что у candidate.yml, а не ручной закреп
Симптом: ci.yml красный (запуск 287, patch failed:
proxy/vless/inbound/inbound.go:597), наблюдатель шлёт patch_ci
«патчи не накладываются на свежий XTLS».

Первопричина: ci.yml брал исходник из ручного закрепа upstream.env
(v26.7.28, Go 1.26), а candidate.yml — из discover по официальному Atom.
В 000c6e8 патчи адаптированы под v26.9.30 и выпущены как
v26.9.30-vpnbot.1, но закреп не подняли: CI проверял новые патчи на старом
исходнике. Поезд выпусков при этом здоров — discover сейчас даёт
upstream=v26.9.30, action=noop. Сломанное правило: «какой официальный
исходник проверяет CI» имело два владельца.

Исправление: ci.yml резолвит исходник тем же
release_pipeline.py discover, передаёт candidate.env в test-patches.sh и
build-release.sh через VPNBOT_BUILD_ENV_FILE и берёт версию Go из
go.mod тега, а не жёсткую "1.26". upstream.env (ручная сборка) поднят до
значений манифеста proven v26.9.30-vpnbot.1.

Тест: оба workflow берут исходник и Go из discover и передают
candidate.env обоим сборочным шагам; на прежнем ci.yml тест падает.
Локально: test-patches.sh с discovered env на v26.9.30 зелёный.

Claude-Session: b2684b34-a663-486d-a69e-4d3543ea2650
2026-10-03 15:22:38 +03:00
.forgejo/workflows CI патчей Xray: источник — тот же discover, что у candidate.yml, а не ручной закреп 2026-10-03 15:22:38 +03:00
docs Наблюдатель выпусков Xray: Telegram по сетевому контракту хоста 2026-09-24 20:04:13 +03:00
patches Патчи под Xray-core v26.9.30: upstream удалил уровни серьёзности ошибок 2026-10-01 16:11:43 +03:00
scripts Наблюдатель выпусков Xray: красный ci.yml — отдельное условие patch_ci 2026-10-03 02:08:14 +03:00
systemd Наблюдатель выпусков Xray: красный ci.yml — отдельное условие patch_ci 2026-10-03 02:08:14 +03:00
tests CI патчей Xray: источник — тот же discover, что у candidate.yml, а не ручной закреп 2026-10-03 15:22:38 +03:00
LICENSE Build VPnBot Xray from official source patches 2026-08-07 15:09:35 +03:00
README.md Наблюдатель выпусков Xray: красный ci.yml — отдельное условие patch_ci 2026-10-03 02:08:14 +03:00
upstream.env CI патчей Xray: источник — тот же discover, что у candidate.yml, а не ручной закреп 2026-10-03 15:22:38 +03:00

VPnBot Xray patches

Этот репозиторий хранит только наши изменения для Xray-core. Полной копии чужого проекта здесь нет: scripts/prepare-source.sh получает точный тег из официального XTLS/Xray-core, проверяет его commit и последовательно накладывает три файла из patches/.

Патчи добавляют capability-маркер vpnbot-active-revoke-v3. Он означает, что после удаления пользователя через Xray API закрываются уже установленные VLESS, Trojan, VMess и Shadowsocks-сессии этого пользователя. Обычный официальный Xray запрещает только новые подключения; поэтому до принятия этого механизма upstream-проектом VPnBot не может безопасно устанавливать чистый официальный бинарник на платные узлы.

Второй маркер vpnbot-live-user-audit-v1 означает, что команда xray api vpnbot-audit-users читает всех пользователей всех inbound через один процесс и одно локальное gRPC-соединение. Команда делает два полных прохода и сверяет каждый список с GetInboundUsersCount; узловой помощник сравнивает оба прохода и по-прежнему безопасно отказывает при любой неоднозначности. На старых узлах без маркера остаётся совместимый, но более дорогой аудит отдельными командами.

Граница источников

  • чужой исходный код загружается только из официального GitHub XTLS;
  • Forgejo хранит наши патчи, проверки, сборочные сценарии и готовые релизы;
  • тег и commit upstream закреплены в upstream.env для ручной сборки, а автоматический выпуск создаёт отдельный build-env с теми же строгими проверками;
  • SHA-256 каждого патча закреплён в patches/series;
  • Actions заново применяет патчи к официальному исходнику, запускает профильные тесты и собирает три Linux-архива, которые используются VPnBot.

Автоматические dev-релизы

Workflow Follow official Xray dev releases каждые шесть часов читает официальный XTLS/Xray-core/releases.atom, после чего временным shallow Git-fetch получает ровно найденный тег, его commit, время и go.mod. GitHub API, API-токен, подвижная ветка main и постоянная локальная копия Xray-core для discovery не используются. Официальный prerelease/dev-тег для него является нормальным входом, но не становится стабильным релизом VPnBot сразу.

Цепочка разделена на два состояния:

  1. Actions разрешает тег в точный официальный commit, применяет патчи, запускает unit- и real-process-тесты, собирает архивы и публикует Forgejo prerelease с суффиксом -candidate.1.
  2. Root-only таймер на production-хосте устанавливает точный кандидат на выделенный canary-узел, проверяет живую конфигурацию и запускает изолированный VLESS-сценарий с двумя непрерывными потоками. После удаления пользователя A поток A должен закрыться не позднее 10 секунд, а поток B — продолжить работу. Тот же canary до и после удаления проверяет двухпроходную команду live-аудита и не сохраняет пользовательские идентификаторы в proof-файле.
  3. Только после этого создаётся обычный proven-релиз. Его файлы копируются из candidate без пересборки и поэтому имеют ровно те же SHA-256.

Стабильные Xray-updater-таймеры на узлах используют канал stable: они игнорируют prerelease=true и видят только proven-релизы. При конфликте патча, падении теста, недоступном canary или неуспешном отзыве новый stable-релиз не создаётся.

Каждый candidate содержит vpnbot-xray-release-manifest.json с официальным тегом/commit, SHA-256 патчей и архивов. Proven дополнительно содержит vpnbot-xray-pilot-proof.json, то есть машинно проверяемый отчёт живого пилота. Для Linux amd64 один выпуск содержит два архива из одного и того же исходника: совместимый Xray-linux-64.zip (GOAMD64=v1) и оптимизированный Xray-linux-64-v3.zip (GOAMD64=v3). Манифест схемы 3 закрепляет требования к процессору, узловой updater выбирает вариант по фактически видимым гостевой системе CPU flags, а production-canary обязан доказать именно v3-вариант. Схема 3 дополнительно закрепляет обязательный vpnbot-live-user-audit-v1, чтобы старый бинарник нельзя было ошибочно продвинуть как новый выпуск с однопроцессным аудитом. Полная модель состояний, гонок и rollback описана в docs/2026-08-07-automatic-dev-release-plan.md.

Production-компонент устанавливается от root:

scripts/install_promoter.sh

Перед включением таймера нужен runtime-файл /etc/vpnbot-xray-release-promoter.env по примеру из systemd/ и root-only Forgejo-токен с областью write:repository. Токен, SSH-ключ и состояние пилота не хранятся в Git.

Тот же установщик добавляет независимый наблюдатель vpnbot-xray-release-alert.timer. Он раз в пять минут проверяет последний candidate.yml, возраст опубликованных candidate без proven и root-only состояние canary. Оператор получает Telegram-сообщение при безопасной остановке выпуска, редкое напоминание для продолжающейся аварии и отдельное сообщение о подтверждённом восстановлении. Переходный retry workflow или canary не считается восстановлением.

Forgejo может показывать публичные Actions-запуски в интерфейсе, но возвращать пустой workflow_runs через публичный API. В таком случае наблюдатель читает страницу именно candidate.yml, выбирает последний запуск main и извлекает только встроенное структурированное JSON-состояние страницы запуска. Он не угадывает результат по цвету иконки или локализованному тексту. Незавершённый запуск старше общего stall-интервала становится отдельной аварией runner, потому что бесконечное waiting иначе оставляло бы сторож молчащим.

Наблюдатель следит и за ci.yml (VPNBOT_XRAY_ALERT_CI_WORKFLOW_ID): красный CI на свежем официальном исходнике — отдельное условие patch_ci. Оно значит, что следующий релиз XTLS не соберётся в candidate, и узнаём мы об этом за дни до candidate.yml (с 01.10.2026 CI был красным незаметно).

Недоступный источник не означает вердикта о выпуске. Ответы 5xx и 429 и сетевой обрыв после повторов release_pipeline.request_bytes поднимает как SourceUnavailableError с кодом source_server_error, source_rate_limited или source_unreachable. Ответ 4xx и битое тело остаются обычным PipelineError: это поломка контракта. В такой прогон наблюдатель не оценивает workflow, candidate и canary, поэтому открытый инцидент не закрывается и новый не открывается. Вместо этого он ведёт условие release_source: молчит, пока недоступность короче VPNBOT_XRAY_ALERT_SOURCE_OUTAGE_SECONDS (по умолчанию 1800 с), затем шлёт одну тревогу, а потом сообщение о восстановлении. Промоутер при недоступном источнике на шаге выбора кандидата (до любых изменений) откладывает прогон и завершается с кодом 0. Повод для этого — ночная остановка Forgejo на ~90 секунд ради консистентного бэкапа: 28–29.09.2026 она роняла оба юнита ответом 502.

Для наблюдателя нужен /etc/vpnbot-xray-release-alert.env по отдельному примеру из systemd/. В нём нет токена Telegram: скрипт читает только VPNBOT_BOT_TOKEN из существующего root-only runtime-env VPnBot и отправляет обычный HTTPS на api.telegram.org. Своей маршрутизации у него нет: путь к Telegram принадлежит хосту. Telegram-фронт node manager сопоставляет имя с loopback-адресом и склеивает соединение со здоровым реле или прямым адресом. До 03.10.2026 скрипт держал копию политики бота (реле, резервные IPv4, семейство адресов), а 24.09 не держал никакой и падал с ENETUNREACH. Отказ доставки печатается typed-кодом: telegram_connect_failed гарантирует, что запрос не ушёл; telegram_delivery_ambiguous — запрос ушёл без ответа и в этом запуске не повторяется. Долговечное состояние дедупликации хранится в /var/lib/vpnbot-xray-release-alert/state.json и никак не участвует в решении о публикации proven.

Режимы ручной проверки после установки:

sudo -n /usr/local/libexec/vpnbot-xray-release-promoter/release_alert_monitor.py --print-status
sudo -n /usr/local/libexec/vpnbot-xray-release-promoter/release_alert_monitor.py --send-test

Первый вызов ничего не отправляет и не меняет incident-state. Второй отправляет одно явно помеченное тестовое сообщение и тоже не создаёт ложную аварию.

Локальная проверка

scripts/test-patches.sh
scripts/build-release.sh ./release-assets

Для подготовки исходного дерева без сборки:

scripts/prepare-source.sh ./xray-with-vpnbot-patches

Каталоги назначения должны отсутствовать или быть пустыми.

Исходный Xray-core и изменённые файлы распространяются по Mozilla Public License 2.0. Полный текст лицензии находится в LICENSE.