Files
obsidian-vault/personal/tech/xray-reverse-tunnel-kraken-truenas.md
T
Taiga b53dd70a15 [2026-09-26 09:10:28] syncthing: personal/tech/archive-org-collection-harvest.md personal/tech/balda-go-fx-pitfalls.md personal/tech/bilety-oxota-interaktiv.md personal/tech/cloudflare-tunnel-ssh-published-route.md personal/tech/deepseek-language-drift.md personal/tech/docker-data-root-mount-race.md personal/tech/docker-mac-disk-issues.md personal/tech/docker_colima_setup.md personal/tech/eagle-dashboard-launchd.md personal/tech/hermes-agent-improvements.md personal/tech/hermes-browser-toolsets.md personal/tech/hermes-fork-vs-upstream.md personal/tech/hermes-git-repo.md personal/tech/hermes-memory-architecture.md personal/tech/hermes-secret-redaction-bypass.md personal/tech/hermes-self-improvement-review.md personal/tech/home-network-config.md personal/tech/inter-site-throughput-taiga-to-mac.md personal/tech/inter-site-throughput-taiga-to-mac.md.bak-nedstab2 personal/tech/jellyfin-db-schema-mismatch.md personal/tech/karabiner-keyboard-config.md personal/tech/kraken-media-inventory-facts.md personal/tech/kraken-truenas-media-copies.md personal/tech/lampa-jellyfin-plugin.md personal/tech/lampac-deployment.md personal/tech/lampac-torrserver.md personal/tech/llm-model-selection-2026.md personal/tech/mac-print-shared-services.md personal/tech/modbus-rtu-sniffer-debugging.md personal/tech/multistream-single-flow-limit.md personal/tech/multistream-single-flow-limit.md.bak-nedstab2 personal/tech/music-tags-repair-truenas.md personal/tech/obsidian-mcp-ecosystem.md personal/tech/original-xbox-2025-guide.md personal/tech/prowlarr-flaresolverr-cloudflare.md personal/tech/radarr-sonarr-phantom-records.md personal/tech/roundtrip-key-verification.md personal/tech/ryujinx-mac-setup.md personal/tech/skill-arr-media-stack-setup-additions.md personal/tech/skill-docker-data-root-mount-race.md personal/tech/skill-lampac-kraken-deploy.md personal/tech/tirith-trust.md personal/tech/truenas-local-tree-comparison.md personal/tech/truenas-nfs4-acl-and-arrmultiuser.md personal/tech/truenas-zfs-panic-recovery.md personal/tech/vault-doc-pruning.md personal/tech/vless-space-subscription-egress.md personal/tech/watchlist-sync-feed.md personal/tech/watchtower-docker-updates.md personal/tech/xray-outbound-subscription-3xui.md personal/tech/xray-reverse-limits-private-network.md personal/tech/xray-reverse-tunnel-kraken-truenas.md personal/tech/xray-reverse-tunnel-kraken-truenas.md.bak-nedstab2 personal/tech/yandex-music-api.md
2026-09-26 09:10:28 +00:00

78 KiB
Executable File
Raw Blame History

title, created, updated, type, namespace, tags, confidence, related, downgrade_to_26.4.25, verified_fix_2026_09_02
title created updated type namespace tags confidence related downgrade_to_26.4.25 verified_fix_2026_09_02
Xray Reverse Tunnel — Kraken ↔ TrueNAS 2026-09-01 2026-09-23 tech personal
xray
reverse
kraken
truenas
tunnel
networking
high
family/how-to/vps-qentra
family/how-to/truenas-infrastructure
family/how-to/kraken-access
family/how-to/rasputin-router
personal/tech/xray-outbound-subscription-3xui
portal+bridge BOTH pinned to 26.4.25; required but insufficient by itself. Kraken bridge must use Docker network_mode: host; Docker bridge/NAT reset the VLESS reverse mux. REALITY+Vision verified end-to-end with Kraken egress.

Xray Reverse Tunnel — Kraken ↔ TrueNAS

✅ 2026-09-23 — КАНАЛ ЖИВ, ПРОВЕРЕНО END-TO-END ПОСЛЕ ПОЧИНКИ 20.09. IP КРА́КЕНА ИЗМЕНИЛСЯ.

Первая проверка канала после фикса гонки docker↔mount (2026-09-20). Результат — работает.

Проверка Результат
SOCKS xray-reverse-portal:12345 → api.ipify.org (из контейнера в сети caddy_default) 92.62.77.233
TrueNAS напрямую curl https://api.ipify.org 90.189.160.148
Вывод IP разные ⇒ payload идёт через Кра́кен, канал живой
Portal netstat ::ffff:172.16.1.7:12346 ← ::ffff:92.62.77.233:32529 ESTABLISHED
xray-reverse-bridge (Кра́кен) Up, образ teddysun/xray:26.4.25, network_mode: host, uptime с 2026-09-20 16:30

🔴 IP Кра́кена ИЗМЕНИЛСЯ: 92.62.70.41 → 92.62.77.233. Прежний 92.62.70.41 зафиксирован во множестве мест этого документа и в family/how-to/* — при проверках брать актуальный из живого запроса, а не из доков.

Команды проверки (воспроизводимо, с TrueNAS):

ssh truenas_admin@mallexxx.duckdns.org \
  'docker run --rm --network caddy_default curlimages/curl:latest curl -s --max-time 20 \
   --socks5-hostname xray-reverse-portal:12345 https://api.ipify.org'
# ожидаем IP Кра́кена (92.62.77.233), НЕ 90.189.160.148 (TrueNAS)

ssh truenas_admin@mallexxx.duckdns.org \
  'docker exec xray-reverse-portal netstat -an | grep 12346'
# ожидаем ESTABLISHED от IP Кра́кена

Вывод для kraken-user

Правило kraken-user-via-reverse (user kraken-user → outbound via-kraken → SOCKS xray-reverse-portal:12345) прописано в шаблоне 3x-ui и, судя по живому каналу, должно работать. End-to-end с клиентом kraken-user в этой сессии НЕ перепроверялся — проверен только сам канал через SOCKS портала. Это разные вещи: канал может быть жив, а клиентский маршрут — нет.

Новый план использования этого канала — ❌ ЗАКРЫТ

Задача «доступ к 192.168.2.x как к локальным адресам» (запрос Alex 2026-09-23) разобрана в плане personal/plans/lan-access-via-reverse-tunnel. Итог: через Xray reverse не реализуется — портал отклоняет как forward-proxy (см. раздел «🚫 АРХИТЕКТУРНЫЙ ПРЕДЕЛ» ниже). Эксперимент откачен 2026-09-23.

🔧 ЭКСПЕРИМЕНТ 2026-09-23: ОТКАЧЕН, КАНАЛ НЕ ТРОНУТ (детали — в плане)

Обе правки конфигов были выполнены, завалидированы (xray run -test → Configuration OK.) и протестированы. Сквозной проход НЕ получился — вскрыт архитектурный предел (см. раздел ниже). По решению Alex всё откачено 2026-09-23; канал kraken-user вернулся в исходное рабочее состояние.

Что Файл Изменение (ОТКАЧЕНО)
Бридж (Кра́кен) /home/kraken/xray-reverse/config.json inbound lan-in: dokodemo-door, 0.0.0.0:12345, followRedirect:true + routing lan-in → conn → возвращён исходный (inbounds: false)
Портал (TrueNAS) /mnt/RED_2TB/docker/reverse-portal/config.json outbound direct + routing 192.168.2.0/24 → direct → возвращён исходный (local → reverse-out)
Хост Кра́кена iptables nat PREROUTING REDIRECT --to-ports 12345 → правило удалено, PREROUTING чист

Бэкапы (сохранены): /home/kraken/xray-reverse/config.json.bak-lan-in-20260923-130541, config.json.bak-v3-20260923-132753, /home/kraken/backups/iptables.bak-20260923-130541, /mnt/RED_2TB/docker/reverse-portal/config.json.before-lanroute.

🚫 АРХИТЕКТУРНЫЙ ПРЕДЕЛ Xray REVERSE: forward-proxy в приватную сеть ЗАПРЕЩЁН (2026-09-23)

Это не баг конфига, не версия и не REALITY. Это намеренная защита Xray, и её надо знать до того, как планировать подобные схемы.

Попытка: завернуть трафик клиентов 192.168.1.0/24 в адреса 192.168.2.x (сеть TrueNAS) через reverse-канал Кра́кен↔TrueNAS.

Результат — цепочка доходит до портала и там умирает:

Шаг Лог Итог
Mac → Кра́кен lan-in accepted tcp:192.168.2.197:80 [lan-in -> conn] ✅ перехват, трафик ушёл в туннель
Туннель → портал received request for tcp:192.168.2.197:80 ✅ дошло до TrueNAS
Портал выпускает for safety reasons, user a81c3179-… is not allowed to use forward proxy ❌ отклонено

Официальное обоснование (дока Xray, outbound freedom):

Traffic from VLESS reverse proxy blocks all targets by default. VLESS/VMess/Trojan/Shadowsocks inbounds block private and reserved IP ranges by default. To allow clients access to internal services, explicitly configure allow rules.

Почему это не обходится правкой правила: портал видит «клиент просит сходить на 192.168.2.197» и классифицирует это как forward proxy — попытку использовать сервер как открытый прокси. finalRules-allow в принципе позволяет обойти, но тогда «домашней» (внутренней) стороной обязан быть Кра́кен, а целевой сетью — его локалка 192.168.1.x. Цель 192.168.2.x при этом недостижима: reverse-канал выдаёт reverse-out на портале и reverse-in на бридже, а не наоборот.

Вывод: направление задачи («в подсеть TrueNAS из сети Кра́кена») не совпадает с направлением, которое поддерживает reverse-архитектура. Через Xray reverse это не реализуется — нужна другая технология (WireGuard / обычный forward-прокси на клиенте).

Релевантный use case из доки — только «Remote Return Home» (xtls.github.io/en/document/level-2/vless_reverse.html, Use Case 2): клиент → публичный сервер → reverse-out → туннель → внутреннее устройство → его локалка. Ровно это и описано выше.

Рассмотренные и отклонённые альтернативы (2026-09-23):

# Вариант Почему не выбран
1 Отказаться, откатить ✅ выбрано Alex
2 SOCKS на стороне клиента (Mac) через vless-proxy :1080 / xray-admin не «через ASUS»; нужен SOCKS-aware клиент или routing на Mac; не работает для других устройств
3 WireGuard на TrueNAS (белый IP + порт есть) даёт полный IP-стек (ICMP, UDP, Samba-обзор) — открытый вариант, если задача вернётся; минус — новая служба на TrueNAS (RAM 17/21 ГБ, на пределе)

Питфоллы, добытые в этом эксперименте (применимы к любой подобной задаче)

Питфолл Суть
dokodemo-door + 127.0.0.1 не принимает REDIRECT-трафик Пакет приходит с внешнего адреса клиента (192.168.1.57) — bind на loopback его отвергает (HTTP 000 за 0.005 с). Нужен listen: 0.0.0.0 (+ firewall).
iptables nat PREROUTING не действует на локально-исходящий трафик Проверка curl с того же хоста, где стоит правило = ложный негатив: счётчик 0. Нужен посторонний хост либо транзит (netns / контейнер с кастомным маршрутом).
redirect: "" в freedom — невалидно Пустая строка ломает конфиг. Не использовать как «не менять адрес».
xray run -test читает stdin Под SSH виснет без < /dev/null. Касается и валидации, и любого sudo.
sudo через SSH на Кра́кене Требует < /dev/null; иначе Connection closed by remote host / Broken pipe. Документированный питфолл — повторён дважды за сессию.
На Кра́кене нет ifconfig Каждый вызов печатает command not found в stderr (засоряет вывод, безвредно). Использовать ip/ip addr.
Тест PHY/транзита на однохостовой машине Для эмуляции «другого хоста в сети» использован ip netns + veth — рабочий приём; обязательно убирать за собой (ip netns del, ip link del).

✅ 2026-09-20 — КОРЕНЬ 2026-09-15 НАЙДЕН: ГОНКА Docker ↔ mount, НЕ конфиг и НЕ версия

Симптом: kraken-user не выходил (portal на TrueNAS жив, но от бриджа — ноль звонков на 12346).

Истинная причина (не имеет отношения к Xray/REALITY/версиям): dockerd на Kraken стартовал на 26 с раньше, чем смонтировался USB-HDD с data-root, поэтому загрузил 0 контейнеров — включая xray-reverse-bridge. Бриджа просто не было запущено → канал не поднимался → reverse-out не создавался → curl через SOCKS пусто.

Событие Время
Boot Kraken Sep 15 17:29:17
dockerd (PID 1324) старт 17:31:01
Диск sda1 смонтирован 17:31:27

Доказательства целостности: docker-data/containers/ = 4.7G, 35 контейнеров целы, включая xray-reverse-bridge и cloudflared; образ teddysun/xray:26.4.25 на месте. docker info врёт Containers=0.

Дефекты конфига, породившие гонку: docker.service без RequiresMountsFor=; дубль строки 6194539b в /etc/fstab.

Что это НЕ: это не регрессия #6242, не REALITY mismatch, не network_mode — все прежние гипотезы по 2026-09-15 снимаются. Проверенный фикс 2026-09-02 (26.4.25 + network_mode: host) остаётся в силе и не трогается.

План и статус (обновлено 2026-09-20): ✅ ВЫПОЛНЕНО И ПРОВЕРЕНО.

  1. ✅ Backup → /home/kraken/backups/docker-recovery-20260920-105228/.
  2. ✅ systemctl restart docker → 25 контейнеров загружены, 12 Up (в т.ч. xray-reverse-bridge).
  3. ✅ Drop-in /etc/systemd/system/docker.service.d/mounts.conf с RequiresMountsFor= + After= маунт-юнита → проверено systemctl show docker -p Requires -p After (маунт в обоих). Гонка закрыта, reboot-безопасно.
  4. ✅ fstab: убран дубль строки 6194539b (+ дубль bind-mount journal). ⚠️ docker start вручную не потребовался: RestartPolicy в daemon state есть (unless-stopped), контейнеры поднялись сами. Ранее записанное «RestartPolicy=null» — ошибка чтения hostconfig.json (он не отражает живую политику). Полный план и команды — family/how-to/kraken-access, секция «2026-09-20».

Урок диагностики: если portal пишет non existing outTag: reverse-out и «ноль соединений на 12346» — сначала проверять, жив ли контейнер xray-reverse-bridge на Kraken (docker ps), а не конфиг. 2026-09-15 этот шаг был пропущен: записали «Kraken недоступен → ждать», хотя машина была жива по LAN (192.168.1.15), а не запущен был только docker-контейнер бриджа.

🔴 2026-09-15 — ТУННЕЛЬ НЕ РАБОТАЕТ: KRAKEN НЕДОСТУПЕН (не конфиг) [СУПЕРСИДЕНО 2026-09-20 — см. выше]

Клиент kraken-user перестал выходить в интернет. Причина — не конфиг портала и не 3x-ui: хост Kraken недоступен по всем путям (SSH через ssh-kraken.qentra.top → timed out during banner exchange; 10.99.1.2:22 → Operation timed out; DNS kraken → NXDOMAIN).

Что Состояние
xray-reverse-portal (TrueNAS) ✅ Up 13 дней, 12345 + 12346 в LISTEN, конфиг цел
Соединения от бриджа на 12346 ❌ ноль — от Kraken никто не звонит
Выход через SOCKS 12345 ❌ пусто (норма — 92.62.70.41)

Диагностика (короткая):

docker exec xray-reverse-portal netstat -an | grep 12346        # пусто = бридж молчит
curl -s --max-time 20 --socks5-hostname 127.0.0.1:12345 https://api.ipify.org

⚠️ Не принимать за поломку: в логах портала будет app/dispatcher: non existing outTag: reverse-out — это ожидаемо, пока бридж не подключён. Тег reverse-out объявлен в inbounds[interconn].clients[0].reverse.tag (не в .outbounds) и создаётся Xray'ем автоматически только при живом бридже. Конфиг портала править НЕ нужно.

Дальше: проверять Kraken через панель хостинга/консоль провайдера. Решение Alex (2026-09-15): «подождём, может оживет». Статус прошлой проверки (2026-09-02) — ниже.

🔀 НЕ ПУТАТЬ с egress-подпиской (2026-09-15)

У xray-admin три независимых механизма выхода, их легко перепутать:

Механизм Кто выходит Док
user1 → outbound direct клиент выходит через TrueNAS 90.189.160.148 ниже
kraken-user → via-kraken → этот reverse-туннель клиент выходит через Кра́кен 92.62.70.41 этот док
vless-space → space-balancer (space-01…10) клиент выходит через внешнюю подписку profilegrid.net personal/tech/xray-outbound-subscription-3xui

Reverse-туннель (portal на TrueNAS + bridge на Кра́кене) — отдельные контейнеры, xray-admin его лишь использует как outbound via-kraken (SOCKS xray-reverse-portal:12345). Подписочный клиент vless-space reverse-туннель не задействует.

Статус: ✅ ВНЕДРЕНО И ПРОВЕРЕНО END-TO-END (2026-09-02). TrueNAS SOCKS :12345 → VLESS Reverse TCP+REALITY+Vision → Kraken → internet работает. HTTP и HTTPS тесты оба вернули выходной IP Kraken 92.62.70.41. Истинная причина: Docker bridge/NAT на Kraken сбрасывал reverse mux; bridge должен работать с network_mode: host. Более ранние секции со статусом «не работает» и гипотезами #6612/#6242 сохранены ниже как история диагностики и суперсидированы секцией «Верифицированный фикс». Архитектурное решение: проксировать исходящий трафик локальных клиентов сети TrueNAS через TrueNAS → Kraken → интернет.

✅ ВАЖНО (2026-09-02): xray-admin (3x-ui) на TrueNAS — это ОДНОВРЕМЕННО РАБОЧИЙ САМОСТОЯТЕЛЬНЫЙ Xray-VPN-сервер

Путаница в вопросе юзера выявила: vpn.mallexxx.duckdns.org:443 — это не только reverse-frontend, а полноценный Xray-сервер со своим собственным выходом в интернет (outbound freedom/direct → сразу через TrueNAS), НЕ зависящий от reverse-канала к Kraken. Это отдельная фича, параллельная reverse-туннелю.

  • Проверено end-to-end 2026-09-02 (временный xray-клиент с Mac): VLESS+WS через vpn.mallexxx.duckdns.org:443 → HTTP 200, выход IP 90.189.160.148 = TrueNAS. Контейнеры xray-admin (Up 21h) + caddy (Up 20h) живы.
  • Inbound in-10095-tcp (VLESS-WS): client id ce320965-6956-4759-84bb-7cb71cfc6252 (user1), security: none, path /vless, host vpn.mallexxx.duckdns.org. TLS терминирует Caddy → в клиенте network: ws + TLS на домен, без двойного TLS внутрь.
  • Полные параметры и pitfalls (вкл. удаление allowInsecure в Xray 26.7.28) — в family/how-to/truenas-infrastructure.md, раздел xray-admin.
  • Reverse к Kraken — это ОТДЕЛЬНЫЙ механизм (для проксирования локальных клиентов сети TrueNAS через Kraken-egress). Он теперь также внедрён и проверен; см. «Верифицированный фикс». 3x-ui-сервер остаётся независимым рабочим VPN-выходом через TrueNAS.

🔴 2026-09-20 — ВЕРХНЯЯ ТОЧКА ВХОДА: оба туннеля были down из-за ГОНКИ DOCKER↔СМОНТИРОВАНИЕ ДИСКА. ФИКС ПРИМЕНЁН.

Симптом: vless reverse proxy kraken→truenas не работает И cloudflared ssh tunnel down. Kraken доступен по LAN (192.168.1.15, hostname kraken).

Корень — НЕ конфиги Xray и НЕ cloudflared. Одна причина на оба симптома: dockerd стартовал раньше, чем монтировался USB-диск с docker-data, и загружал пустое состояние → 0 контейнеров в памяти.

Событие Время (boot Sep 15)
Boot Kraken 17:29:17
sda1 виден ядром +130 с → 17:31:27
dockerd PID 1324 стартовал 17:31:01 ← на 26 с РАНЬШЕ диска
Диск смонтирован 17:31:27

Почему оба туннеля: cloudflared и xray-reverse-bridge просто не были загружены. Не падали — их не существовало для daemon.

Ничего не потеряно: containers/ = 4.7G, 35 контейнеров целы, образы, 32 volume. Daemon их просто не видел.

Диагностический признак (запомнить): docker ps -a пусто, но docker-data/containers/ полон → это всегда гонка data-root, а не потеря данных. Проверять: docker info --format "{{.DockerRootDir}} | containers={{.Containers}}" vs содержимое docker-data/containers/.

✅ ФИКС (применён, проверен)

  1. Backup: /home/kraken/backups/docker-recovery-20260920-105228/ (fstab, daemon.json, xray-reverse).
  2. Немедленно: sudo systemctl restart docker → диск уже смонтирован → все контейнеры загрузились.
  3. Защита от повтора при reboot — создан drop-in /etc/systemd/system/docker.service.d/mounts.conf:
    [Unit]
    RequiresMountsFor=/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker-data
    After=srv-dev\x2ddisk\x2dby\x2duuid\x2d6194539b\x2d03e0\x2d4f33\x2d986b\x2d4da09834e82f.mount
    
    Проверено: systemctl show docker -p Requires -p After → маунт-юнит в Requires И After. dockerd физически не стартует раньше диска.
  4. fstab — убран ДУБЛЬ строки для 6194539b (внизу была ручная UUID=6194539b... вне OMV-блока → «Duplicate entry in fstab» в journal) и дубль bind-mount /var/log/journal. Осталось 1 вхождение (OMV-блок). Грепом проверено.

Проверка после фикса

sudo systemctl restart docker → containers=25, 11-12 Up. Критичные поднялись автоматом: cloudflared, xray-reverse-bridge, jellyfin, sonarr, radarr, prowlarr, portainer, transmission, rclone, watchtower, flaresolverr. ⚠️ hermes-kraken — Restarting (1) (crash-loop, не связан с этой задачей, был до правок).

Питфолл: RestartPolicy в hostconfig.json показывает null (reflection исходного docker run), но в state policy есть — при рестарте daemon контейнеры поднимаются сами. Не пугаться null.

Питфолл диагностики: ls docker-data требует sudo (root:root 711). sudo -n работает без апрува — использован sudo -n ls/jq.

Урок: USB-диск на этом узле поднимается ~130 с. Любой сервис, зависящий от docker-data на этом диске, ОБЯЗАН иметь RequiresMountsFor. Без него — та же гонка.

Контекст / Почему

  • 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:

@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 опровергнута.

🔑 КОРЕНЬ ПРОБЛЕМЫ НАЙДЕН (2026-09-01, интернет-поиск) — issue XTLS/Xray-core #6612

Симптомы точно совпадают с #6612: reverse-канал устанавливается (udp:reverse:0 на месте), но TCP-payload не проходит; portal логирует accepted tcp:... -> reverse-out, а bridge НЕ получает входящих reverse-in-соединений; curl → 000.

Причина: начиная с Xray v26.5+ (PR #6027) у outbound freedom/direct появилась дефолтная политика безопасности, которая блокирует ВСЕ цели для трафика VLESS Reverse, если не задан явный finalRules. Контрольный reverse-канал при этом продолжает устанавливаться — поэтому «всё выглядит подключённым», но реальный payload молча отбрасывается. Это ровно наш случай на версии 26.7.28.

Точный фикс — добавить в freedom direct на BRIDGE (место реального egress из reverse-in в интернет):

{
  "protocol": "freedom",
  "tag": "direct",
  "settings": {
    "domainStrategy": "AsIs",
    "finalRules": [ { "action": "allow" } ]
  }
}

Issue говорит прямо: проблема воспроизводится с обычным Freedom без finalRules вообще, и добавление безусловного allow чинит на 26.7.28.

Релевантные ссылки:

  • #6612 — главный фикс: https://github.com/XTLS/Xray-core/issues/6612
  • #6027 — корень (finalRules у Direct/Freedom): https://github.com/XTLS/Xray-core/pull/6027
  • Документация freedom: https://xtls.github.io/en/config/outbounds/freedom.html
  • 3x-ui разбор под reverse: https://github.com/MHSanaei/3x-ui/issues/4782
  • #2664 — если finalRules не поможет: flow: xtls-rprx-vision на BRIDGE-outbound + REALITY может ломать доставку (держите flow:"" на reverse-клиенте): https://github.com/XTLS/Xray-core/issues/2664
  • Регрессия роутинга reverse v26.5+ (если фикс не поможет): #6242, #6195, #6248 — временный кварк: пинить v26.4.25.

Важные детали из поиска (проверить при продолжении):

  • Портал ДОЛЖЕН иметь placeholder-freedom (у нас есть) — иначе reverse-out станет default. Плейсхолдеру не нужен finalRules:allow (он обслуживает только несопоставленный трафик).
  • Роутинг inboundTag:["reverse-in"] -> direct на bridge — нужен (у нас есть).
  • У VLESS outbound поле encryption обязательно ("none" или парный PQ-ключ к серверному decryption) — у нас "none", ок.

✅ ФИКС ПРИМЕНЁН, но заблокирован (2026-09-01)

Новый bridge-конфиг с finalRules:[{action:"allow"}] в direct залит на Kraken (/home/kraken/xray-reverse/config.json, 1098 байт, проверено cat | head -5). НО:

  • ⛔ Kraken по docker НЕДОСТУПЕН: systemctl is-active docker → activating (не active), демон застрял, накоплено множество зависших docker-процессов (ps/run/compose).
  • Причина: USB-HDD снова не поднялся — lsblk /dev/sda → 0B (без раздела). Docker data-root = /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker-data (на этом HDD) → daemon ждёт диск и застревает.
  • ⚠️ Замечено расхождение UUID: сейчас data-root указывает на /srv/dev-disk-by-uuid-49e8f586-..., а в контексте ранее фигурировал смонтированный HDD /srv/dev-disk-by-uuid-6194539b-... (sda1 1.8T). Текущий sda = 0B без раздела.
  • docker compose down/up для bridge не выполнен — контейнер всё ещё со старым конфигом (больше не деплоится, daemon не отвечает).

Шаг для продолжения (требует подтверждения Alex): починить HDD/docker на Kraken (повторить утренний сценарий: sudo reboot или физическое переподключение USB-диска), затем пересоздать bridge-контейнер (cd /home/kraken/xray-reverse && docker compose down && docker compose up -d), затем тест curl --socks5 127.0.0.1:12345 http://api.ipify.org на TrueNAS → ожидаем выход с IP Kraken.

Статус: задание НЕ завершено — остаётся применить bridge-фикс после восстановления docker на Kraken.

✅ 2026-09-02: Kraken восстановлен (диск/docker) + фикс #6612 применён — НО payload всё равно мёртв → ИСТИННЫЙ КОРЕНЬ #6242 (bridge-side v26.5+)

Kraken полностью поднялся (проверено живьём по SSH)

  • Uptime 2 мин — Kraken перезагрузился (USB-HDD-сценарий). systemctl is-active docker был activating первые минуты (ждал поднятия диска), затем стал active.
  • Диск /dev/sda1 поднялся: 1.8T, смонтирован к /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f, 235G свободно (87% занято). (В отличие от 2026-09-01, когда sda был 0B.)
  • Все контейнеры восстановились (в прошлый раз — 0): transmission, sonarr, prowlarr, homeassistant, jellyfin, radarr, hermes-kraken, portainer, rclone, cloudflared, flaresolverr, watchtower, xray-reverse-bridge. Docker Root Dir /srv/dev-disk-by-uuid-6194539b-.../docker-data.
  • Bridge-конфиг содержит фикс #6612: /home/kraken/xray-reverse/config.json → freedom/direct с "finalRules":[{"action":"allow"}].
  • Reverse-канал к TrueNAS жив: bridge лог 2026-09-02 13:12: dialing TCP to mallexxx.duckdns.org:12346 → tunneling request → received request for udp:reverse:0. Bridge = Xray 26.7.28 (teddysun/xray:latest).

Portal (TrueNAS) — состояние

xray-reverse-portal Up 22h, reverse-канал от Kraken держится. Лог portal: accepted tcp:8.6.112.0:80 [local -> reverse-out] — запрос с локального SOCKS-входа уходит в reverse-out (в сторону Kraken). Конфиг portal без изменений (interconn :12346 REALITY client a81c3179... reverse-out; local :12345 SOCKS; routing local→reverse-out; placeholder-freedom). Сеть caddy_default, curl-контейнер в ней резолвит xray-reverse-portal:12345 = 172.16.1.7.

❌ End-to-end payload по-прежнему НЕ проходит (даже с фиксом #6612)

Тест временным контейнером curlimages/curl в сети caddy_default на TrueNAS:

docker run --rm --network caddy_default curlimages/curl:latest curl -sv --socks5-hostname xray-reverse-portal:12345 -m 20 http://api.ipify.org

→ verbos: Opened SOCKS connection from 172.16.1.8 port ... to api.ipify.org port 80 (via 172.16.1.7 port 12345) → Request completely sent off → Empty reply from server (соединение закрыто без ответа). Трафик доходит до portal, уходит в reverse-out, НО не возвращается от bridge → ответ теряется.

🔑 ИСТИННЫЙ КОРЕНЬ (2026-09-02, интернет-поиск): issue XTLS/Xray-core #6242 — регрессия bridge в v26.5+

Симптомы точно совпадают с issue #6242 (закрыта "not planned"):

  • Регрессия только на стороне BRIDGE (outbound-initiating), версия portal не важна.
  • С v26.5+ (и 26.6.x) bridge стартует без ошибок, reverse-канал вроде устанавливается (udp:reverse:0), но трафик не маршрутизируется через reverse tunnel. Ровно наш случай на 26.7.28.
  • Понижение ТОЛЬКО bridge до v26.4.25 мгновенно возвращает полную работу без изменений конфига.
  • Связано с #5750 (BurstObservatory не успевает health-check динамически регистрируемых rproxy-* outbound'ов — до 10 мин) и обсуждением #5962 (stale-tunnel mappings после рестартов). PR #5101 прямо предупреждал: "reverse sub-protocol unstable, will break, кросс-версий совместимости НЕ гарантировано".
  • Почему фикс #6612 не помог: #6612 (finalRules:allow) лечит ДРУГУЮ проблему (Freedom блокирует payload) — мы её уже устранили. Но осталась регрессия маршрутизации #6242, которую finalRules не обходит.

Решение/кварк: сдаунгрейд bridge до Xray 26.4.25 (образ teddysun/xray:26.4.25, существует на Docker Hub / GitHub Container Registry ghcr.io/xtls/xray-core:26.4.25). Portal-сторона (26.7.28) остаётся.

План внедрения (согласован с Alex — что НЕ трогать vpn.mallexxx и xray-admin)

  1. На Kraken: остановить xray-reverse-bridge контейнер.
  2. В /home/kraken/xray-reverse/docker-compose.yml сменить образ teddysun/xray:latest → teddysun/xray:26.4.25.
  3. cd /home/kraken/xray-reverse && docker compose up -d (пересоздаст bridge на 26.4.25).
  4. Проверить reverse-канал: bridge лог udp:reverse:0.
  5. Контрольный end-to-end: временный curl-контейнер в сети caddy_default на TrueNAS через xray-reverse-portal:12345 → ожидаем выход с IP Kraken (92.62.70.41), НЕ IP TrueNAS. ⛔ НЕ трогать: xray-admin / vpn.mallexxx / Caddy / portal.

⚠️ Важное прояснение для будущих сессий (из этого диалога)

Запрос юзера "не могу подключиться к xray на truenas до наших измерений" — это была путаница между тремя разными сущностями:

  1. vless-proxy (teddysun/xray, SOCKS :1080/:1081, outbound на удалённый VPS qentra.top) — мёртв из-за удаления VPS 2026-09-01.
  2. xray-admin (3x-ui) = самостоятельный рабочий Xray-VPN из интернета через vpn.mallexxx.duckdns.org:443 (см. секцию «ВАЖНО 2026-09-02» выше). Жив, end-to-end проверен.
  3. reverse-туннель TrueNAS↔Kraken (portal xray-reverse-portal + bridge на Kraken) — это про проксирование egress ЛОКАЛЬНЫХ клиентов сети TrueNAS через Kraken. НЕ связан с vpn.mallexxx.

🔴 2026-09-15 (вечер): KRAKEN НЕДОСТУПЕН — kraken-user отвалился НЕ из-за правок БД

Симптом: Alex сообщил «не работает больше vless-ws-kraken-user, даже из бэкапа». Логичное подозрение — мои правки БД 3x-ui. Подозрение опровергнуто фактами.

Диагностика (по порядку, все — факт):

Проверка Результат
docker ps на TrueNAS xray-reverse-portal Up 13 days, xray-admin Up, caddy Up. xray-reverse-bridge отсутствует (он на Kraken)
порт 12345 (SOCKS) LISTEN ✅
порт 12346 (interconn) LISTEN ✅
выход через SOCKS :12345 → api.ipify.org ❌ пусто (ни IP, ни ошибки)
netstat соединений на 12345 много CLOSE_WAIT от 172.16.1.5 — сессии оборваны, новых нет
соединений от бриджа на 12346 ❌ НОЛЬ (бридж не звонит)
логи портала app/dispatcher: non existing outTag: reverse-out + from tcp:172.16.1.5:… [local -> reverse-out]
TrueNAS напрямую 90.189.160.148 ✅ (интернет на NAS есть)
ssh kraken@10.99.1.2 ❌ Operation timed out
ssh ssh-kraken.qentra.top (cloudflared) ❌ Connection timed out during banner exchange
DNS host kraken ❌ NXDOMAIN

🔴 ВЫВОД: хост Kraken недоступен по ОБОИМ задокументированным путям (WG-адрес 10.99.1.2 и cloudflared-туннель ssh-kraken.qentra.top). kraken-user не работает, потому что машина Kraken выключена/недоступна, а не из-за правок в x-ui.db. Совпадение по времени.

ВАЖНО про non existing outTag: reverse-out: это НЕ дефект конфига портала. В reverse-схеме Xray тег reverse-out объявляется не в outbounds[], а в clients[].reverse.tag инбаунда interconn — и создаётся только когда бридж подключён. Ошибка = бридж не подключён. Конфиг портала (/mnt/RED_2TB/docker/reverse-portal/config.json, 1287 б, бинд-маунт :ro) корректен, проверено 2026-09-15.

⚠️ Сделано по ходу диагностики (требует внимания): выполнен docker restart xray-reverse-portal — портал перезапущен, но CLOSE_WAIT ушли, а новых соединений от Kraken не появилось (ожидаемо: машины нет). Портал после рестарта — Up, оба порта LISTEN. Рестарт портала сам по себе проблему не решает — она на стороне Kraken.

Что проверять, когда Kraken вернётся:

# 1) канал поднялся?
docker exec xray-reverse-portal sh -c 'netstat -an' | grep 12346
# 2) output жив?
curl -s --max-time 20 --socks5-hostname 127.0.0.1:12345 https://api.ipify.org
# ожидаем: 92.62.70.41

Питфолл диагностики: curl --socks5-hostname 127.0.0.1:12345 на TrueNAS не проверяет туннель, если портал сам не может выйти — надо сравнивать с curl напрямую (90.189.160.148), иначе не отличить «портал сломан» от «Kraken недоступен».

❌ ИСТОРИЯ ДИАГНОСТИКИ 2026-09-02: downgrade сам по себе не помог

⚠️ ВАЖНО: вопреки секции «ИСТИННЫЙ КОРЕНЬ #6242» выше (которая была гипотезой, ещё не проверенной полностью), полный downgrade обеих сторон до Xray 26.4.25 payload НЕ починил. Это зафиксировано здесь как фактический итог.

Что было сделано (выполнено по факту, alive-диагностика)

По согласованию с Alex (не трогая vpn.mallexxx / xray-admin) выполнено:

  1. Bridge (Kraken): /home/kraken/xray-reverse/docker-compose.yml → образ teddysun/xray:26.4.25. Docker Pull прошёл, контейнер на 26.4.25 (Xray 26.4.25 ... go1.26.2 linux/arm64). Бэкап: docker-compose.yml.bak-26.7.28.
  2. Portal (TrueNAS): /mnt/RED_2TB/docker/reverse-portal/docker-compose.yml → тоже teddysun/xray:26.4.25 (Linux amd64, образ 21.59MB Pull). Бэкап: docker-compose.yml.bak-26.7.28. Контейнер xray-reverse-portal пересоздан.
  3. Portal config.json loglevel поднят на debug (для диагностики), залит в /mnt/RED_2TB/docker/reverse-portal/config.json.
  4. Локальные копии файлов на Mac (для правки): ~/xray-test/ → docker-compose.bridge.yml, docker-compose.portal.yml, portal.config.json, config.json (тестовый клиент vpn.mallexxx, удалить не нужно).
  5. После смены версии bridge перезапущен (для переустановки reverse-канала к новому portal).

Результат end-to-end теста (обе стороны 26.4.25)

  • Reverse-канал у bridge устанавливается: лог dialing TCP to mallexxx.duckdns.org:12346 → tunneling request to unknown → received request for udp:reverse:0. Portal принимает (лог: proxy/vless/inbound: received request for tcp:v1.rvs.cool:0 → dispatching request to udp:reverse:0).
  • НО payload по-прежнему НЕ проходит: тест curl через xray-reverse-portal:12345 → Empty reply from server / exit=52.
  • Portal (TrueNAS) debug-лог полностью проясняет картину:
    • При запросе: [118463829] proxy/socks: TCP Connect request to tcp:api.ipify.org:80 → [118463829] app/dispatcher: taking detour [reverse-out] for [tcp:api.ipify.org:80] — и НИЧЕГО дальше (ни ошибки, ни dial к bridge). Dispatch в reverse-out молча глотается.
    • Фоновые разрывы: common/mux: failed to read metadata > read tcp 172.16.1.7:12346->92.62.70.41:3266: connection reset by peer — portal пытается что-то слать к bridge, но канал рвётся.
  • Критично: на TrueNAS НЕТ постоянного ESTABLISHED TCP-соединения от bridge на :12346 (ss -tn sport=:12346 пусто). Reverse-канал НЕ держится постоянным — устанавливается эфемерно (per контрольный UDP прочёт), и data-stream по нему не доходит до bridge.
  • Bridge (Kraken) никогда не логирует приём reverse-in TCP-payload (только контрольный udp:reverse:0).

Вывод

Проблема НЕ регрессия #6242 фиксируемая версией bridge — иначе downgrade до рабочей по issue пары 26.4.25↔26.4.25 решил бы. После полного downgrade payload по-прежнему мёртв. Настоящая причина: reverse-канал portal↔bridge не удерживается постоянным на TCP-уровне (нет стабильного ESTABLISHED :12346), поэтому dispatch портала в reverse-out не находит живой транспорт до bridge и молча теряет данные.

Это согласуется с предупреждением PR #5101: новый VLESS Reverse sub-protocol itself нестабилен («will break, кросс-версий совместимость не гарантирована») — по-видимому канал между двумя разнесёнными docker-реализациями (Kraken arm64 ↔ TrueNAS amd64, обе 26.4.25) не держится стабильно.

Дальнейшие гипотезы (НЕ проверены, треб.WB)

  1. Транспортный REALITY mismatch arm64(26.4.25 bridge) ↔ amd64(26.4.25 portal) даёт нестабильный mux → попробовать не-REALITY (простой TCP, т.к. канал только между сервисами TrueNAS↔Kraken, не извне) — убрать REALITY, оставить VLESS-TCP без camouflage.
  2. Перепроверить, что bridge реально удерживает единственное mux-соединение (в xray reverse bridge обычно держит persistent канал, у нас его нет → пере-аудит конфиг bridge: возможно не хватает чего-то, заставляющего держать канал постоянно).
  3. Запросить консультацию/повторно изучить рабочую конфигурацию сбора из живого разбора темы (потому что каноничные примеры из доки и issues не дали полного рабочего egress-конфига).

⚠️ ТЕКУЩЕЕ СОСТОЯНИЕ СИСТЕМ (на момент записи, 2026-09-02)

  • Версии: BOTH portal и bridge сейчас на teddysun/xray:26.4.25 (исходно были на :latest = 26.7.28). Откат при необходимости: поменять образ в compose обратно на teddysun/xray:latest и docker compose up -d.
  • Конфиг portal имеет loglevel: debug (пока). Bridge config.json содержит фикс #6612 finalRules:allow.
  • vpn.mallexxx.duckdns.org / xray-admin / Caddy — НЕ тронуты, работают (см. секцию «ВАЖНО 2026-09-02»).
  • Reverse к Kraken НЕ внедрён/не работает end-to-end — это остаётся открытой задачей.

⏳ Открытые вопросы по 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/<app>/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-02: systemctl is-active docker → active, диск /dev/sda1 1.8T смонтирован к /srv/dev-disk-by-uuid-6194539b-..., 235G свободно (87% занято). Все контейнеры восстановились (в отличие от 2026-09-01, когда было 0): transmission, sonarr, prowlarr, homeassistant, jellyfin, radarr, hermes-kraken, portainer, rclone, cloudflared, flaresolverr, watchtower, xray-reverse-bridge (Up).
  4. ✅ End-to-end payload проходит. #6612/#6242 оказались неполными гипотезами. Верифицированный корень — Docker bridge/NAT на Kraken; решение — Xray 26.4.25 + network_mode: host на bridge. См. authoritative-секцию ниже.

🚧 2026-09-23 — ГРАНИЦА ВОЗМОЖНОСТЕЙ: reverse НЕ работает как «вход в чужую приватную сеть»

Попытка: завернуть клиентов 192.168.1.0/24 (за ASUS) на адреса 192.168.2.x через этот reverse-туннель — то есть использовать его как «вход в сеть TrueNAS».

Результат: невозможно по дизайну. План и полный разбор — personal/plans/lan-access-via-reverse-tunnel.

Механизм отказа (воспроизведён вживую):

портал: for safety reasons, user a81c3179-… is not allowed to use forward proxy

Официальная дока Xray (freedom outbound):

Traffic from VLESS reverse proxy blocks all targets by default. Traffic from VLESS/VMess/Trojan/Shadowsocks/Hysteria/WireGuard inbounds blocks private and reserved IP ranges by default. To allow clients access to internal services, explicitly configure allow rules.

То есть reverse намеренно не даёт ходить в приватные сети — защита от превращения сервера в открытый прокси. Это не баг конфига и не лечится версией Xray.

Единственная рабочая конфигурация reverse (Use Case 2, «Remote Return Home»):

клиент → PUBLIC SERVER (портал) → reverse-out → туннель
                                                    ↓
                              INTERNAL DEVICE (бридж)
                                                    ↓
                           freedom + finalRules[allow ip <локальная сеть>]
                                                    ↓
                                         <сеть «внутренней» стороны>

Целевая сеть — локалка «внутренней» стороны (здесь — Кра́кен, 192.168.1.0/24), не сеть публичной стороны. Направление «пойти в сеть TrueNAS снаружи» reverse-каналом не решается.

Что это НЕ задевает: существующие сценарии работают как раньше — kraken-user (egress через Кра́кен) использует reverse-in → direct и не затронут; user1 / vless-space — вообще другой механизм (direct / подписка).

✅ Побочный факт: канал впервые проверен end-to-end после починки 2026-09-20

через SOCKS портала: 92.62.77.233 ≠ напрямую с TrueNAS 90.189.160.148. ⚠️ WAN-IP Кра́кена изменился: 92.62.70.41 → 92.62.77.233. Везде в этом доке и в kraken-access.md фигурирует старый — при следующей правке актуализировать.

✅ Верифицированный фикс 2026-09-02 (authoritative)

Эта секция суперсидирует все более ранние выводы «payload мёртв», «нет persistent ESTABLISHED» и предполагаемые корни #6612/#6242. Фикс найден и проверен живыми A/B-тестами.

Истинная причина

xray-reverse-bridge на Kraken работал в обычной Docker bridge-сети. Docker bridge/NAT на этом узле сбрасывал long-lived VLESS reverse mux после успешной регистрации udp:reverse:0. Поэтому portal создавал reverse-out, но payload не доходил до reverse-in.

Ключевой A/B-тест:

  1. Тот же JSON на temporary bridge amd64 внутри TrueNAS заработал сразу → portal/config/routing исправны.
  2. Тот же Xray 26.4.25 arm64 + тот же JSON на Kraken в --network host заработал сразу → CPU architecture и WAN исправны, отличие только в Docker network mode.
  3. После возврата REALITY+Vision туннель остался рабочим → проблема не в REALITY, Vision или TCP transport.

Постоянная конфигурация

Kraken: /home/kraken/xray-reverse/docker-compose.yml

services:
  xray-reverse-bridge:
    image: teddysun/xray:26.4.25
    network_mode: host

Bridge config возвращён к защищённому VLESS TCP + REALITY + flow: xtls-rprx-vision. direct сохраняет finalRules: [{"action":"allow"}]. Portal на TrueNAS также на teddysun/xray:26.4.25, REALITY+Vision. xray-admin, Caddy и vpn.mallexxx.duckdns.org не менялись.

network_mode: host расширяет сетевые права bridge-контейнера. В этом конфиге у него нет физических listening inbounds; reverse-in — виртуальный inbound Xray. Не добавлять в этот контейнер обычные inbounds без аудита bind address/firewall.

Финальная проверка

2026-09-02 после permanent Compose deploy:

  • docker inspect xray-reverse-bridge → image teddysun/xray:26.4.25, network host, status running, restart count 0.
  • Bridge лог: received request for udp:reverse:0, затем TCP payload принят в reverse-in -> direct.
  • HTTPS через SOCKS xray-reverse-portal:12345 → 92.62.70.41.
  • HTTP через тот же SOCKS → 92.62.70.41.
  • 92.62.70.41 — публичный egress Kraken; TrueNAS egress 90.189.160.148 не использовался.

Бэкапы и rollback

Kraken:

  • /home/kraken/xray-reverse/docker-compose.yml.bak-bridge-network-20260902-1147
  • /home/kraken/xray-reverse/config.json.bak-plain-host-working-20260902-1146
  • /home/kraken/xray-reverse/config.json.bak-reality-vision-20260902-1142

TrueNAS:

  • /mnt/RED_2TB/docker/reverse-portal/config.json.bak-plain-host-working-20260902-1146
  • /mnt/RED_2TB/docker/reverse-portal/config.json.bak-reality-vision-20260902-1142

Rollback network fix: вернуть compose-бэкап на Kraken и выполнить docker compose up -d. Это вернёт нерабочий Docker bridge mode, поэтому делать только для диагностики/отката.

✅ Subscription-канал (auto-обновление клиентов) — 2026-09-15

Проверено живьём: клиенты панели отдаются ссылкой подписки, а не только одиночным vless://.

Клиент Ссылка подписки Egress
user1 https://vpn-panel.mallexxx.duckdns.org/sub/68c5cy5n5ui138yh direct → TrueNAS 90.189.160.148
kraken-user https://vpn-panel.mallexxx.duckdns.org/sub/f43074a029dc656e via-kraken → Kraken 92.62.70.41

Ответ — base64-список vless:// (стандартная подписка: type=ws, security=tls, path=/vless, host=vpn.mallexxx.duckdns.org). В клиенте: удалить ручной профиль → «Add subscription» с ПОЛНЫМ путём …/sub/<subId> → включить auto-update (6–12 ч). Питфолл: вбитый руками vless:// авто-обновляться не будет — только ссылка подписки. Ссылка открыта без авторизации (кто знает subId — имеет ключ) — открытый вопрос к Alex. Полный разбор + команды проверки + что панель 3.7.0 умеет по подпискам: family/how-to/truenas-infrastructure → раздел xray-admin → «SUBSCRIPTION-КАНАЛ».

✅ Per-user egress на vpn.mallexxx.duckdns.org (2026-09-02)

В существующий VLESS-WS inbound in-10095-tcp добавлен второй клиент. Маршрутизация теперь различает клиентов по email:

Client email Client ID Egress
user1 ce320965-6956-4759-84bb-7cb71cfc6252 direct → TrueNAS 90.189.160.148
kraken-user 93a5dc4b-1b8d-4af5-9363-eb0091734293 via-kraken → portal SOCKS xray-reverse-portal:12345 → Kraken 92.62.70.41

В persistent 3x-ui Xray template (settings.key = xrayTemplateConfig) добавлен SOCKS outbound:

{
  "protocol": "socks",
  "tag": "via-kraken",
  "settings": {
    "address": "xray-reverse-portal",
    "port": 12345
  }
}

После глобальных geoip:private -> blocked и bittorrent -> blocked добавлено правило:

{
  "type": "field",
  "user": ["kraken-user"],
  "outboundTag": "via-kraken",
  "ruleTag": "kraken-user-via-reverse"
}

Проверка одним и тем же локальным Docker-клиентом xray-test-client, менялся только client ID:

  • user1 → HTTPS api.ipify.org → 90.189.160.148 (TrueNAS direct).
  • kraken-user → HTTP и HTTPS api.ipify.org → 92.62.70.41 (Kraken reverse).

Локальный /Users/admin/xray-test/config.json оставлен на kraken-user. Бэкап direct-клиента: /Users/admin/xray-test/config.json.bak-user1-direct-20260902-1227.

⚠️ СОСТОЯНИЕ КЛИЕНТА 2026-09-02 (после замеров скорости туннеля)

Контейнер xray-test-client переключён с kraken-user на user1-direct для замеров скорости direct-пути, и НЕ возвращён обратно. Активная конфигурация = user1 (direct, REALITY).

  • Контейнер: xray-test-client (image teddysun/xray:latest; лог старта показал «Xray 26.7.28 started»), bind-mount /Users/admin/xray-test/config.json:/etc/xray/config.json:ro, SOCKS 127.0.0.1:1080→1080.
  • Как переключать: в /Users/admin/xray-test/:
    • user1-direct = config.json.bak-user1-direct-20260902-1227 (id ce320965-6956-4759-84bb-7cb71cfc6252) — выход TrueNAS 90.189.160.148.
    • kraken-user = прежний активный, сохранён в config.json.current-kraken-user (id 93a5dc4b-1b8d-4af5-9363-eb0091734293) — выход Kraken 92.62.70.41.
    • Смена: cp <файл> /Users/admin/xray-test/config.json && docker restart xray-test-client.
  • Размер обоих конфигов одинаковый (831 байт), inbound общий (SOCKS :1080 noauth), различие только в VLESS-outbound (client id / egress).

📊 Замеры скорости туннелей (2026-09-02, с Mac через xray-test-client :1080)

🔗 2026-09-21 — важное дополнение: вопрос «поднять ещё VLESS-туннелей и распараллелить, чтобы Jellyfin залетал» разобран в [[inter-site-throughput-taiga-to-mac]] → раздел «2026-09-21 — РАЗБОР». Кратко: speedtest 120 Мбит = 8 параллельных TCP-сессий; один поток всё равно 28–45 Мбит, и N туннелей по одному физическому пути (ТТК→Ростелеком) этого не меняют. Документ также содержит сравнение webOS-клиентов (Moonfin/Breezyfin) и инструменты prefetch-proxy.

Замер пропускной способности каждого egress-режима (скачивание файлов по SOCKS-прокси контейнера; источник http cachefly + ovh; Cloudflare с этого egress режется = 0 B/s → не показатель):

Режим egress IP Средний down Разброс Комментарий
kraken-user (reverse) 92.62.70.41 (Kraken) ~5.7 МБ/с (~45 Мбит) 2.0–6.98 МБ/с убывающий по ходу замера
user1 (direct/REALITY) 90.189.160.148 (TrueNAS) ~4.6 МБ/с (~37 Мбит) 3.67–5.63 МБ/с cachefly 4×10MB

Вывод: оба egress-режима туннеля дают ~35–45 Мбит/с (разброс 2.0–6.98 МБ/с) — не кратно быстрее прямого межоператорского пути (~28 Мбит single-flow), туннель не даёт надёжного запаса под stрим пиковых битрейтов BluRay (~20+ Мбит). Для jellyfin-стрима на ТВ туннель не решает проблему дёрганья.

Контроль (не туннель, Mac напрямую до Cloudflare): ~55 МБ/с. Туннель ~в 10× медленнее прямого локального интернета.

Бэкапы TrueNAS до и после изменения: /mnt/RED_2TB/docker/backups/xray-per-user-20260902-1200/ (x-ui.db, x-ui.post-change.db, runtime configs, reverse portal config/compose). Temporary full-admin API token не создавался; api_tokens осталась пустой.

Связанные заметки