diff --git a/docs/runbooks/ru-hub-add-exit.md b/docs/runbooks/ru-hub-add-exit.md new file mode 100644 index 0000000..1bd6c6d --- /dev/null +++ b/docs/runbooks/ru-hub-add-exit.md @@ -0,0 +1,134 @@ +# Добавление и удаление выхода семейного RU-хаба + +Область: RU 3x-ui, существующая единая HTTPS-подписка человека. Адреса, пути, +UUID, subId и ключи брать из защищённых операторских файлов 0600. В команды, +Git, терминальный вывод и журналы значения не вставлять. Панель открывается +через существующий SSH-туннель; её bind остаётся loopback. + +## Модель и исходное состояние + +Один человек — одна глобальная запись Client в панели, один UUID, один subId, +одни лимиты и срок. Запись прикреплена ко всем семейным inbound. Не создавать +копии человека с суффиксами `-de`, `-ru`, `-auto` или с новыми subId. + +| Строка подписки | Inbound RU | sort index | Действие | +|---|---:|---:|---| +| ⚡ Авто | TCP24444 | 10 | RU-направления direct, остальные family-auto | +| 🇩🇪 Германия | TCP443 | 20 | RU-направления direct, остальные vpn-de | +| 🇷🇺 Россия | TCP24443 | 30 | весь трафик direct | + +Фиксированные строки нужны, когда важен постоянный выход. `family-auto` использует +`leastLoad`, selector `vpn-`, fallback `blocked`; observatory также выбирает `vpn-`. +Сейчас выход один, поэтому сравнительная скорость нескольких серверов не проверена. + +Подписки: TLS на публичном TCP2096 домена `sub.ochenstarik.ru`, случайный путь +длиной не менее 32 символов, `subUpdates=12`; ответ содержит +`profile-update-interval: 12`. В реальном URL обязателен `:2096`: TCP443 занят Reality. +Ссылка человека сохранена в `family_subscriptions.txt` и при добавлении выхода не меняется. + +## Перед изменением + +1. Согласовать одного оператора на время работы. Если клиентские имена или + привязки меняются параллельно, остановить записи и свой откат к устаревшему + снимку; сделать новый checkpoint, сохраняющий правки владельца. +2. Через SQLite backup API сохранить согласованную БД панели и integrity check. + Копии конфигурации, UFW, managed-ports и runtime evidence — root-only, каталог + 0700, файлы 0600. Не копировать работающую SQLite простым `cp`. +3. Зафиксировать UUID/subId глобальных клиентов, членство inbound и существующие + routing/outbounds. До применения проверить кандидат штатным Xray `run -test`. + Подготовить независимый ограниченный таймер отката; восстановление БД — только + при остановленной панели, с учётом WAL/SHM и последующим штатным запуском. +4. Проверить свежие входы и подписки до изменения. Не использовать проверку + другого сервера или старого SHA как подтверждение текущего состояния. + +## Добавить выход X + +1. На сервере X создать отдельный VLESS+Reality TCP inbound для RU-хаба с + самостоятельными ключами. Firewall X разрешает его порт только с RU-адреса; + публичный домашний inbound X, если есть, к этой схеме не относится. + Проверить TLS1.3 и сертификат camouflage target. Разрешённый SNI должен быть + согласован с этим target: случайный список посторонних имён в подписке недопустим. +2. На RU в штатных **Xray Configs** панели добавить outbound `vpn-x` с реквизитами + из файла 0600. Рабочий сгенерированный `config.json` вручную не править. + Существующие `vpn-de`, `direct`, `blocked`, API и RU-domain/geoip правила сохранить. +3. Создать на RU новый VLESS+Reality TCP inbound на проверенном свободном порту, + с собственными ключами и согласованным SNI. Включить Vision и нужный remark X. + Сначала сохранить правила прямого RU-трафика; после них добавить правило + `inboundTag` нового входа → `vpn-x`. Не менять фиксированные DE/RU строки. +4. В **Clients** выбрать существующих глобальных клиентов и прикрепить к новому + inbound. UUID/subId и настройки клиентов сохранить. В установленной версии + изменение `settings.clients` в форме существующего inbound не заменяет штатные + операции глобальных Clients. +5. `vpn-x` автоматически попадает под selector `vpn-` балансировщика и observatory. + Проверить, что выбран именно транспорт к X и что `fallbackTag` по-прежнему + `blocked`. При недоступности всех выходов автоматическая строка не должна + уходить через `direct` или неявный первый outbound. +6. Открыть новый TCP-порт RU в UFW для семейных клиентов, сохранив старые правила. + Вписать его в root-owned 0600 `/etc/ochenstarik-server/ufw-managed-ports.conf`. + Списки под этот installer — строки `порт/tcp`; не оставлять литеральные `\n`. +7. Выставить порядок: «Авто» первым, затем фиксированные зарубежные выходы, + «Россия» последней. Менять только sort index (доступен отдельный endpoint), + не пересоздавать inbound ради сортировки. HTTPS-путь и subId не ротировать. + +## Проверки и применение + +- Через API получить новый generated config и проверить его штатным Xray до + окончательного применения. Settings сохранять через панель/API, а не SQL-UPDATE + или редактор generated config. `getConfigJson` может быть свежее старого файла + после hot-add; подтвердить настоящий listener и аутентифицированный трафик. +- На каждом человеке загрузить ту же HTTPS-ссылку: валидная TLS chain, HTTP200, + старые строки и ровно одна новая, правильные remarks/порядок, update interval12. + Тело и заголовки со ссылками хранить только в защищённом каталоге. +- Из каждой строки временным клиентом проверить зарубежный IP и российский сайт. + Для сопоставления с учтёнными IPv4 использовать явно IPv4. В текущей сети + Интернетометр Яндекса показывает адрес в странице; его `/api/v0/ip` в день + проверки возвращал loopback даже при прямом запросе с RU и был исключён как IP-echo. +- Проверить UFW, bind панели на loopback, публичные только разрешённые VPN/TLS + listeners, сохранность всех пользовательских UUID/subId и отсутствие дублей. +- При двух и более выходах отдельно измерить выбор при близких задержках, + заметной разнице и отказе. Текущие параметры: burst interval30s, sampling2, + timeout3s; leastLoad expected1, maxRTT2s, tolerance0.2, baseline150ms. + Это фильтр качества и дисперсии, а не строгий sticky-IP или гарантированный + throughput benchmark. После добавления FI/DK нужна отдельная многосерверная приёмка. +- Для отказа использовать отдельную nft-таблицу на RU, блокирующую только + транспорт RU→выход (для DE TCP24443). Независимое удаление через 60 секунд + включить **до** добавления правила. Подтвердить отказ зарубежного «Авто», + отсутствие тихого RU-egress, сохранность RU-исключений и строки «Россия», + автоматическое удаление правила и восстановление «Авто» через доступный выход. + Домашний DE443 и SSH не блокировать. +- Только после положительных проверок отменить откат. Оставить snapshots и + санитизированные доказательства; законченные собственные timers остановить. + Сертификат проверять `certbot renew --dry-run --no-random-sleep-on-renew`: + временный HTTP80 открывают/закрывают renewal hooks, deploy hook штатно + перезапускает x-ui. Публичный доступ к панели не требуется. + +## Особенности API установленной 3x-ui + +Доступ через сохранённые реквизиты/локальный SSH management tunnel; секреты +передавать из файла/STDIN. Для session auth получить CSRF token и cookie, +передавать `X-CSRF-Token`, включая login. Token/cookie не публиковать. + +Namespace — `panel/api/`: `xray/update`, `setting/all`, `setting/update`, +`inbounds`, `clients`. Часть API принимает form, часть JSON; проверять текущую +схему и `success`, а для bulk — также `errors` и фактический результат. +Например, `subUpdates` в JSON settings — число; `settings` в ответе inbound +может уже быть объектом. ClientRecord (`id` числовой, `uuid` строковый, +`allowedIPs` может быть строкой) не является готовым DTO обновления VPN-клиента: +использовать форму Clients или документированную модель, не слать запись БД целиком. + +Скрипт установки не добавлен: на пяти общих клиентах операторский runbook проще +проверять; установленный API существенно различает формы и DTO. Отдельная +автоматизация потребует собственной задачи, совместимости и тестов. + +## Удалить выход + +Убрать правило фиксированного inbound и `vpn-x` из шаблона, проверить selector +и работу оставшихся выходов. Открепить существующих клиентов только от удаляемого +inbound, затем удалить этот inbound и только его UFW/managed-port записи. +Глобальных людей, UUID/subId, HTTPS-путь и остальные подключения не удалять. +На X закрыть и удалить только RU-hub inbound после проверки, что он больше не +используется. Повторить проверку тех же ссылок: исчезла только удалённая строка. + +Сверка DE выполняется без изменений: существующий `vpn-de`, фиксированный вход +RU443, RU-direct правила и exit DE24443 с firewall только от RU. Фактический +итог сверки и испытаний записывается в отчёт выполнения, а не предполагается из runbook.