# Reverse Xray (3x-ui) — TrueNAS ↔ Kraken > Создано: 2026-09-01. Цель: проксировать трафик локальных клиентов (сеть TrueNAS 192.168.2.x) через TrueNAS → Kraken → интернет. **Kraken = точка выхода (exit node).** TrueNAS = bridge/контроллер. ## Архитектура ```text ЛОКАЛЬНЫЕ КЛИЕНТЫ (192.168.2.x) │ подключаются к прокси TrueNAS:1080/1081 (SOCKS/HTTP) ИЛИ на поддомен ▼ TRUENAS = 3x-ui (Xray-сервер, bridge/контроллер) — белый IP, mallexxx.duckdns.org │ принимает клиентский трафик; reverse-канал к Kraken ▼ ▲ KRAKEN = Xray-клиент (outbound reverse) + exit node — держит исходящий канал к TrueNAS ▼ интернет ``` - **TrueNAS** (3x-ui): принимает от локальных клиентов + держит reverse-вход, куда подключается Kraken. - **Kraken**: сам **инициирует** канал к TrueNAS (за NAT, не может принимать), получает по нему трафик клиентов, отпускает в интернет. - Кра́кен за NAT ⇒ направление канала **от Kraken к TrueNAS** (Xray reverse). ## Ключевые факты (прояснены) 1. **На 443 у TrueNAS — Caddy** (reverso-proxy, валидные LE-серты), НЕ Xray REALITY. Хостовый маппинг: `0.0.0.0:8443→443` (контейнер), `2019` (admin), `8088→80`. 2. **Xray на TrueNAS** раньше был задуман как 3x-ui: - База `/mnt/RED_2TB/docker/xray-admin/x-ui.db` (3x-ui), inbound `vless-ws` port `10095`, tag `in-10095-tcp`, path `/vless`, host `vpn.mallexxx.duckdns.org`, protocol vless. - Композ-файла в `xray-admin/` нет; контейнер НЕ запущен. 3. **Caddyfile** уже проксирует (мёртвые ссылки на `xray-admin`): - `vpn.mallexxx.duckdns.org` → `@ws path /vless` → `xray-admin:10095` - `vpn-panel.mallexxx.duckdns.org` → `xray-admin:443` / `xray-admin:2053` (path /sub/*) - Сертификаты для этих поддоменов уже выданы (DNS на TrueNAS IP). 4. **`vless-proxy`** (teddysun/xray) на TrueNAS — КЛИЕНТ: слушает 1080/1081 (SOCKS/HTTP), outbound на мёртвый `v.qentra.top:443` (VPS удалён). Используется Hermes-Taiga. 5. **VPS qentra.top (91.207.28.205) УДАЛЁН.** Вся старая VLESS+REALITY инфраструктура на нём недоступна. 6. Открытые порты TrueNAS наружу: **22, 443** (8443 ведёт внутрь контейнера Caddy:443 → но Caddy обрабатывает HTTPS-домены). ## Образ 3x-ui - Официальный: `ghcr.io/mhsanaei/3x-ui:latest` - Контейнер должен называться **`xray-admin`** (как в Caddyfile) и быть в сети **`caddy_default`** (чтобы Caddy резолвил имя). - Volume: `/mnt/RED_2TB/docker/xray-admin:/etc/x-ui` (там лежит готовая `x-ui.db`). - Порт панели: 54321 (web UI, через Caddy поддомен `vpn-panel.mallexxx.duckdns.org`). - VLESS inbound 10095 принимается извне через Caddy `vpn.mallexxx.duckdns.org/vless` (WS), НО для reverse к Kraken нужен подход через панель. ## Композ-файл Файл: `/mnt/RED_2TB/docker/xray-admin/docker-compose.yml` ```yaml services: xray-admin: image: ghcr.io/mhsanaei/3x-ui:latest container_name: xray-admin restart: unless-stopped volumes: - /mnt/RED_2TB/docker/xray-admin:/etc/x-ui environment: - XRAY_VMESS_AEAD_FORCED=false networks: - caddy_default ports: - "54321:54321" # 3x-ui панель (web UI) networks: caddy_default: external: true ``` ⚠️ ПОРТЫ 10095 и 2053/443 НЕ пробрасывать на host отдельно — Caddy стоит перед 443 и маршрутизирует /vless → xray-admin:10095 по имени в общей сети. Если нужно наружу снаружи (не через Caddy), проброс отдельный — обсудить. ## Сеть: reverse к Kraken `xray-admin` должен быть в сети `caddy_default` — там же Caddy. Проверено: caddy_default содержит caddy, syncthing, webdav, gitea. ## Reverse-схема (Xray portal/bridge) — 2026-09-01, спроектировано Целевое: локальные клиенты сети TrueNAS (192.168.2.x) выходят в интернет через Kraken. Роли Xray reverse (по эталону Xray-examples/ReverseProxy): - **Kraken = BRIDGE** (reverse bridges) — держит исходящий канал к TrueNAS, публикует "интернет-выход" (freedom). - **TrueNAS = PORTAL** (reverse portals) — принимает от локальных клиентов (external-inbound) и пересылает в Kraken по reverse-каналу (interconn). Конкретные порты/транспорт: | Компонент | Хост | Контейнер/роль | Транспорт | Вход/выход | |---|---|---|---|---| | portal | TrueNAS | `xray-reverse-portal` | VLESS-WS | interconn `:12346` → Caddy path `/rvs`; external `:12345` для клиентов сети | | bridge | Kraken | `xray-reverse-bridge` | VLESS-WS | interconn → `vpn.mallexxx.duckdns.org` path `/rvs`; свобода → интернет | Транспорт: VLESS + WebSocket (т.к. снаружи TrueNAS только 443 через Caddy; WS подходит для reverse поверх outbound). Отдельный путь Caddy `/rvs` (не `/vless` 3x-ui) → `xray-reverse-portal:12346`, чтобы не смешивать с inbound 3x-ui. Caddy правка: `vpn.mallexxx.duckdns.org` добавить маршрут `@rvs path /rvs` → `reverse_proxy @rvs xray-reverse-portal:12346`. ## Статус деплоя (2026-09-01) ✅ **3x-ui развёрнут на TrueNAS и работает:** - Контейнер `xray-admin` (ghcr.io/mhsanaei/3x-ui:latest, **3.7.0**, Xray 26.7.28) в сети `caddy_default`, volume `/mnt/RED_2TB/docker/xray-admin:/etc/x-ui`. - Панель web UI: **`https://vpn-panel.mallexxx.duckdns.org/` → HTTP 200** (Caddy резолвит `xray-admin:2053`). - Sub-сервер: `[::]:443` (путь /sub), панель `[::]:2053` — как в Caddyfile. - Inbound: `vless-ws` port **10095**, tag `in-10095-tcp`, path `/vless`, host `vpn.mallexxx.duckdns.org` (Caddy path /vless → xray-admin:10095). - 3x-ui **поддерживает reverse** (в бинарнике `clientReverseTags`) — настройка через панель. - Бэкап: `/mnt/RED_2TB/docker/backups/reverse-xray-3xui-20260901-113625/` (Caddyfile + x-ui.db + docker-inventory). ### Фактически развёрнутый compose (deployed на TrueNAS) ```yaml services: xray-admin: image: ghcr.io/mhsanaei/3x-ui:latest container_name: xray-admin hostname: xray-admin restart: unless-stopped environment: - TZ=Asia/Novosibirsk - PUID=950 - PGID=950 volumes: - /mnt/RED_2TB/docker/xray-admin:/etc/x-ui ports: - "54321:54321" # 3x-ui web UI (внутри панель реально на 2053) networks: - caddy_default networks: caddy_default: external: true ``` > Черновик выше (секция «Композ-файл») — предварительный; фактический файл на TrueNAS содержит `hostname`, `TZ`, `PUID/PGID`. Панель внутри слушает **2053** (не 54321) — это то, что Caddyfile проксирует через `vpn-panel`. Хостовый 54321-проброс не используется панелью (панель = 2053), можно убрать. **Следующий шаг:** ✅ Выполнено — reverse развёрнут (см. ниже). Основной doc архитектуры: `personal/tech/xray-reverse-tunnel-kraken-truenas.md`. ## Reverse деплой — ПОЛНЫЙ СТАТУС (2026-09-01, финал сессии) ### Развёрнутые контейнеры (фактические конфиги) **TrueNAS — `xray-reverse-portal`** (VLESS/W S, reverse portal): `/mnt/RED_2TB/docker/reverse-portal/` - compose в `/mnt/RED_2TB/docker/reverse-portal/docker-compose.yml`, image `teddysun/xray:latest` (Xray 26.7.28) - конфиг `config.json` (portal reverse): - inbound `interconn`: VLESS на `:12346`, ws path `/rvs`, host `vpn.mallexxx.duckdns.org`, client `a81c3179-312b-4c5e-8a46-6bf3c30c2941`, `"reverse":{"tag":"reverse-out"}` - inbound `local`: SOCKS на `:12345` (для клиентов сети TrueNAS), `udp:true` - routing: `inboundTag:["local"] → outboundTag:"reverse-out"` - outbounds: `freedom` (placeholder) - проброс на host: **только `12345:12345`** (SOCKS для сети). Порт 12346 в docker-сети (к нему обращается Caddy по имени `xray-reverse-portal:12346`), наружу НЕ проброшен. - сеть `caddy_default`, папку создавал через `docker run --rm -v /:/host alpine sh -c "mkdir -p ...; chown 950:950 ..."` (truenas_admin не имеет прав на `/mnt/RED_2TB/docker/`). **TrueNAS — Caddy**: в блок `vpn.mallexxx.duckdns.org` добавлен маршрут `/rvs`: ```caddy @rvs path /rvs reverse_proxy @rvs xray-reverse-portal:12346 ``` - Caddyfile на хосте: `/mnt/RED_2TB/docker/caddy/Caddyfile` (bind-mount; **нельзя `docker cp`** → `device or resource busy`; править на хосте через alpine `cp /host/tmp/...`). - Бэкап перед правкой: `Caddyfile.pre-reverse` в той же папке. Caddy валидация: `docker exec caddy caddy validate --config /tmp/Caddyfile.new` → "Valid configuration". Перезапуск: `docker restart caddy` (безопасно). - Проверка маршрута: `curl -sk https://vpn.mallexxx.duckdns.org/rvs` → HTTP 400 (ожидаемо для WS-эндпоинта Xray при не-WS GET). **Kraken — `xray-reverse-bridge`** (VLESS-WS reverse bridge): `/home/kraken/xray-reverse/` - compose + `config.json` (bridge reverse): - outbounds: `direct` = `freedom` + `"finalRules":[{"action":"allow","network":"tcp,udp","ip":["0.0.0.0/0"]}]`; `conn` = VLESS simplified style (НЕ vnext) → `vpn.mallexxx.duckdns.org:443`, ws `/rvs`, `"reverse":{"tag":"reverse-in"}`, security tls - routing: `inboundTag:["reverse-in"] → outboundTag:"direct"` - **Питфолл:** VLESS-outbound для reverse ДОЛЖЕН быть в *упрощённом* стиле (`settings.address/port/id/encryption/reverse`) — при использовании `vnext[]/users[]` Xray 26.x ругается: `VLESS users: please use simplified outbound's config style to use "reverse"`. - `loglevel debug` включён для диагностики. - Порт 443 на Kraken свободен; образ `teddysun/xray:latest` скачан. ### Развёрнутый reverse-канал — работает - Kraken → TrueNAS: `netstat` на Kraken показывает `172.24.0.2:xxxxx → 90.189.160.148:443 ESTABLISHED`. - Portal (TrueNAS): `::ffff:172.16.1.7:12346 ::ffff:172.16.1.3:52616 ESTABLISHED` (172.16.1.3 = Caddy, передающий WS от Kraken). - Bridge логи: `common/mux: received request for udp:reverse:0` — reverse-канал установлен (TCP+UDP). ### ❌ НЕ работает: payload (end-to-end curl 000) - `curl --socks5 127.0.0.1:12345 http://api.ipify.org` на TrueNAS → `code=000` (прямой curl с того же хоста → 200). - Portal логи: `accepted tcp:8.47.69.0:80 [local -> reverse-out]` — portal отправил запрос в reverse-out. - **Bridge НЕ логирует accepted/received для этого TCP-payload** — данные теряются между portal reverse-out и bridge reverse-in. - Kraken имеет прямой интернет (api.ipify → `92.62.70.41`, code=200), поэтому проблема НЕ в egress Kraken. ### 💡 Гипотеза по неработающему payload (ВЕРОЯТНАЯ) **WebSocket-транспорт НЕ пропускает reverse-payload должным образом.** В официальном Xray reverse-примере используется **прямой TCP** + `flow: xtls-rprx-vision` (REALITY) для канала bridge↔portal. Обратный UDP reverse создаётся (`udp:reverse:0`), но TCP-payload по WS не доходит до bridge. **Решение (предполагаемое):** перевести reverse-канал на **прямой TCP**: на TrueNAS VLESS-inbound interconn на отдельном TCP-порту (напр. 12346 наружу) + проброс на роутере `внешний :12346 → 192.168.2.197:12346`; bridge VLESS-outbound → TCP (не WS). Выполнение отложено — Alex согласовал проброс порта («не проблема»), но внедрение не завершено. ## Порядок работ (отметки → фактический статус 2026-09-01, финал) 1. ✅ Бэкап: `/mnt/RED_2TB/docker/backups/reverse-xray-3xui-20260901-113625/` (Caddyfile + x-ui.db + docker-inventory). 2. ✅ Создан `/mnt/RED_2TB/docker/xray-admin/docker-compose.yml` (deployed версия — см. «Фактически развёрнутый compose»). 3. ✅ Поднят `docker compose up -d` → контейнер Up. 4. ✅ Проверено: панель `https://vpn-panel.mallexxx.duckdns.org/` → HTTP 200, inbound vless-ws:10095 активен. 5. ✅ Создан portal-контейнер `xray-reverse-portal` на TrueNAS (VLESS-WS `interconn`:12346 + SOCKS `local`:12345) + Caddy маршрут `/rvs`. 6. ✅ Создан bridge-контейнер `xray-reverse-bridge` на Kraken (VLESS-WS → TrueNAS, egress direct). Reverse-канал установлен. 7. ❌ End-to-end НЕ работает (curl через SOCKS 12345 → 000; payload теряется на WS). Гипотеза — перевести reverse на прямой TCP + проброс порта (см. секцию «Reverse деплой»). **ВНЕДРЕНИЕ TCP-варианта ОТЛОЖЕНО (незавершено).** 8. ⏳ Обновить Obsidian: truenas-infrastructure.md, kraken-access.md, vps-qentra.md. **TODO для следующей сессии.** ## Ограничения / риски - Кра́кен в NAT ⇒ только исходящие соединения; reverse-канал держит Kraken. - Не ломать существующий Caddy/домены (бэкапить Caddyfile, перезапуск Caddy аккуратно). - `vless-proxy` (Hermes-Taiga) не трогать — настроен под local SOCKS. - Внешний Xray-порт: через Caddy по пути `/vless` (WS). Для полноценного reverse возможно потребуется отдельный VLESS+Reality inbound на отдельном порту + проброс на роутере для Kraken — ДОБАВИТЬ после проверки связности панели.