Files
obsidian-vault/personal/plans/lan-access-via-reverse-tunnel.md
T

391 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Доступ к 192.168.2.0/24 с ASUS через reverse-туннель Kraken→TrueNAS
created: '2026-09-23'
type: plan
namespace: personal
tags:
- xray
- reverse
- kraken
- truenas
- asus
- routing
- vpn
status: closed-rolled-back
updated: '2026-09-23'
related:
- '[[personal/tech/xray-reverse-tunnel-kraken-truenas]]'
- '[[family/how-to/truenas-infrastructure]]'
- '[[family/how-to/kraken-access]]'
- '[[family/how-to/router-bishkek-asus]]'
---
# Доступ к 192.168.2.0/24 с ASUS через reverse-туннель Kraken→TrueNAS
> ## 🏁 СТАТУС: ЗАКРЫТО, ВСЁ ОТКАЧЕНО (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`. Направление задачи и направление туннеля не совпадают.
>
> **Решение Alex: ОТКАТЫВАТЬ.** Выполнено 2026-09-23 — все три узла возвращены в исходное состояние. См. раздел «✅ ОТКАТ ВЫПОЛНЕН» ниже.
>
> ### ✅ ОТКАТ ВЫПОЛНЕН (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-*` фигурирует старый — актуализировать при следующей правке (в этой сессии правка тех-доков НЕ выполнялась, см. незакрытый пункт в таблице исполнения).
> **Исходный статус на момент планирования: ПРЕДЛОЖЕНО.** План согласован к выполнению 2026-09-23.
## Задача
Alex хочет, чтобы клиенты сети `192.168.1.0/24` (за роутером ASUS `192.168.1.1`) ходили на адреса `192.168.2.x` **как на локальные** — через существующий reverse-туннель Кра́кен↔TrueNAS.
Мотивация: сейчас `192.168.2.x` недостижим никак (ни LAN, ни по домену как чистый IP). Jellyfin/WebDAV/порты приходится дёргать через `*.mallexxx.duckdns.org`.
## Топология (проверено 2026-09-23)
```
Mac 192.168.1.57 ─┐
├── 192.168.1.0/24, gw 192.168.1.1 (ASUS RT-AC68U)
Kraken .14/.15 ──┘
│ reverse-туннель VLESS+REALITY TCP :12346 (ЖИВ)
▼
TrueNAS 192.168.2.197 ── сеть 192.168.2.0/24 (шлюз OpenWrt 192.168.2.2)
```
🔴 **ГЛАВНЫЙ ФАКТ, СНЯВШИЙ ЛОЖНУЮ ПОСЫЛКУ:** Mac и Кра́кен — **соседи** в одной сети `192.168.1.0/24`, шлюз один (`192.168.1.1`). Между ними **нет** OpenWrt. OpenWrt `192.168.2.2` — шлюз **сети TrueNAS**, к стороне Alex отношения не имеет.
**Следствие:** схема «статический маршрут на ASUS → Кра́кен» **работает**. Обратный путь не нужен, `ip rule` / Rasputin / NAT на стороне Alex **не требуются**. Ранее предложенные варианты A (iptables NAT на ASUS) и B (политика на Rasputin) были построены на неверной топологии — **отброшены**.
## Проверенное состояние (2026-09-23)
| Что | Результат |
|---|---|
| `xray-reverse-portal` (TrueNAS) | Up 4 дня, `:12346` LISTEN |
| `xray-reverse-bridge` (Kraken) | Up 2 дня, `teddysun/xray:26.4.25`, `network_mode: host` |
| ESTABLISHED от бриджа | ✅ `172.16.1.7:12346 ← 92.62.77.233:32529` |
| **Payload end-to-end** | ✅ через SOCKS портала `92.62.77.233` ≠ напрямую `90.189.160.148` |
| ASUS SSH `192.168.1.1:22` | ❌ `Connection closed` — правка только через веб-UI |
| `inbounds` в конфиге бриджа | ❌ **`null`** — слушающих портов нет вообще |
| Порты 12345–12350 / 1080 на Кра́кене | пусто |
> ✅ **НОВЫЙ ФАКТ (нет в других доках):** пассивная проверка дала `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.
**Первоначальный (ошибочный) вывод:** «бриджу нужна точка входа, `inbounds: null`». Точка входа действительно была добавлена (`dokodemo-door`) и **работала** — но это оказалось входом **не с той стороны**. Реальный блокер вскрыт ниже: портал отказывается выпускать трафик в приватную сеть. См. «🔴 КРИТИЧНАЯ НАХОДКА».
## 🔴 КРИТИЧНАЯ НАХОДКА (2026-09-23) — направление перевёрнуто
Прогнано вживую. Цепочка «ASUS → Кра́кен → туннель → TrueNAS → 192.168.2.x» **не работает архитектурно**, а не из-за конфига.
**Что происходит по факту:**
| Шаг | Лог | Результат |
|---|---|---|
| Mac → Кра́кен `lan-in` | `accepted tcp:192.168.2.197:80 [lan-in -> conn]` | ✅ перехват, уход в туннель |
| Туннель → портал | `received request for tcp:192.168.2.197:80` | ✅ дошло |
| Портал выпускает | `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. 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** — то есть как попытку использовать сервер как открытый прокси. Отсюда отказ.
**Правильное направление (Use Case 2 «Remote Return Home» из доки Xray):**
```
клиент → PUBLIC SERVER (TrueNAS, портал) → reverse-out → туннель
↓
INTERNAL DEVICE (Кра́кен, бридж)
↓
freedom + finalRules allow
↓
192.168.2.0/24
```
То есть **точка входа должна быть на TrueNAS (портал)**, а `reverse-in → freedom с finalRules[allow ip 192.168.2.0/24]` — **на Кра́кене (бридж)**.
🔴 **Мой план был построен на перевёрнутой схеме** — «ASUS → Кра́кен → в подсеть». В этой архитектуре Кра́кен выступает «домашней» стороной, и именно ему нужен allow-rule, а вход — на TrueNAS.
**Проверенные факты по пути (сохранить):**
- `dokodemo-door` **обязан** слушать `0.0.0.0`, не `127.0.0.1` — иначе REDIRECT-трафик с внешнего адреса не принимается.
- `iptables -t nat PREROUTING` **не действует** на локально-исходящий трафик с самого хоста — для теста нужен отдельный netns либо реальный клиент из сети.
- `redirect: ""` в freedom — невалидно; пустая строка ломает конфиг.
- Xray 26.4.25: `xray run -test` **читает stdin** и виснет под SSH без `< /dev/null`.
- Кра́кен: `sudo` через SSH требует `< /dev/null` на каждой команде, иначе `Connection closed by remote host`.
- На Кра́кене **нет `ifconfig`** — каждый вызов печатает `command not found` в stderr (безвредно, но засоряет вывод).
## Три правки (СУПЕРСИДЕД — см. находку выше)
### Правка 1 — Кра́кен: `dokodemo-door` + REDIRECT (сделано, но НЕ тот вход)
Файл `/home/kraken/xray-reverse/config.json`. Применено, канал работает, но это вход **не с той стороны** — см. находку выше. Требует пересмотра.
Файл `/home/kraken/xray-reverse/config.json` (bind-mount `:ro` → `/etc/xray/config.json`).
🔴 **Причина, почему НЕ SOCKS:** схема требует доступа **по чистому IP** (`http://192.168.2.197:8096`). Обычный `socks`-inbound ждёт SOCKS-протокол от клиента — браузер и `mount_smbfs` его не говорят. Нужен **прозрачный перехват**: Xray молча подбирает сырые пакеты, клиент ничего не знает.
Выбран **`dokodemo-door` + `iptables REDIRECT`** (а не TPROXY): проще, не требует `tproxy`-модуля ядра, не требует `fwmark`/второй таблицы маршрутизации. Проверено на Кра́кене 2026-09-23: `iptables` присутствует, `nft` есть, `ip rule` пустой, Xray 26.4.25 умеет `dokodemo-door`.
Добавить секцию `inbounds` (сейчас `null`):
```json
"inbounds": [
{
"tag": "lan-in",
"listen": "127.0.0.1",
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp",
"followRedirect": true
},
"sniffing": { "enabled": false }
}
]
```
- `listen: 127.0.0.1` — снаружи порт **не виден вообще**, доступ только через REDIRECT. Закрывает отметку безопасности из `xray-reverse-tunnel-kraken-truenas`: *«Не добавлять в этот контейнер обычные inbounds без аудита bind address/firewall»*.
- `sniffing: false` — не нужен, назначение уже известно из `SO_ORIGINAL_DST`.
Правило `routing.rules` — `inboundTag:["lan-in"] → outboundTag:"conn"` (в reverse-канал):
```json
{ "inboundTag": ["lan-in"], "outboundTag": "conn" }
```
Существующее правило `inboundTag:["reverse-in"] → direct` **оставить без изменений** — оно обслуживает обратное направление (интернет-egress через Кра́кен для `kraken-user`).
**Перехват на хосте Кра́кена:**
```bash
iptables -t nat -A PREROUTING -s 192.168.1.0/24 -d 192.168.2.0/24 -p tcp \
-j REDIRECT --to-ports 12345
```
Xray из REDIRECT-сокета читает `SO_ORIGINAL_DST` → узнаёт настоящий `192.168.2.197:8096` → отправляет через туннель.
⚠️ **Правило iptables не переживёт reboot** — нужна персистентность (`iptables-persistent` / `netfilter-persistent` либо systemd-юнит). Проверить наличие перед правкой; на Кра́кене (OMV/Debian) вероятнее всего отсутствует → создать oneshot-юнит.
⚠️ **`-d 192.168.2.0/24` обязателен.** Без него REDIRECT перехватит **весь** LAN-трафик Кра́кена, включая его собственный reverse-канал и `cloudflared`.
⚠️ **Только TCP.** REDIRECT — TCP-механизм. UDP через эту схему **не пройдёт**. См. раздел «Что пройдёт, а что нет».
- Порт 12345 на Кра́кене свободен (проверено `ss -tlnp`, 2026-09-23).
- Бэкап ДО правки: `config.json.bak-lan-in-<date>` + `iptables-save > /home/kraken/backups/iptables.bak-<date>`.
**Альтернатива (не выбрана) — TPROXY:** даёт UDP, но требует `modprobe tproxy` (сейчас модуль не загружен), `fwmark`, отдельную таблицу маршрутизации и `tun`. Сложнее; брать только если UDP реально понадобится.
### Правка 2 — TrueNAS: научить портал выпускать в 192.168.2.0/24
Файл `/mnt/RED_2TB/docker/reverse-portal/config.json` (bind-mount `:ro`).
Сейчас: `routing.rules = [{inboundTag:["local"], outboundTag:"reverse-out"}]`, outbound — только placeholder `freedom`.
Добавить правило, которое после распаковки на бридже отправит целевой трафик локально:
```json
{
"type": "field",
"ip": ["192.168.2.0/24"],
"outboundTag": "direct"
}
```
⚠️ **Требует проверки перед применением:** нужен ли на портале `direct`-outbound с `finalRules:[{action:"allow"}]` (как на бридже — фикс Xray 26.5+, issue #6612) или достаточно placeholder-freedom. Боль в том, что портал сейчас на `teddysun/xray:26.4.25`, где #6612 формально не применим, — но версия помечена как «фикс, требующий проверки в рантайме».
**Порядок правила важен:** правило для `192.168.2.0/24` должно стоять **выше** правила `local → reverse-out`, иначе `local` его перехватит.
- ⚠️ Правка конфига на TrueNAS: папка `/mnt/RED_2TB/docker/reverse-portal/` — права root, `truenas_admin` писать не может. Класть через `docker run --rm -v /tmp:/src -v <dst>:/dst alpine cp …` + `chown`.
- Бэкап ДО: `config.json.bak-lan-route-<date>`.
### Правка 3 — ASUS: статический маршрут ✅ ВЫПОЛНЕНО (не через UI)
✅ **ASUS доступен по SSH** — прежняя запись «SSH закрыт, только веб-UI» **ОШИБОЧНА**. Правильный вход:
```bash
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 # пользователь admin, НЕ root
```
Порт 22 открыт; подключение как `root` даёт `Connection closed` — отсюда ложный вывод.
**Механизм статических маршрутов — `nvram`, не UI.** Формат `NET:MASK:GW:METRIC` в одной строке:
```bash
nvram get lan_route # → 192.168.2.0:255.255.255.0:192.168.1.2:25
nvram set lan_route="192.168.2.0:255.255.255.0:192.168.1.15:25"
nvram commit
```
⚠️ `service restart_routing` **НЕ перечитывает** `lan_route` (проверено — таблица осталась со старым шлюзом). Применять явно:
```bash
ip route del 192.168.2.0/24 via 192.168.1.2 dev br0
ip route add 192.168.2.0/24 via 192.168.1.15 dev br0 metric 25
```
Бэкап: `nvram get lan_route > /jffs/lan_route.bak.$(date +%Y%m%d-%H%M%S)`
⚠️ Кра́кен имеет **два** адреса в `192.168.1.0/24`: `.14` (eth0, metric 100) и `.15` (wlan0, metric 600), **разные MAC** (`…03:f3` / `…03:f4`). Использовать **`.15`**, как в DNS-записи `address=/kraken/192.168.1.15`.
⚠️ Маршрут действует на всём сегменте — **все** клиенты `192.168.1.0/24` пойдут на `192.168.2.x` через `.15`. Если нужно выборочно — routing на конкретном клиенте, но тогда ASUS не нужен.
## 🏁 РАЗВИЛКА — решение НЕ принято (2026-09-23)
Тупик: Xray reverse **по дизайну** не пропускает forward-proxy трафик в приватные сети. Направление «ASUS → Кра́кен → в сеть TrueNAS» реализовать нельзя — только обратное («дом = Кра́кен», цель = `192.168.1.x`), что не решает задачу.
| # | Вариант | Что даёт | Цена |
|---|---|---|---|
| **1** | **Отказаться**, откатить всё из бэкапов | возврат к исходному состоянию | теряется только то, чего и не было |
| **2** | SOCKS-прокси на стороне **клиента** (Mac) — через существующий `vless-proxy` (SOCKS `:1080`) / `xray-admin` | доступ к `192.168.2.x` с Mac | не «через ASUS»; нужен SOCKS-aware клиент или routing на Mac; не работает для других устройств |
| **3** | **WireGuard на TrueNAS** (белый IP + открытый порт уже есть) | **полный IP-стек**: ICMP, UDP, Samba-обзор, «как локальный» | новая служба на TrueNAS; TrueNAS на пределе RAM (17/21 ГБ) |
**Рекомендация:** вариант **3** — если нужен реально «true VPN» с UDP и Samba; вариант **2** — если хватит доступа с одного Mac.
⚠️ **Вариант 2 ограничен:** `docker exec vless-proxy wget` **не проверяет SOCKS** (wget не умеет SOCKS5, вернёт локальный IP) — проверять только через `curl --socks5-hostname`.
## Как это будет работать
```
Браузер (192.168.1.x): http://192.168.2.197:8096
↓
ASUS: маршрут 192.168.2.0/24 → 192.168.1.15
↓
Kraken .15: xray-reverse-bridge, inbound lan-in :12345
→ routing: lan-in → conn (outbound VLESS+REALITY, reverse-in)
↓ reverse-канал :12346 (уже поднят)
TrueNAS: xray-reverse-portal
→ правило 192.168.2.0/24 → direct
↓
192.168.2.197:8096 отвечает
↑ обратно по тому же каналу → Кра́кен → ASUS → клиент
```
## Что пройдёт, а что нет
| Протокол | Результат | Комментарий |
|---|---|---|
| TCP (8096 Jellyfin, 80, 445, 22) | ✅ да | основа схемы |
| Samba по IP (`mount_smbfs`) | ✅ да | TCP/445 |
| Samba auto-discover / browse | ❌ нет | broadcast не роутится |
| UDP | ❌ **нет** | REDIRECT — TCP-механизм. Для UDP нужен TPROXY (не выбран) |
| ICMP (ping) | ❌ нет | туннель port-based |
> 🔴 **Честная рамка: это НЕ WireGuard-класс.** «True VPN» с полным IP-стеком не получится — ни ICMP, ни broadcast, ни гарантии UDP. Что будет — TCP-доступ к `192.168.2.x` по чистым IP.
## Непроверенное (не додумывать)
1. **Пропускная способность через туннель.** Старые замеры (`xray-reverse-tunnel-kraken-truenas`) дают ~35–45 Мбит/с с нестабильностью. Для Jellyfin direct-play 20+ Мбит — впритык. Межоператорский путь ~104 мс RTT + per-TCP-flow штраф.
2. **Много параллельных TCP при 104 мс RTT** — не тестировалось.
3. **Транспарентность решена:** выбран `dokodemo-door` + `iptables REDIRECT` (правка 1 переписана). Проверено на Кра́кене: `iptables` есть, `nft` есть, `ip rule` пустой, Xray 26.4.25 поддерживает `dokodemo-door`. TPROXY не нужен, `tproxy`-модуль не загружен и не требуется для TCP.
## Порядок работ — ФАКТИЧЕСКОЕ ИСПОЛНЕНИЕ
Боевые конфиги — **коммит ДО → правка → заливка → ПРОВЕРКА ALEX → коммит ПОСЛЕ**.
| # | Шаг | Статус |
|---|---|---|
| 1 | Бэкап обоих конфигов + iptables | ✅ выполнено |
| 2 | Развилка **SOCKS vs `dokodemo-door`** | ✅ решено — `dokodemo-door` |
| 3 | Правка 2 (TrueNAS, портал) | ✅ выполнено, `Configuration OK.`, портал Up |
| 4 | Проверка, что канал не порвался после рестарта портала | ✅ egress `92.62.77.233` |
| 5 | Правка 1 (Кра́кен, бридж) | ✅ выполнено, `Configuration OK.`, бридж Up |
| 6 | Правило iptables REDIRECT на Кра́кене | ✅ добавлено, inbound слушает |
| 7 | **Сквозной тест** | ✅ **ПРОЙДЕН ЧАСТИЧНО** — перехват работает, но портал режет forward-proxy |
| 8 | Повторный тест **с Mac** (посторонний хост) | ✅ выполнен — `HTTP 000` + отказ портала |
| 9 | Диагностика отказа портала | ✅ `not allowed to use forward proxy` — **штатная защита Xray** |
| 10 | Диагностика ASUS-маршрута | ✅ SSH найден, битый `lan_route` → `.2` исправлен на `.15` |
| 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 | ⏳ отдельная задача, не входила в команду |
### 🔴 Как правильно проверять сквозной проход
**НЕЛЬЗЯ:** запускать `curl` с узла, где стоит правило REDIRECT (Кра́кен). Локально-исходящий трафик идёт через `nat OUTPUT`, `PREROUTING` его не видит → счётчик 0, `curl` даёт 000. Это **ложный негатив**, а не доказательство поломки.
**МОЖНО:**
1. **С Mac** (посторонний хост): `curl -v --max-time 15 http://192.168.2.197/` — **до** добавления маршрута на ASUS это даст timeout (контроль), после — должен пойти ответ.
2. **Транзитный тест из контейнера** с кастомным маршрутом (`--network host` + `ip route add 192.168.2.0/24 via 192.168.1.1`) — трафик станет транзитным и попадёт в `PREROUTING`.
3. **Контроль счётчика:** `iptables -t nat -L PREROUTING -n -v | grep 12345` — до/после теста. Ненулевой счётчик = правило сработало.
### Файлы, задействованные в правках
| Файл | Где | Что |
|---|---|---|
| `/home/kraken/xray-reverse/config.json` | Кра́кен | inbound `lan-in` + routing `lan-in → conn` |
| `/mnt/RED_2TB/docker/reverse-portal/config.json` | TrueNAS | routing `192.168.2.0/24 → direct` + outbound `direct` |
| Правило iptables | Кра́кен | `nat PREROUTING` REDIRECT (не персистентно) |
| `/Users/admin/tmp-lan-tunnel/bridge-config-new.json` | Mac (локально) | эталон нового конфига бриджа |
| `/Users/admin/tmp-lan-tunnel/portal-config-new.json` | Mac (локально) | эталон нового конфига портала |
### Команды валидации (использованы, воспроизводимые)
```bash
# Валидация конфига живым бинарником — ДО заливки
ssh kraken 'sudo docker run --rm -v /home/kraken/xray-reverse:/etc/xray \
teddysun/xray:26.4.25 xray run -test -c /etc/xray/ctest.json'
# → ожидается "Configuration OK."
# Заливка на TrueNAS (папка root-owned)
docker run --rm -v /tmp:/src -v /mnt/RED_2TB/docker/reverse-portal:/dst alpine \
sh -c "cp /src/portal-config-new.json /dst/config.json && chown 950:950 /dst/config.json"
# Правило перехвата
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
```
## Откат — ✅ ВЫПОЛНЕН (команды, воспроизводимые)
```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>` **перед** копированием.
## Связанные заметки
- [[personal/tech/xray-reverse-tunnel-kraken-truenas]] — архитектура reverse-туннеля (основной док)
- [[family/how-to/truenas-infrastructure]] — контейнеры TrueNAS, `xray-reverse-portal`
- [[family/how-to/kraken-access]] — Кра́кен, бридж
- [[family/how-to/router-bishkek-asus]] — ASUS
- [[family/how-to/rasputin-router]] — второй роутер (в этой схеме **не участвует**)