vpnbot-xray-patches/README.md
loop-uh eeb7e7c60b
Some checks failed
Follow official Xray dev releases / candidate (push) Successful in 1m7s
Test and build VPnBot Xray patches / test-and-build (push) Failing after 1m14s
Наблюдатель выпусков Xray: красный ci.yml — отдельное условие patch_ci
Симптом: ci.yml красный с 01.10.2026 (patch failed:
proxy/vless/inbound/inbound.go:597 на свежем XTLS), и этого никто не видел.
Наблюдатель следил только за candidate.yml, а тот зелёный, пока официальный
релиз не вышел. Когда XTLS выпустит релиз, candidate упадёт, и тревога придёт
на дни позже, чем можно было узнать.

Исправление: оценщик workflow обобщён на таблицу WorkflowWatch (имя
условия, заголовок, последствие, действие). Кроме patch_pipeline
(candidate.yml) появилось условие patch_ci (ci.yml,
VPNBOT_XRAY_ALERT_CI_WORKFLOW_ID): красный последний запуск main — тревога с
действием «адаптировать патч», зелёный — восстановление. Старое состояние
без patch_ci читается без миграции.

Тесты: красный CI — отдельная проблема при зелёном candidate; зелёный CI
восстанавливает; collect_conditions читает оба workflow.

Claude-Session: 6557d466-b637-49c9-9419-7a5fa7cc1ff7
2026-10-03 02:08:14 +03:00

165 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# VPnBot Xray patches
Этот репозиторий хранит только наши изменения для Xray-core. Полной копии
чужого проекта здесь нет: `scripts/prepare-source.sh` получает точный тег из
официального [`XTLS/Xray-core`](https://github.com/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`](docs/2026-08-07-automatic-dev-release-plan.md).
Production-компонент устанавливается от root:
```bash
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.
Режимы ручной проверки после установки:
```bash
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. Второй отправляет
одно явно помеченное тестовое сообщение и тоже не создаёт ложную аварию.
## Локальная проверка
```bash
scripts/test-patches.sh
scripts/build-release.sh ./release-assets
```
Для подготовки исходного дерева без сборки:
```bash
scripts/prepare-source.sh ./xray-with-vpnbot-patches
```
Каталоги назначения должны отсутствовать или быть пустыми.
Исходный Xray-core и изменённые файлы распространяются по Mozilla Public
License 2.0. Полный текст лицензии находится в `LICENSE`.