--- title: Xray Reverse Tunnel — Kraken ↔ TrueNAS created: '2026-09-01' updated: '2026-09-01' type: tech namespace: personal tags: [xray, reverse, kraken, truenas, tunnel, networking] confidence: medium related: - "[[family/how-to/vps-qentra]]" - "[[family/how-to/truenas-infrastructure]]" - "[[family/how-to/kraken-access]]" - "[[family/how-to/rasputin-router]]" --- # Xray Reverse Tunnel — Kraken ↔ TrueNAS > **Статус: ЧАСТИЧНО ВНЕДРЕН, end-to-end НЕ РАБОТАЕТ (2026-09-01).** ✅ 3x-ui развёрнут и работает. ✅ reverse portal (TrueNAS) + bridge (Kraken) развёрнуты на **прямом TCP+REALITY**, reverse-канал установлен. ⛔ **End-to-end payload НЕ проходит** (curl 000) — проверено на WS И на TCP+REALITY (и с flow `xtls-rprx-vision`, и без flow). Гипотеза «WS блокирует payload» **опровергнута**. OpenWrt DNAT + порт 12346 проброшены. Задание НЕ завершено. > Архитектурное решение: проксировать исходящий трафик локальных клиентов сети TrueNAS через **TrueNAS → Kraken → интернет**. ## Контекст / Почему - **VPS qentra.top (91.207.28.205) УДАЛЁН** — вся прежняя Xray-инфраструктура на нём (VLESS+REALITY, OpenVPN, WebSocket v.qentra.top) больше не существует. - Нужен новый путь для выхода локальных клиентов сети TrueNAS в интернет через другую точку выхода (Kraken). - Белый IP есть только у **TrueNAS** (`mallexxx.duckdns.org` = `90.189.160.148`). - **Kraken за NAT**, входящие не принимает — только исходящие соединения. ## Принятая схема ``` Локальные клиенты (сеть TrueNAS, 192.168.2.x) │ шлют трафик на локальный прокси TrueNAS (SOCKS 1080 / HTTP 1081) ▼ TrueNAS ←── контроллер / bridge (белый IP, mallexxx.duckdns.org), принимает │ TrueNAS заворачивает трафик в reverse-канал ▼ ▲ Kraken ──┘ держит ИСХОДЯЩИЙ reverse-канал к TrueNAS, отпускает трафик → интернет ▼ интернет ``` **Тип решения: Xray `reverse`.** Роли по Xray: | Узел | Роль | Держит канал? | Выход в интернет? | |------|------|---------------|-------------------| | **TrueNAS** | bridge/контроллер (inbound `reverse`) | ❌ слушает | ❌ | | **Kraken** | outbound reverse-нода + exit | ✅ **исходящий** к TrueNAS | ✅ **да** | | **Локальные клиенты** | используют TrueNAS как локальный прокси-шлюз | — | через Kraken | **Ключевое физическое ограничение:** Kraken за NAT не может принимать входящих. Поэтому канал держит **Kraken исходящим** к TrueNAS. Для передачи клиентского трафика TrueNAS → Kraken используются конструкции `dokodemo-door` + `reverse` + policy-маршрутизация (routing rules). Это чуть сложнее "поставить reverse и всё", конфиг нужен аккуратный. ## ⚠️ Факты, проверенные 2026-09-01 (важно, ломают прежние допущения) 1. **На 443 у TrueNAS НЕ Xray.** Проверено `openssl s_client`: на `mallexxx.duckdns.org:443` отвечает **обычный TLS 1.3 с валидным Let's Encrypt сертификатом для `mallexxx.duckdns.org`** (`issuer=Let's Encrypt/CN=YE2`). Это **Caddy/nginx reverse-proxy**, НЕ Xray REALITY (у REALITY сертификат был бы чужой/поддельный). → Твоя память «на 443 висел xray server» не подтверждается. 2. **`vless-proxy` на TrueNAS** (контейнер `teddysun/xray:latest`, Up 7 дней): - inbound: SOCKS `0.0.0.0:1080`, HTTP `0.0.0.0:1081` (локально в LAN TrueNAS) - outbound: VLESS+WS+TLS на `v.qentra.top:443`, path `/qentra`, id `2D9F24C4-21FE-4784-9843-F11C384DA67A` — **указывает на УДАЛЁННЫЙ VPS → сейчас мёртвый**. - ⚠️ Используется Hermes-Taiga как SOCKS5-прокси (`vless-proxy:1080`) → **Hermes-Taiga сейчас без рабочего прокси**. 3. **Kraken→TrueNAS по `mallexxx.duckdns.org`:** открыты **только 22 (SSH) и 443 (HTTPS/TLS)**. `8443/8964/8080/9000` — closed. Порт 443 — TLS (Caddy), не сырой. 4. **Kraken:** Docker установлен (`/usr/bin/docker`), но демон отвечает медленно/рвёт SSH (проверка `docker ps` не завершилась за 40s). Xray на Kraken **отсутствует** (`which xray` пусто) — нужен Docker-контейнер. 5. **Связанность Kraken↔TrueNAS по 22/443 — подтверждена** (оба OPEN с Kraken). ## ✅ ВНЕДРЕНО 2026-09-01: 3x-ui на TrueNAS (фронтенд + Docker Compose) **Решение Alex:** использовать **3x-ui frontend** + **Docker Compose** (управление клиентами через панель), а не ручной Caddy-pass-through с сырым Xray. Это изменило исходный план реализации (Шаг 1 ниже устарел по способу). ### Развёрнут контейнер `xray-admin` (TrueNAS) - **Имя контейнера:** `xray-admin` (строго, т.к. Caddyfile резолвит `xray-admin` по имени в docker-сети). - **Образ:** `ghcr.io/mhsanaei/3x-ui:latest` (**3.7.0**, Xray **26.7.28**). - **Сеть:** `caddy_default` (external) — там же Caddy, чтобы резолвить имя. - **Volume:** `/mnt/RED_2TB/docker/xray-admin:/etc/x-ui` (туда лёг существующий `x-ui.db`). - **Порт панели:** хостовый `54321 → 54321` (внутри панель реально слушает **2053** — Caddy проксирует `vpn-panel.mallexxx.duckdns.org` → `xray-admin:2053`). - **Compose-файл:** `/mnt/RED_2TB/docker/xray-admin/docker-compose.yml` (deployed версия с `TZ=Asia/Novosibirsk`, `PUID/PGID=950`; см. актуальный файл на TrueNAS — отличается от черновика в плане). - **Панель доступна:** `https://vpn-panel.mallexxx.duckdns.org/` → **HTTP 200**. - **Sub-сервер:** `[::]:443` (path `/sub`), панель `[::]:2053`, inbound `vless-ws:10095` (path `/vless`, host `vpn.mallexxx.duckdns.org`). ### Почему это заработало «из коробки» (важно) База `/mnt/RED_2TB/docker/xray-admin/x-ui.db` **уже была настроена под эту Caddy-интеграцию** (раньше 3x-ui уже задумывался на TrueNAS): inbound `vless-ws` port 10095 tag `in-10095-tcp`, subDomain `vpn-panel.mallexxx.duckdns.org`, subPort 443, subScheme https. Caddyfile уже содержал (мёртвые до подъёма) блоки: - `vpn.mallexxx.duckdns.org` → `@ws path /vless` → `xray-admin:10095` (WS) - `vpn-panel.mallexxx.duckdns.org` → `@sub path /sub/*` → `xray-admin:443` + fallback `xray-admin:2053` - LE-сертификаты для этих поддоменов уже выданы. ### 3x-ui поддерживает reverse В бинарнике `/app/x-ui` присутствует **`clientReverseTags`** → reverse-настройка реализуема через панель 3x-ui (3.7.0). ### Бэкап (сделан до изменений) `/mnt/RED_2TB/docker/backups/reverse-xray-3xui-20260901-113625/` — содержит: `caddy/Caddyfile` (копия из контейнера, 90 строк), `xray-admin/x-ui.db`, `docker-inventory.txt`. ### Мелочь/питфолл Скопированный в volume `docker-compose.yml` оказался внутри контейнера `/etc/x-ui/` (т.к. volume смонтирован туда) — удалить лишний файл из контейнера: `docker exec xray-admin rm -f /etc/x-ui/docker-compose.yml`. ## ✅ ВНЕДРЕНО 2026-09-01: Reverse portal (TrueNAS) + bridge (Kraken) — VLESS-WS После 3x-ui развёрнут полноценный reverse. **Ключевое открытие:** Xray **26.x заменил legacy reverse на "VLESS Reverse Proxy"** — старая схема `reverse.bridges/portals` (Xray-examples/ReverseProxy) **не работает** в этой версии (ошибка `The feature "legacy reverse" has been removed and migrated to "VLESS Reverse Proxy"`). Новая схема: `reverse.tag` в VLESS-клиентах/аутбаундах (примеры — `xtls.github.io/en/document/level-2/vless_reverse.html`, use case "Home Broadband Egress"). ### Роли (новая терминология VLESS Reverse) - **Internal device (Kraken) = BRIDGE**: VLESS-**outbound** с `"reverse":{"tag":"reverse-in"}` → активно устанавливает канал к TrueNAS; на своей стороне создаётся виртуальный **inbound** `reverse-in`, чей трафик направляется в freedom (интернет). - **Public server (TrueNAS) = PORTAL**: VLESS-**inbound** с `"reverse":{"tag":"reverse-out"}` у клиента → создаёт **routable-маутбаунд** `reverse-out`; локальные клиенты (SOCKS) маршрутизируются в `reverse-out`. - `reverse.tag` на двух сторонах **не обязаны совпадать** — соответствие через общий UUID соединения. ### TrueNAS — `xray-reverse-portal` (папка `/mnt/RED_2TB/docker/reverse-portal/`) compose: image `teddysun/xray:latest` (26.7.28), сеть `caddy_default`, volume `config.json:/etc/xray/config.json:ro`, проброс host **`12345:12345`**. `config.json`: - inbound `interconn` (:12346, VLESS, ws path `/rvs`, host `vpn.mallexxx.duckdns.org`, client id `a81c3179-312b-4c5e-8a46-6bf3c30c2941`, `"reverse":{"tag":"reverse-out"}`) - inbound `local` (:12345, SOCKS `noauth udp:true`) — точка входа для клиентов сети TrueNAS - routing: `inboundTag:["local"] → outboundTag:"reverse-out"` - outbounds: `freedom` (placeholder — обязателен, иначе `reverse-out` станет default и весь трафик уйдёт в reverse) - Порт 12346 НЕ проброшен наружу — к нему обращается Caddy по имени `xray-reverse-portal:12346` в docker-сети. ### TrueNAS — Caddyfile (bind mount `/mnt/RED_2TB/docker/caddy/Caddyfile`) Добавлен маршрут в блок `vpn.mallexxx.duckdns.org`: ```caddy @rvs path /rvs reverse_proxy @rvs xray-reverse-portal:12346 ``` Питфоллы: **Caddyfile нельзя править `docker cp`** в контейнер (volume → `device or resource busy`) — править на хосте через `docker run --rm -v /:/host alpine cp /host/tmp/...`. Валидация `docker exec caddy caddy validate --config /tmp/Caddyfile.new` → "Valid configuration". Перезапуск `docker restart caddy` безопасен. Бэкап: `Caddyfile.pre-reverse`. ### Kraken — `xray-reverse-bridge` (папка `/home/kraken/xray-reverse/`) compose: image `teddysun/xray:latest`, volume `config.json:/etc/xray/config.json:ro`. `config.json`: - outbound `direct` = `freedom` + `"finalRules":[{"action":"allow","network":"tcp,udp","ip":["0.0.0.0/0"]}]` (интернет-egress Kraken) - outbound `conn` = **VLESS упрощённого стиля** (`settings.address/port/id/encryption/reverse` — НЕ `vnext[]`!) → `vpn.mallexxx.duckdns.org:443` ws `/rvs` `"reverse":{"tag":"reverse-in"}`, security tls, tlsSettings.serverName `vpn.mallexxx.duckdns.org` - routing: `inboundTag:["reverse-in"] → outboundTag:"direct"` - **Питфолл:** VLESS-outbound с `reverse` должен быть упрощённого стиля. Если через `vnext[]/users[]` → Xray 26.x: `VLESS users: please use simplified outbound's config style to use "reverse"`. - `loglevel debug` (для диагностики). ### Reverse-канал: ✅ установлен - Kraken `netstat`: `172.24.0.2:... → 90.189.160.148:443 ESTABLISHED` - Portal: `::ffff:172.16.1.7:12346 ::ffff:172.16.1.3:52616 ESTABLISHED` (172.16.1.3 = Caddy) - Bridge logs: `common/mux: received request for udp:reverse:0` ### ❌ End-to-end payload НЕ работает - `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]` — запрос ушёл в reverse-out. - **Bridge НЕ логирует received для этого TCP-payload** — данные теряются между reverse-out (portal) и reverse-in (bridge). - Kraken имеет прямой интернет (`api.ipify` → `92.62.70.41`), проблема не в egress. ### ✅ ВНЕДРЕНО (2026-09-01) — TCP+REALITY переход, все шаги выполнены WS-транспорт не пропускал reverse-payload; переведён на **прямой TCP + REALITY** (Alex согласовал проброс). Все 4 шага ВЫПОЛНЕНЫ: 1. ✅ Пересоздан `xray-reverse-portal` на TrueNAS (compose `12345:12345` + `12346:12346`, config REALITY TCP). Проверено `ss -tlnp` → `0.0.0.0:12346 LISTEN`. 2. ✅ OpenWrt DNAT добавлен: redirect `xray-reverse-12346`, `src_dport=12346` → `dest_ip=192.168.2.197:12346`, `target=DNAT`, `/etc/init.d/firewall reload` → `DNAT_ADDED`. Проверено: `mallexxx.duckdns.org:12346` → **OPEN** извне. 3. ✅ Пересоздан `xray-reverse-bridge` на Kraken (config REALITY TCP). Reverse-канал ESTABLISHED: Kraken `172.24.0.2 → 90.189.160.148:12346` + `common/mux: received request for udp:reverse:0`. 4. ❌ **Тест payload НЕ прошёл даже на TCP+REALITY**: `curl --socks5 127.0.0.1:12345 http://api.ipify.org` → **`code=000`**. Portal: `accepted tcp:8.6.112.0:80 [local -> reverse-out]`, но bridge НЕ логирует приход TCP-payload. ### ❌ Дополнительно пробовано: снятие `flow: xtls-rprx-vision` Убрал `flow: xtls-rprx-vision` с обеих сторон (portal interconn client + bridge conn outbound), пересоздал контейнеры (оба `Configuration OK`). Результат: **по-прежнему `code=000`**. Reverse-канал устанавливается, TCP-payload до bridge не доходит. **Вывод:** проблема НЕ в `flow` и НЕ в WS. **Даже на «каноничном» TCP+REALITY payload от portal-reverse-out до bridge-reverse-in не передаётся** (bridge не получает inbound-TCP). Гипотеза про WS **опровергнута**. ### 💡 Обновлённая гипотеза (непроверенная) Reverse-канал (mux `udp:reverse:0`) НЕ доставляет инициированный portal'ом inbound TCP-payload из outbound `reverse-out`. НЕ испробовано: - `sniffing` (http/tls/quic) на portal inbound `local` (routing по домену в reverse-out). - Возможно, в Xray 26.x reverse не пробрасывает произвольный inbound SOCKS-трафик от portal в bridge корректно. - Альтернатива: Kraken тянет `xray`-SOCKS, TrueNAS ходит на него **обычным VLESS-клиентом (без reverse)** — простой исходящий прокси, reverse может быть избыточен. **Статус: задание НЕ завершено — продолжить со sniffing / пересмотром роли reverse в следующей сессии.** ## ⏳ Открытые вопросы по reverse (требуют ответа/действия Alex) ## План реализации (история; Шаг 1 устарел — см. «ВНЕДРЕНО» выше) ### Шаг 1 — TrueNAS: Xray reverse-server поверх Caddy - **Способ (рекомендован): Caddy TLS-pass-through.** Добавить в Caddy TCP-правило: поддомен `xray.mallexxx.duckdns.org:443` → внутренний порт Xray-контейнера (напр. `localhost:8443`). Caddy передаёт сырой TLS-стрим дальше. Xray на TrueNAS принимает VLESS+Reality/TLS. Kraken ходит на `xray.mallexxx.duckdns.org:443`. - Плюс: переиспользуем уже открытый/проброшенный 443 на роутере, не трогаем роутер, туннель маскируется под HTTPS. - Альтернатива: пробросить отдельный порт на роутере (напр. 8443) → требует доступа к роутеру. Менее предпочтительно. - Новый/доразвернутый Xray-контейнер: - inbound `reverse`/`dokodemo-door` на 8443 (извне по pass-through) - local inbound SOCKS/HTTP (уже есть 1080/1081) - routing: трафик клиентов → в reverse-канал к Kraken ### Шаг 2 — TrueNAS: бэкап перед изменением - Снять копию текущего конфига `vless-proxy` (config.json), в `/mnt/RED_2TB/docker//backup/` (паттерн как с cups-splix). ### Шаг 3 — Kraken: Xray outbound reverse в Docker - Контейнер Xray на Kraken (`docker run --restart unless-stopped`, как остальные). - outbound vless → `xray.mallexxx.duckdns.org:443` (через Caddy pass-through). - inbound SOCKS/HTTP на Kraken — точка выхода. - reverse-конфиг: Kraken регистрирует «сервис» (весь трафик через dokodemo-door) наружу через канал к TrueNAS. ### Шаг 4 — Проверка связности - Kraken → `xray.mallexxx.duckdns.org:443` (TCP). - Локальный клиент → TrueNAS:1080 → curl через прокси → должен выйти с IP Kraken. ### Шаг 5 — Обновить Obsidian после внедрения - Дополнить `family/how-to/truenas-infrastructure.md` (Xray reverse-настройка), `family/how-to/kraken-access.md`; обновить `personal/tech/vps-qentra.md` (VPS удалён, ссылки на него). ## Открытые вопросы (требуют ответа Alex) 1. ✅ (решено) **Проброс порта для reverse** — переведён на TCP+REALITY, ВСЁ ВЫПОЛНЕНО (portal пересоздан с REALITY, OpenWrt DNAT `внешний:12346 → 192.168.2.197:12346` добавлен, bridge на Kraken пересоздан). См. секции «ВНЕДРЕНО — TCP+REALITY» выше. **Компанент работает, но payload НЕ проходит (см. пункт 4).** 2. **Какой трафик TrueNAS пустить через Kraken** — весь исходящий интернет, или конкретные сервисы/подсети? (Влияет на маршрутизацию на Kraken.) — всё ещё открыто. 3. ✅ **Kraken docker** — РАБОТАЕТ (после перезагрузки 2026-09-01): Server 29.4.3, Docker Root Dir `/srv/dev-disk-by-uuid-6194539b-.../docker-data` (актуальный UUID, HDD смонтирован), **30 образов сохранены, но 0 контейнеров** (all контейнеры не восстановлены после сбоя). Reverse-bridge-контейнер развёрнут поверх. НО: известные контейнеры (jellyfin, ha, transmission и т.д.) требуется пересоздать — отдельная задача, не входила в reverse-сферу. 4. ❌ **End-to-end payload не проходит** — блокер. WS-вариант не пропускал payload; переведён на TCP+REALITY (ВЫПОЛНЕНО: portal пересоздан, OpenWrt DNAT + порт 12346 проброшен, bridge пересоздан). **НО payload всё равно не проходит** (`code=000`) даже на TCP+REALITY, с flow и без flow (`Configuration OK`). См. секции «ВНЕДРЕНО — TCP+REALITY» и «Обновлённая гипотеза» выше. Задание не завершено. ## Связанные заметки - [[family/how-to/vps-qentra]] — VPS на 2026-09-01 УДАЛЁН - [[family/how-to/truenas-infrastructure]] — TrueNAS Caddy/контейнеры - [[family/how-to/kraken-access]] — Docker Kraken - [[family/how-to/rasputin-router]] — прежний VLESS-туннель на VPS (тоже требует пересмотра, VPS нет) - [[family/how-to/wireguard-vpn]] — WG Eagle↔VPS↔Kraken (VPS-звено теперь мёртво)