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

32 KiB
Executable File
Raw Blame History

title, created, type, namespace, tags, status, updated, related
title created type namespace tags status updated related
Доступ к 192.168.2.0/24 с ASUS через reverse-туннель Kraken→TrueNAS 2026-09-23 plan personal
xray
reverse
kraken
truenas
asus
routing
vpn
closed-rolled-back 2026-09-23
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 с обеих сторон), поэтому канал живой. Команда для самостоятельной проверки:

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

"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-канал):

{ "inboundTag": ["lan-in"], "outboundTag": "conn" }

Существующее правило inboundTag:["reverse-in"] → direct оставить без изменений — оно обслуживает обратное направление (интернет-egress через Кра́кен для kraken-user).

Перехват на хосте Кра́кена:

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.

Добавить правило, которое после распаковки на бридже отправит целевой трафик локально:

{
  "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» ОШИБОЧНА. Правильный вход:

ssh -i ~/.ssh/id_rsa admin@192.168.1.1     # пользователь admin, НЕ root

Порт 22 открыт; подключение как root даёт Connection closed — отсюда ложный вывод.

Механизм статических маршрутов — nvram, не UI. Формат NET:MASK:GW:METRIC в одной строке:

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 (проверено — таблица осталась со старым шлюзом). Применять явно:

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 (локально) эталон нового конфига портала

Команды валидации (использованы, воспроизводимые)

# Валидация конфига живым бинарником — ДО заливки
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

Откат — ✅ ВЫПОЛНЕН (команды, воспроизводимые)

# 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> перед копированием.

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