[2026-09-23] eagle: family/how-to/router-bishkek-asus.md personal/plans/lan-access-via-reverse-tunnel.md personal/tech/xray-reverse-tunnel-kraken-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-23 13:56:52 +06:00
1 parent bf2a1aa850
commit 00beffc97f
3 files changed
+163 -36

No files matched your search

+60 -20
View File
@@ -11,7 +11,7 @@ tags:
- asus
- routing
- vpn
status: stopped-architectural-deadlock
status: closed-rolled-back
updated: '2026-09-23'
related:
- '[[personal/tech/xray-reverse-tunnel-kraken-truenas]]'
@@ -21,22 +21,37 @@ related:
---
# Доступ к 192.168.2.0/24 с ASUS через reverse-туннель Kraken→TrueNAS
> ## 🏁 СТАТУС: ОСТАНОВЛЕНО (2026-09-23, вечер). Архитектурный тупик, схема НЕ доведена.
> ## 🏁 СТАТУС: ЗАКРЫТО, ВСЁ ОТКАЧЕНО (2026-09-23, вечер). Архитектурный тупик. Схема НЕ реализована.
>
> **Итог:** цепочка «ASUS → Кра́кен → туннель → TrueNAS → 192.168.2.x» **не реализуется** в Xray reverse. Портал отклоняет: `for safety reasons, user a81c3179-… is not allowed to use forward proxy`. Это **штатная защита** Xray от превращения сервера в открытый прокси, не баг конфига. Обходится только `finalRules`-allow, но тогда «домашней» стороной обязан быть Кра́кен, а целевая сеть — его локалка (`192.168.1.x`), **не** `192.168.2.x`. Направление задачи и направление туннеля не совпадают.
> **Итог задачи:** цепочка «ASUS → Кра́кен → туннель → TrueNAS → 192.168.2.x» **не реализуется** в Xray reverse. Портал отклоняет: `for safety reasons, user a81c3179-… is not allowed to use forward proxy`. Это **штатная защита** Xray от превращения сервера в открытый прокси, не баг конфига. Обходится только `finalRules`-allow, но тогда «домашней» стороной обязан быть Кра́кен, а целевая сеть — его локалка (`192.168.1.x`), **не** `192.168.2.x`. Направление задачи и направление туннеля не совпадают.
>
> **Решение Alex:** НЕ принято. Варианты в разделе «Развилка» ниже. Откат возможен в одну команду из бэкапов.
> **Решение Alex: ОТКАТЫВАТЬ.** Выполнено 2026-09-23 — все три узла возвращены в исходное состояние. См. раздел «✅ ОТКАТ ВЫПОЛНЕН» ниже.
>
> **Что осталось применённым на системах (требует решения — откатить или оставить):**
> - Кра́кен: inbound `lan-in` (`dokodemo-door`, `0.0.0.0:12345`) + routing `lan-in → conn`; правило `iptables nat PREROUTING` REDIRECT (не персистентно). Бэкапы: `config.json.bak-lan-in-20260923-130541`, `config.json.bak-listen0000-20260923-131655`, `config.json.bak-v3-<date>`, `iptables.bak-20260923-130541`.
> - TrueNAS: правило `192.168.2.0/24 → direct` в портале. Бэкап: `config.json.before-lanroute`.
> - ASUS: `nvram lan_route` изменён с `192.168.1.2` на `192.168.1.15`. Бэкап: `/jffs/lan_route.bak.20260923-131613`.
> - ⚠️ **Обнаружен и исправлен битый артефакт:** `lan_route` указывал на мёртвый `192.168.1.2` (ARP `FAILED`, MAC нулевой) — трафик на `192.168.2.x` уходил в никуда. Это была **предсуществующая поломка**, не созданная в этой сессии.
> ### ✅ ОТКАТ ВЫПОЛНЕН (2026-09-23) — фактическое состояние систем
>
> | Узел | Что было моё | Стало | Проверка |
> |---|---|---|---|
> | **Кра́кен** | inbound `lan-in` (`dokodemo-door` `0.0.0.0:12345`), outbound `home-lan`, routing `lan-in → conn`, правило `iptables nat PREROUTING` REDIRECT | ✅ исходный конфиг (`inbounds: false`, outbounds `direct`+`conn`, routing `reverse-in → direct`), iptables чист, netns `lantest` удалён | порт 12345 **не слушается**; лог `received request for udp:reverse:0` — канал жив |
> | **TrueNAS портал** | routing-правило `192.168.2.0/24 → direct` + outbound `direct` с `finalRules` | ✅ исходный (`routing = [{local → reverse-out}]`, один placeholder-freedom) | после рестарта `dispatching request to udp:reverse:0` |
> | **ASUS** | `nvram lan_route` → `192.168.1.15` | ✅ возвращён `192.168.2.0:255.255.255.0:192.168.1.2:25` (как было) | `nvram get lan_route` + живая таблица маршрутов совпадают |
>
> **Бэкапы оставлены (не удалялись):**
> - Кра́кен: `config.json.bak-lan-in-20260923-130541`, `config.json.bak-listen0000-20260923-131655`, `config.json.bak-listen0000-20260923-132108`, `config.json.bak-v3-20260923-132753`, `config.json.pre-rollback-<date>`, `iptables.bak-20260923-130541` (в `/home/kraken/backups/`)
> - TrueNAS: `config.json.before-lanroute` (эталон отката), `config.json.pre-rollback`
> - ASUS: `/jffs/lan_route.bak.20260923-131613`
>
> ⚠️ **Не подтверждено:** финальный тест egress через туннель (`92.62.77.233`) не был прогнан — истёк апрув на команду. Оба конца логируют установку канала (`udp:reverse:0` с обеих сторон), поэтому канал живой. Команда для самостоятельной проверки:
> ```bash
> ssh truenas_admin@mallexxx.duckdns.org "docker run --rm --network caddy_default curlimages/curl curl -s --max-time 20 --socks5-hostname xray-reverse-portal:12345 https://api.ipify.org"
> # ожидается 92.62.77.233
> ```
>
> ⚠️ **Оставлено как было, сознательно:** маршрут на ASUS `192.168.2.0/24 → 192.168.1.2` **битый** — `192.168.1.2` мёртв (ARP `FAILED`, MAC нулевой, порт закрыт). Это **предсуществующая поломка**, не созданная в этой сессии; Alex решил только откатывать. Кандидат на отдельную задачу — убрать.
>
> **✅ ПОЛЕЗНЫЕ ПОБОЧНЫЕ НАХОДКИ (сохранить, не терять):**
> - ✅ **ASUS SSH РАБОТАЕТ:** `ssh -i ~/.ssh/id_rsa admin@192.168.1.1` (пользователь **`admin`**, не `root`). Порт 22 открыт. Прежний вывод «ASUS не пускает по SSH» — **ошибка**: подключался как `root`. Маршруты правятся через `nvram lan_route` (формат `NET:MASK:GW:METRIC`), не через UI.
> - ✅ **Reverse-канал ВПЕРВЫЕ подтверждён end-to-end** после починки гонки docker↔mount 2026-09-20: через SOCKS портала `92.62.77.233` ≠ напрямую `90.189.160.148`.
> - ⚠️ **WAN-IP Кра́кена изменился:** `92.62.70.41` → **`92.62.77.233`**. В `kraken-access.md` / `xray-reverse-tunnel-*` фигурирует старый — актуализировать при следующей правке.
> - ⚠️ **WAN-IP Кра́кена изменился:** `92.62.70.41` → **`92.62.77.233`**. В `kraken-access.md` / `xray-reverse-tunnel-*` фигурирует старый — актуализировать при следующей правке (в этой сессии правка тех-доков НЕ выполнялась, см. незакрытый пункт в таблице исполнения).
> **Исходный статус на момент планирования: ПРЕДЛОЖЕНО.** План согласован к выполнению 2026-09-23.
@@ -75,11 +90,11 @@ TrueNAS 192.168.2.197 ── сеть 192.168.2.0/24 (шлюз OpenWrt 192.168.
> ✅ **НОВЫЙ ФАКТ (нет в других доках):** пассивная проверка дала `92.62.77.233` — **WAN-IP Кра́кена изменился** (в доке фигурирует `92.62.70.41`). Канал впервые подтверждён end-to-end после починки гонки docker↔mount 2026-09-20.
## Блокер
## Блокер (историческая фиксация первых часов работы)
`reverse` в Xray **асимметричен**: на бридже (Кра́кен) создаётся виртуальный inbound `reverse-in` (трафик *из* портала *в* бридж), на портале (TrueNAS) — маутбаунд `reverse-out`. Портал сейчас роутит `inboundTag:["local"] → reverse-out`, то есть SOCKS `:12345` на самом TrueNAS.
`reverse` в Xray **асимметричен**: на бридже (Кра́кен) создаётся виртуальный inbound `reverse-in` (трафик *из* портала *в* бридж), на портале (TrueNAS) — маутбаунд `reverse-out`. Портал роутит `inboundTag:["local"] → reverse-out`, то есть SOCKS `:12345` на самом TrueNAS.
**Чтобы ASUS мог что-то отправить, бриджу нужна точка входа. Сейчас её нет** — `inbounds: null`. Пока правка 1 не сделана, схема физически не может работать.
**Первоначальный (ошибочный) вывод:** «бриджу нужна точка входа, `inbounds: null`». Точка входа действительно была добавлена (`dokodemo-door`) и **работала** — но это оказалось входом **не с той стороны**. Реальный блокер вскрыт ниже: портал отказывается выпускать трафик в приватную сеть. См. «🔴 КРИТИЧНАЯ НАХОДКА».
## 🔴 КРИТИЧНАЯ НАХОДКА (2026-09-23) — направление перевёрнуто
@@ -295,9 +310,10 @@ TrueNAS: xray-reverse-portal
| 8 | Повторный тест **с Mac** (посторонний хост) | ✅ выполнен — `HTTP 000` + отказ портала |
| 9 | Диагностика отказа портала | ✅ `not allowed to use forward proxy` — **штатная защита Xray** |
| 10 | Диагностика ASUS-маршрута | ✅ SSH найден, битый `lan_route` → `.2` исправлен на `.15` |
| 11 | **Вывод: архитектурный тупик** | 🏁 зафиксирован, решение Alex **не принято** |
| 12 | Откат или переход к варианту 2/3 | ⏳ ждёт решения |
| 13 | Обновить `personal/tech/xray-reverse-tunnel-kraken-truenas.md` | ⏳ |
| 11 | **Вывод: архитектурный тупик** | 🏁 зафиксирован |
| 12 | **Решение Alex: откатывать** | ✅ **ОТКАТ ВЫПОЛНЕН** — все 3 узла в исходном состоянии, проверено |
| 13 | Обновить `personal/tech/xray-reverse-tunnel-kraken-truenas.md` (WAN-IP `92.62.77.233`, факт живого канала после 2026-09-20) | ⏳ **НЕ ВЫПОЛНЕНО** — тех-доки не правились |
| 14 | Убрать битый маршрут `192.168.2.0/24 → 192.168.1.2` на ASUS | ⏳ отдельная задача, не входила в команду |
### 🔴 Как правильно проверять сквозной проход
@@ -335,11 +351,35 @@ sudo iptables -t nat -A PREROUTING -s 192.168.1.0/24 -d 192.168.2.0/24 \
-p tcp -j REDIRECT --to-ports 12345
```
## Откат
## Откат — ✅ ВЫПОЛНЕН (команды, воспроизводимые)
- Кра́кен: вернуть `config.json.bak-lan-in-<date>`, `docker restart xray-reverse-bridge`.
- TrueNAS: вернуть `config.json.bak-lan-route-<date>`, `docker restart xray-reverse-portal`.
- ASUS: удалить маршрут в UI.
```bash
# 1. КРА́КЕН — вернуть конфиг без 'inbounds' (исходный), убрать REDIRECT, перезапустить
ssh kraken 'sudo bash /tmp/rollback-bridge.sh' # скрипт выбирает бэкап с inbounds=false
ssh kraken 'sudo iptables -t nat -D PREROUTING -s 192.168.1.0/24 -d 192.168.2.0/24 -p tcp \
-j REDIRECT --to-ports 12345'
ssh kraken 'sudo ip netns del lantest; sudo ip link del veth-test-h' # убрать тестовый netns
ssh kraken 'sudo docker restart xray-reverse-bridge'
# проверка: порт 12345 не слушается; лог 'received request for udp:reverse:0'
# 2. TRUENAS — вернуть портал (папка root-owned → через alpine-контейнер)
ssh truenas_admin@mallexxx.duckdns.org 'docker run --rm \
-v /mnt/RED_2TB/docker/reverse-portal:/dst alpine sh -c \
"cp /dst/config.json.before-lanroute /dst/config.json && chown 950:950 /dst/config.json"'
ssh truenas_admin@mallexxx.duckdns.org 'docker restart xray-reverse-portal'
# проверка: routing = [{local → reverse-out}], лог 'dispatching request to udp:reverse:0'
# 3. ASUS — вернуть nvram и живую таблицу
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 \
'nvram set lan_route="192.168.2.0:255.255.255.0:192.168.1.2:25" && nvram commit'
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 \
'ip route del 192.168.2.0/24 via 192.168.1.15 dev br0; \
ip route add 192.168.2.0/24 via 192.168.1.2 dev br0 metric 25'
```
⚠️ **Питфолл отката портала:** файл восстанавливается мгновенно, но контейнер держит старый конфиг в памяти — **обязателен `docker restart`**, иначе `docker exec … cat` покажет уже новый файл при работающем старом конфиге (ложное «откатилось»).
⚠️ **Питфолл отката бриджа:** среди бэкапов есть и «промежуточные плохие» (`bak-listen0000-*`, `bak-v3-*`). Верный исходный — тот, где `has("inbounds")` = `false`. Скрипт `rollback-bridge.sh` выбирает его автоматически; вручную — проверять `jq -r 'has("inbounds")' <file>` **перед** копированием.
## Связанные заметки
@@ -1,7 +1,7 @@
---
title: Xray Reverse Tunnel — Kraken ↔ TrueNAS
created: '2026-09-01'
updated: '2026-09-20'
updated: '2026-09-23'
type: tech
namespace: personal
tags:
@@ -56,25 +56,61 @@ verified_fix_2026_09_02: >-
> ### Вывод для `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-bridge` **не имеет `inbounds`** (ключи конфига только `log`/`outbounds`/`routing`) — канал есть, но принять трафик от роутера бриджу нечем. Это недостающий кусок для схемы.
> ### Новый план использования этого канала — ❌ ЗАКРЫТ
> Задача «доступ к `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.` на обоих), контейнеры перезапущены, канал после рестарта жив (`92.62.77.233`). Сквозной проход **не подтверждён** (см. питфолл ниже).
> ### 🔧 ЭКСПЕРИМЕНТ 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`, `listen 127.0.0.1:12345`, `followRedirect:true`, `sniffing:false` + routing `lan-in → conn` |
> | Портал (TrueNAS) | `/mnt/RED_2TB/docker/reverse-portal/config.json` | outbound `direct` создан с `finalRules:[{action:"allow"}]`; routing-правило `192.168.2.0/24 → direct` **выше** `local → reverse-out` |
> | Хост Кра́кена | iptables | `nat PREROUTING -s 192.168.1.0/24 -d 192.168.2.0/24 -p tcp -j REDIRECT --to-ports 12345` |
> | ~~Бридж (Кра́кен)~~ | `/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`, `/home/kraken/backups/iptables.bak-20260923-130541`, `/mnt/RED_2TB/docker/reverse-portal/config.json.before-lanroute`.
>
> ⚠️ **`iptables-persistent` на Кра́кене НЕ установлен** — правило REDIRECT не переживёт reboot, нужен systemd oneshot-юнит (не сделан).
>
> 🔴 **ПИТФОЛЛ ДИАГНОСТИКИ `REDIRECT` (стоил ложного вывода):** нельзя проверять проход, запуская `curl` **с того же хоста, где стоит правило**. Локально-исходящий трафик идёт через `nat OUTPUT`, `PREROUTING` его не видит → счётчик правила = 0, `curl` → `HTTP 000`. Это **ложный негатив, а не доказательство поломки**. Проверять только с постороннего хоста (Mac в `192.168.1.x`) либо транзитным трафиком из контейнера с кастомным маршрутом. Контроль — счётчик: `iptables -t nat -L PREROUTING -n -v | grep 12345`.
>
> ⚠️ **Гипотеза, требующая проверки:** в логах бриджа видно `proxy/freedom: applying default private IP blocking policy for inbound vless-reverse`. Если private-IP-политика `freedom` применится и к новому inbound `lan-in`, трафик до `192.168.2.x` не дойдёт. Тот же класс проблемы, что issue #6612.
> Бэкапы (сохранены): `/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, НЕ конфиг и НЕ версия
>