diff --git a/.agent/decisions/0003-3x-ui-reality-chain.md b/.agent/decisions/0003-3x-ui-reality-chain.md new file mode 100644 index 0000000..59160b5 --- /dev/null +++ b/.agent/decisions/0003-3x-ui-reality-chain.md @@ -0,0 +1,99 @@ +# ADR-0003: цепочка 3x-ui REALITY на otreca — что нельзя менять + +**Статус:** accepted + +**Дата:** 2026-10-10 + +**Контекст:** + +10 октября 2026 владелец сообщил: «по прежнему не работает xray inbound через +3x-ui на otreca. Не знаю, в какой момент после правок агента всё пошло не туда». +Разбор занял ~1.5 часа и дал неочевидный результат: **сервер был полностью +работоспособен**, а «поломка» читалась как системная катастрофа. + +Хронология по коммитам и журналам: + +| Время (MSK) | Событие | +|---|---| +| 16:25:52 | `0df9688` (задача T10) — удалён `reality443Forwarding` | +| 17:05:27 | первый `Connection refused` к `127.0.0.1:15380` в журнале nginx | +| 17:07:33 | первое `worker_connections are not enough` (с 37.128.246.126) | +| ~17:15 | клиенты уходят в ретрай-петлю: ~1668 ошибок за ~40 мин | +| 17:30:58 | `37b4956` — revert nftables (T3) | +| 17:54:18 | `07a0437` — `reality443Forwarding` восстановлен | +| 17:55:38 | контейнер `3xui_app` пересоздан с `127.0.0.1:15380:443/tcp` | +| ~18:05+ | флуд прекращается, ошибок 0 за 36 мин | +| 19:16–19:19 | живые REALITY-сессии, `oqyude` и `snity` online | + +Два вывода, которые неочевидны и потому требуют фиксации: + +1. **Отказ `reality443Forwarding` не выглядит как отказ Xray.** Контейнер + здоров (`restarts=0`), ядро 26.7.28 на месте, SSH жив, панель по SNI + `pubray1.zeroq.su` отвечает валидным сертификатом. Умер только маршрут + `443 → 15380`. Диагностировать «панель/Xray» по симптому бесполезно — + надо проверять порт и `podman inspect .NetworkSettings.Ports`. + +2. **`worker_connections are not enough` — вторичный симптом, а не причина.** + nginx имеет пустой `events {}` → `worker_connections` = 512 (дефолт). Пока + маршрут на 443 был мёртв, реальные клиенты (37.128.246.126 — lanta-me, + Тамбов; 213.135.154.225 — Ростелеком, Тамбов) слали 517-байтные + ClientHello в цикле и выедали 512 соединений. Из-за этого «не работало + всё» даже там, где конкретная причина уже была устранена, и создавался + флуд в логах, уводящий от настоящей причины. + +Отдельно: `x-ui.db.bak.1787862834` (2026-08-27) при поверхностном взгляде +выглядит как «бэкап, который можно откатить». Это **другая конфигурационная +эпоха** — инбаунды на портах 14380/14480/14910/14920, 7 клиентов, без +`dest media.mediavitrina.ru`. Откат заменил бы рабочие 443/8443 и обесценил +все 11 клиентских конфигов. + +**Рассматриваемые альтернативы:** + +1. **A. Оставить как есть, зафиксировать инвариантами (выбрано).** R1.10–R1.13 + + ловушки + порядок диагностики. Минимум правок в коде. +2. **B. Поднять `worker_connections` в `modules/vds/nginx.nix`.** Убирает + вторичный симптом, но **не первопричину**, а файл в AGENTS.md помечен как + мёртвый (T13: `networking.firewall.allowedTCPPorts` не применяется). + Отложено до отдельной задачи — не смешивать с починкой. +3. **C. Бан ретрай-флуда (fail2ban/rate-limit на 443).** Отклонено: флуд + создавали легитимные клиенты, а не атака. Jail `3x-ipl` в контейнере + (`maxRetry=1`) за инцидент не забанил никого — 0 банов. Любое усиление + должно отличать «шторм переподключений» от «злоупотребления». +4. **D. Пин версии образа 3x-ui вместо `:latest`.** Отклонено: противоречит + R1.5 (панель намеренно `:latest`). Схема БД мигрирует на месте при + обновлении — это отдельный риск, не решается версией образа. + +**Решение:** вариант **A**. Зафиксированы R1.10 (уже был) и новые +R1.11–R1.13, две новые ловушки, порядок диагностики из 5 шагов и команды +проверки в раздел «Проверки». + +**Обоснование:** + +- **Стоимость ошибки асимметрична.** Удаление одной опции уронило прокси на + 1.5 часа и выглядело как «сломался весь сервер». Повторение должно быть + видно в правилах, а не восстанавливаться снова. +- **Правило без сигнатуры бесполезно.** «Не удалять `reality443Forwarding`» + без описания симптома не помогает — агент видит «панель отвечает» и + concludes «3x-ui работает». Поэтому R1.10 дополнирован сигнатурой отказа + и порядком диагностики. +- **Нумерация R1 была сломана.** В `project-rules.md` два пункта были + помечены «8», из-за чего `reality443Forwarding` был девятым по счёту, но + AGENTS.md, ловушки и `f2e70bb` уже ссылались на него как на **R1.10**. + Порядок исправлен (R1.8 ядро, R1.9 бэкапы, R1.10 reality) — иначе + перекрёстные ссылки расходятся. +- **Откат БД — ловушка с высоким потенциалом.** Файл называется + `x-ui.db.bak.*` и выглядит как безопасный откат; на деле — снимок + другой эпохи. Запрет зафиксирован явно (R1.12). + +**Последствия:** + +- Любая правка `ports` в `modules/containers/3x-ui.nix` требует + `nixos-rebuild switch` **и** проверки `podman inspect .NetworkSettings.Ports` (R1.11). +- Деплой, пересоздающий `3xui_app`, = окно недоступности REALITY с + ретрай-флудом. Планировать такие деплои в нерабочее время. +- `worker_connections = 512` остаётся известным пробелом — отдельная задача, + файла в манифесте пока нет. +- Панель живёт по адресу `https://pubray1.zeroq.su/pubray/`; запрос к `/` + даёт 404 и это норма (ловушка в `project-rules.md`). + +**Связанное:** R1.10–R1.13, R1.5, R1.8, T10, T3, `.agent/rules/project-rules.md`. \ No newline at end of file diff --git a/.agent/decisions/index.json b/.agent/decisions/index.json index dd76e86..24b485a 100644 --- a/.agent/decisions/index.json +++ b/.agent/decisions/index.json @@ -21,6 +21,14 @@ "blocked_by": [ "user: open question 5.6 (where are backups, how are they verified)" ] + }, + { + "id": "0003", + "title": "Цепочка 3x-ui REALITY на otreca — что нельзя менять (R1.10-R1.13)", + "status": "accepted", + "date": "2026-10-10", + "file": ".agent/decisions/0003-3x-ui-reality-chain.md", + "tags": ["3x-ui", "xray", "reality", "otreca", "nginx", "invariant", "R1.10", "R1.11", "R1.12", "R1.13", "T10"] } ], "proposals": [