# sdm-xray: stealth transport — спецификация для интеграции Версия: v0.2.1 (черновик). Статус: работает (клиент/сервер — форк Xray-core). ## 1. Что это `stealth` — кастомный сетевой транспорт для Xray-core (поле `network: "stealth"` в `streamSettings`). Каждая туннельная сессия = **один долгоживущий HTTP/2 POST-стрим** (ALPN `h2`): тело запроса несёт кадры клиент→сервер, тело ответа — кадры сервер→клиент (двунаправленно, как gRPC/стриминговые загрузки). Снаружи выглядит как обычный HTTPS к API-эндпоинту реального сайта. Цель — анти-DPI: ротация путей на каждое соединение, браузерный TLS (uTLS chrome), padding/pacing, ретрай со сменой identity, зеркало реального сайта для зондов. ## 2. Конфигурация (streamSettings) ```json { "network": "stealth", "stealthSettings": { "key": "<общий секрет, клиент и сервер совпадают>", "padMax": 2048, "padProb": 50, "paceMs": 0, "paceJitterMs": 0, "path": "/", // один путь (fallback) "paths": ["/api/t04d12b46/", "/api/v2/telemetry/", "/collect/", "/ingest/"], "ports": [443], // опция: ротация портов "bps": 0, // опция: rate-limit, 0 = выкл "target": "https://www.iana.org", // опция: зеркало (сервер) "decoy": false, // опция: фоновый трафик "decoyEverySecs": 60, "decoyTarget": "https://www.cloudflare.com/cdn-cgi/trace", "padProfile": "browser", // "browser" | "uniform" "retries": 3 }, "security": "tls", // или "reality" "tlsSettings": {"serverName": "...", "fingerprint": "chrome"} } ``` Клиент и сервер должны иметь одинаковые `key`, `paths` (список путей). Порты — только на клиенте (сервер слушает каждый порт отдельным inbound). ## 3. Wire-протокол (поверх TLS+HTTP/2) ### 3.1 Установка сессии 1. Клиент: TLS 1.3 (uTLS, fingerprint chrome, ALPN h2) к серверу:443. 2. HTTP/2: клиент открывает **один POST** на один из `paths`. 3. Тело запроса (клиент→сервер) — поток кадров. **Первый кадр = AUTH**: `[len][0xFE][key]`. 4. Сервер читает AUTH: - ключ верный → отвечает `200` (заголовки + flush), дальше тело ответа — поток кадров сервер→клиент; - ключ неверный/нет → `404` + закрытие. 5. После 200 обе стороны обмениваются кадрами DATA/PAD двунаправленно. ### 3.2 Формат кадра ``` [4 байта, big-endian длина = 1 + len(payload)] [1 байт type] [payload] ``` Типы: | type | значение | смысл | |---|---|---| | DATA | 0x01 | данные туннеля (VLESS-поток) | | PAD | 0x02 | padding (читатель пропускает) | | AUTH | 0xFE | первый кадр тела запроса, payload = ключ | | CLOSE| 0xFF | закрытие | Лимит кадра: 64 КБ. Поток байтов в DATA-кадрах сохраняет порядок (VLESS видит обычный поток); PAD-кадры прозрачны для читателя. ### 3.3 Сервер: зеркало для зондов Не-туннельные запросы (GET/HEAD к любым путям) сервер **реверсивно проксирует на `target`** (реальный сайт): переписывает `Location`, HTML `href/src/content`, CSS `url(...)` на свой домен. POST на туннельные пути без валидного AUTH → 404. Пустой `target` → встроенная страница-заглушка. ## 4. Клиент: ротация и ретрай - Клиент на каждое соединение выбирает **случайный путь** из `paths`. - При неудаче — ретрай со свежим путём/портом (`retries`). - Padding: после каждого DATA-кадра с вероятностью `padProb` идёт PAD-кадр размера до `padMax` (профиль `browser` — перекос к мелким). - Pacing: `paceMs` + `paceJitterMs` (мин. интервал между кадрами). - Мультиплекс: несколько сессий идут по одному TLS+HTTP/2 каналу (несколько POST-стримов). ## 5. Требования к сборке - Go 1.26, golang.org/x/net/http2, golang.org/x/time/rate, refraction-networking/utls. - `config.proto` → `config.pb.go` генерится: `protoc -I. --go_out=. --go_opt=paths=source_relative transport/internet/stealth/config.proto`. - Бинарь: `go build ./main` (клиент и сервер — один бинарь). ## 6. Файлы, которые нужно добавить/изменить в Xray-core **Новые** (пакет транспорта): - `transport/internet/stealth/config.proto` (+ сгенерированный `config.pb.go`) - `transport/internet/stealth/config.go` — регистрация конфига - `transport/internet/stealth/framing.go` — кадры - `transport/internet/stealth/conn.go` — h2Conn (net.Conn поверх POST-стрима) - `transport/internet/stealth/dialer.go` — клиент (TLS/REALITY, ротация, ретрай) - `transport/internet/stealth/hub.go` — сервер (http.Server, зеркало, AUTH) **Изменённые** (в `infra/conf`): - `infra/conf/transport_internet.go` — `case "stealth"`, поле `StealthSettings`, ветка сборки, разрешение stealth в REALITY-проверке - `infra/conf/transport_method.go` — struct `StealthConfig` + `Build()` Полный исходник и изменения — в репозитории (публичном): https://git.my-handbook.ru/ded_ikar/sdm-xray