Files
obsidian-vault/personal/tech/xray-reverse-limits-private-network.md
T

119 lines
7.7 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: 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 (тупик)