--- title: Xray reverse — граница возможностей (forward proxy в приватные сети) created: '2026-09-23' type: tech namespace: personal tags: - xray - reverse - vless - vpn - networking - pitfall status: verified related: - '[[personal/tech/xray-reverse-tunnel-kraken-truenas]]' - '[[personal/plans/lan-access-via-reverse-tunnel]]' --- # Xray reverse — граница возможностей > **Короткий вывод:** Xray reverse **намеренно** не даёт использовать себя как «вход в чужую приватную сеть». Это защита от превращения сервера в открытый прокси — **не баг**, версией Xray не лечится, конфигом не обходится (кроме одного случая, см. ниже). Проверено вживую 2026-09-23 на связке TrueNAS (портал) ↔ Кра́кен (бридж), Xray 26.4.25. ## Симптом Настроен рабочий reverse-канал (payload проходит, egress проверен). Подаём в него трафик, адресованный в приватную сеть **публичной** стороны: ``` портал: for safety reasons, user a81c3179-312b-4c5e-8a46-6bf3c30c2941 is not allowed to use forward proxy ``` Соединение доходит до портала (`received request for tcp:192.168.2.197:80`), но портал **отказывается его выпускать**. ## Причина (официальная документация) Из доки Xray, outbound `freedom`: > ⚠️ **Default fallback safety policy** (server-side / reverse-proxy scenarios): > - Traffic from **VLESS reverse proxy** blocks **all targets** by default > - Traffic from `VLESS`, `VMess`, `Trojan`, `Shadowsocks`, `Hysteria`, or `WireGuard` inbounds blocks **private and reserved IP ranges** by default > - Other traffic is **fully allowed** by default > > To allow clients access to internal services, explicitly configure `allow` rules and limit them to necessary `network`, `ip`, and `port`. Источник: `https://xtls.github.io/en/config/outbounds/freedom.html` Портал классифицирует запрос как **forward proxy** (клиент просит «сходи на `192.168.2.197`») и режет его по политике. ## Единственная рабочая конфигурация reverse Use Case 2 из доки Xray — «Remote Return Home»: ``` клиент → PUBLIC SERVER (портал) → reverse-out → туннель ↓ INTERNAL DEVICE (бридж) ↓ freedom + finalRules[allow ip <локальная сеть>] ↓ <сеть «внутренней» стороны> ``` 🔴 **Ключевое ограничение:** целевая сеть — **локалка «внутренней» стороны** (той, что держит reverse-соединение). Ходить reverse-каналом в сеть **публичной** стороны **нельзя**. **Пример конфига внутренней стороны (бридж) с разрешением в локалку:** ```json { "protocol": "freedom", "tag": "home-lan", "settings": { "domainStrategy": "AsIs", "finalRules": [ { "action": "allow", "network": "tcp,udp", "ip": ["192.168.1.0/24"] } ] } } ``` И правило роутинга: `{ "inboundTag": ["reverse-in"], "outboundTag": "home-lan" }`. ⚠️ `finalRules` применяется **только если freedom — финальный outbound**. Если у outbound задан `sockopt.dialerProxy`, freedom перестаёт быть финальным и `finalRules` **не применяется** (из доки). ## Чем ЭТО обходится (а чем нет) | Способ | Помогает? | |---|---| | `finalRules: [{action:"allow", ip:[...]}]` | ✅ **да** — но только для локалки «внутренней» стороны | | Смена версии Xray | ❌ нет, это политика, не регрессия | | `allowForwardProxy` в inbound | ⚠️ относится к **обычным** proxy-inbound, не снимает reverse-политику | | `dokodemo-door` / TPROXY / REDIRECT | ❌ нет — меняет способ **приёма** трафика, не политику выпуска | | Смена `listen` на `0.0.0.0` | ❌ нет — влияет только на приём пакетов | ⚠️ **Не путать с issue #6612 / #6242** (регрессии версий, лечатся даунгрейдом/`network_mode: host`). Здесь другой класс: **штатная политика безопасности**, она есть во всех версиях. ## Что делать, если нужен доступ в приватную сеть 1. **Определить, чья сеть «домашняя».** Reverse пускает только в локалку стороны, держащей соединение. Если нужная сеть — на публичной стороне, reverse не подходит. 2. **Альтернативы для «полного IP-стека»** (ICMP, UDP, broadcast/Samba-обзор): - **WireGuard** на узле с белым IP — даёт настоящий L3-VPN, всё проходит. - **SOCKS-прокси на стороне клиента** — только TCP, нужен SOCKS-aware клиент или routing на клиенте. - **Прозрачный прокси на клиенте** (TPROXY) — TCP; UDP требует отдельной работы. 3. **Reverse оставить для того, для чего он есть** — egress через домашний канал (`reverse-in → direct`). ## Сопутствующие питфоллы, найденные в той же сессии - **`dokodemo-door` обязан слушать `0.0.0.0`, не `127.0.0.1`.** При `listen: 127.0.0.1` REDIRECT-трафик с внешнего адреса (клиент `192.168.1.57`) не принимается — соединение отбивается мгновенно (`HTTP 000` за ~0.005 с). - **`iptables -t nat PREROUTING` НЕ действует на локально-исходящий трафик того же хоста.** Тест `curl`-ом с самого узла, где стоит правило, всегда даст `000` и счётчик `0` — это **ложный негатив**. Проверять с постороннего хоста либо через `ip netns` (трафик станет транзитным). - **`redirect: ""` в freedom невалидно** — пустая строка ломает конфиг. Чтобы не менять адрес, использовать `":порт"` (адрес не меняется) либо убрать поле целиком. - **`xray run -test` читает stdin** — под SSH без `< /dev/null` виснет. - **`sudo` через SSH на Кра́кене требует `< /dev/null`** — иначе `Connection closed by remote host`. ## Связанные заметки - [[personal/tech/xray-reverse-tunnel-kraken-truenas]] — рабочий reverse-туннель (egress), архитектура - [[personal/plans/lan-access-via-reverse-tunnel]] — попытка использовать reverse как вход в сеть TrueNAS (тупик)