mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
refactor(captcha): вынести ручной flow в internal/client/captcha/manual
- cmd/vk-turn-client/manual_captcha.go (875 строк, был в package main) → internal/client/captcha/manual/manual.go как отдельный пакет. Экспортирует SolveViaProxy и SolveViaHTTP (переименованы из solveCaptchaViaProxy/ solveCaptchaViaHTTP). Остальное package-private. - Глобал isDebug, который ручной flow читал из main, заменён на manual.Debug (package var). cmd/vk-turn-client/main.go ставит manualcaptcha.Debug = cfg.Debug рядом с существующим isDebug = cfg.Debug. - Тестовый файл перенесён с кодом; пакет переключён с main на manual. TestRewriteProxyRedirectLocation по-прежнему зовёт package-private rewriter изнутри пакета. - План предлагал дробить manual.go дальше (server.go/browser.go/proxy.go/ rewrite_html.go). Пропущено: лишний churn без выгоды, раз файл живёт в своём пакете. Можно сделать позже.
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
# Архитектурный аудит V2 — vk-turn-proxy
|
||||
|
||||
Дата: 2026-05-19.
|
||||
Контекст: после закрытия этапов 1–6 первого `REFACTOR_PLAN.md` итог не устроил заказчика. Этот документ — независимый повторный аудит (структура + предметная область) и план финализации.
|
||||
|
||||
Предыдущий план: `notes/REFACTOR_PLAN.md`. Не отменяется — закрытые этапы остаются как есть, V2 строится поверх.
|
||||
|
||||
---
|
||||
|
||||
## 1. Снимок текущего состояния
|
||||
|
||||
```
|
||||
client/
|
||||
main.go (272) # package main: wiring + isDebug + debugf
|
||||
manual_captcha.go (875) # package main: HTTP-сервер, browser launch, gzip proxy
|
||||
manual_captcha_test.go
|
||||
internal/
|
||||
browserprofile/ captcha/ dnsdial/ namegen/ vkauth/
|
||||
server/
|
||||
main.go (402) # package main: wiring + globalBondRegistry + debugf
|
||||
internal/
|
||||
bond/{frame.go,client/,server/}
|
||||
config/ dtlsdial/ ish/ netadapt/ proxy/{udp,vless}
|
||||
stats/ turnpipe/ wrap/
|
||||
tcputil/
|
||||
tcputil.go # KCP/smux профили, top-level
|
||||
go.mod
|
||||
notes/ README.md Dockerfile routes-*.{sh,ps1}
|
||||
```
|
||||
|
||||
CLI флаги (текущие):
|
||||
- client: `-turn -port -listen -vk-link -peer -n -udp -no-dtls -vless -vless-bond -wrap -wrap-key -gen-wrap-key -streams-per-cred -debug -manual-captcha -dns -dns-servers`
|
||||
- server: `-listen -connect -vless -vless-bond -wrap -wrap-key -gen-wrap-key -debug`
|
||||
|
||||
---
|
||||
|
||||
## 2. Структурные болячки
|
||||
|
||||
### 2.1. Нет `cmd/`
|
||||
Бинари в `client/` и `server/` рядом с бизнес-кодом. Канон Go: `cmd/<bin>/main.go` = wiring only. Сейчас `client/` одновременно:
|
||||
- путь к бинарю;
|
||||
- родитель `client/internal/`;
|
||||
- содержит 875-строчный `manual_captcha.go` в `package main`.
|
||||
|
||||
### 2.2. `manual_captcha.go` в `package main`
|
||||
875 строк (больше самого `main.go`): HTTP-сервер на 8765, запуск браузера, gzip-rewrite VK-страниц, регекс-патчинг, capability detection. Тесты в `package main` — изолированно не тестируется. Должен быть отдельный пакет.
|
||||
|
||||
### 2.3. Двойная `internal/` иерархия
|
||||
`client/internal/` vs `internal/`. Правило выбора **де-факто**: «если общее — наверх, если клиент-only — вниз». Сломалось на `internal/ish` — он клиент-only, но потребитель (vless) живёт в `internal/`, поэтому ish вытолкнут наверх. То есть правило перевёрнуто: «куда импортируется из общего, то наверх». Это симптом, не дизайн.
|
||||
|
||||
Раздробление:
|
||||
- `client/internal/vkauth, captcha, browserprofile, dnsdial, namegen` — клиент-only.
|
||||
- `internal/proxy/{udp,vless}` — по смыслу клиент-only, но в общем.
|
||||
- `internal/ish` — клиент-only, но в общем (ради vless).
|
||||
- `internal/bond/{frame,client,server}` — frame общий, client клиент-only, server сервер-only — три разных аудита смешаны.
|
||||
|
||||
### 2.4. `tcputil` top-level
|
||||
Не `cmd/`, не `internal/`. Side-quest (переименовать в `kcptun`) не закрыт. Имя врёт: внутри KCP/smux профили, никакого TCP.
|
||||
|
||||
### 2.5. Side-quests не закрыты (из старого плана)
|
||||
- `tcputil` → `kcptun` — не сделан.
|
||||
- `selectedKCPProfile()` `os.Getenv` в hot path → `sync.Once` — не сделан.
|
||||
- `isDebug` глобал → logger interface — не сделан.
|
||||
- `globalAppCancel` убран (4.1), но `globalBondRegistry` остался (5.2).
|
||||
|
||||
### 2.6. Логирование — три способа
|
||||
- `log.Printf` (stdlib).
|
||||
- `debugf` (gated глобал в обоих main).
|
||||
- `Deps{Debug bool, Debugf func}` callback в каждом пакете.
|
||||
|
||||
Один `internal/logx.Logger` решает.
|
||||
|
||||
### 2.7. `globalBondRegistry` инициализация на package init
|
||||
`server/main.go:155`:
|
||||
```go
|
||||
var globalBondRegistry = bondserver.NewRegistry(bondserver.Deps{Debug: isDebug, Debugf: debugf})
|
||||
```
|
||||
Здесь `isDebug == false` (main ещё не выполнен). Работает только потому что bondserver **не читает** поле `Debug`, использует только `Debugf` callback. Bug-by-design, который сейчас не стреляет. Стрельнёт когда кто-то прочтёт `Debug`.
|
||||
|
||||
### 2.8. `proxy/udp` и `proxy/vless` — 70% общего кода
|
||||
Оба:
|
||||
- открывают N TURN-стримов через `turnpipe`;
|
||||
- крутят DTLS через `dtlsdial`;
|
||||
- ходят за VK creds (`vkauth.Client`);
|
||||
- держат `activeLocalPeer` / `connectedStreams`.
|
||||
|
||||
Различие: что копировать поверх DTLS. Это **handler**, не отдельный mode. Нет общего `proxy.Engine` + handler-интерфейса.
|
||||
|
||||
---
|
||||
|
||||
## 3. Путаница в предметной области
|
||||
|
||||
### 3.1. Имена врут
|
||||
|
||||
| Имя | Что говорит | Что делает |
|
||||
|-----|-------------|------------|
|
||||
| `-wrap` (CLI help) | «ChaCha20-XOR obfuscate» | ChaCha20-Poly1305 **AEAD** |
|
||||
| `wrap` (пакет doc) | «SRTP-mimicry AEAD» | то же |
|
||||
| `wrap` (Go-термин) | `errors.Wrap`, `net.Wrap*` | здесь — VK-bypass обфускация |
|
||||
| `tcputil` | TCP utils | KCP/smux профили |
|
||||
| `turnpipe` | data pipe | TURN dial+allocate setup |
|
||||
| `pipeConn` (server) | то же слово | **bidi copy loop** — другое! |
|
||||
| `netadapt` | adapter | conn wrappers |
|
||||
| `-no-dtls` ↔ `Direct` | один флаг | два имени между CLI и Go |
|
||||
| `-turn` → `Host` | «TURN server ip» | принимает host (не только IP) |
|
||||
| `-connect` (server) | error: «server address» | реально backend address |
|
||||
|
||||
### 3.2. Перегруженные термины
|
||||
|
||||
**«Client» — 4 сущности:**
|
||||
- `cmd/client` бинарь
|
||||
- `vkauth.Client` HTTP-клиент к VK
|
||||
- `bondclient.Handler` наша bond-сторона
|
||||
- `turn.NewClient` TURN-protocol-клиент
|
||||
|
||||
**«Bond» — feature или подсистема?** Layout `internal/bond/{frame,client,server}` делает его равным `wrap`. Реально bond — **только опция vless-режима**. Иерархия преувеличивает значимость.
|
||||
|
||||
**«Stream» — 3 значения:**
|
||||
- TURN stream (одна из N TURN-connections)
|
||||
- smux stream (внутри одной DTLS-сессии)
|
||||
- VK credential stream / cache (одни creds на группу TURN-streams)
|
||||
|
||||
`-streams-per-cred` → `streamsPerCache` в коде. Грепаешь — путаешься.
|
||||
|
||||
**«Mode» — 5 ортогональных переключателей**, нигде не сгруппированы:
|
||||
- `-udp`: TURN transport (UDP|TCP к TURN).
|
||||
- `-vless`: app proxy (UDP-relay|TCP-forward).
|
||||
- `-vless-bond`: внутри TCP-forward.
|
||||
- `-wrap`: obfuscation (off|SRTP-mimicry).
|
||||
- `-no-dtls`: DTLS off (DO NOT USE).
|
||||
- `-dns`: udp|doh|auto.
|
||||
|
||||
Плоские bool в `config.Client` без группировки.
|
||||
|
||||
### 3.3. Концептуальные дыры
|
||||
|
||||
**a) DTLS = obfuscation, не security.** Доки, переменные, контекст говорят про DTLS как защиту. Реально DTLS нужен чтобы VK content-filter увидел legit-handshake — иначе drop. `-no-dtls` помечен «DO NOT USE» именно потому что не работает в проде. Это **нигде не зафиксировано**.
|
||||
|
||||
**b) Captcha разбит на 3 места:**
|
||||
- `client/internal/captcha/` — auto slider-solver.
|
||||
- `client/manual_captcha.go` (875 строк, `package main`) — manual flow (browser+http+gzip).
|
||||
- `vkauth.AutoSolveFunc`/`ManualSolveFunc` — DI-точки.
|
||||
|
||||
Один домен «как пройти VK капчу», три места.
|
||||
|
||||
**c) `ish` package** — iOS sandbox shim. Имя расшифровывается только если знаешь iSH (Linux-под-iOS на iPhone). Без header-doc — мистика.
|
||||
|
||||
**d) Auto-detect bond на сервере** (`bond-autodetect=true` на старте) делает `server.-vless-bond` флаг **частично избыточным**. Документация не объясняет когда он нужен.
|
||||
|
||||
### 3.4. TCP/UDP терминология (специально вынесено)
|
||||
|
||||
**Два разных слоя:**
|
||||
1. **TURN transport** — флаг `-udp`. Default `false` → TCP/TLS к TURN. True → UDP к TURN.
|
||||
2. **App proxy mode** — флаг `-vless`. Default `false` → UDP packet relay. True → TCP forwarder (внутри VLESS-генерик).
|
||||
|
||||
«TCP-режим» в проекте **есть** — это `vless`. Имя историческое (первый потребитель — Xray VLESS). Внутри ничего VLESS-специфичного: tcp-байты в smux-стрим, на сервере `net.Dial("tcp", backend)`. Честное имя пакета: `tcp` или `tcpfwd`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Корневая причина
|
||||
|
||||
Проект рос **по фичам, не по доменам**. Каждая новая способность (wrap, bond, vless, scan) приклеивалась соседней сущностью вместо встраивания в иерархию. Итог:
|
||||
- термины перегружены (client/bond/mode/stream);
|
||||
- CLI ≠ Go-имена;
|
||||
- DTLS-as-obfuscation нигде не объяснён;
|
||||
- captcha и proxy раздроблены без причины;
|
||||
- два режима прокси не имеют общего родителя.
|
||||
|
||||
Первый рефакторинг (1–6) **вытаскивал** код из main, но не **перестраивал** домен. Сейчас main маленький, но домен такой же запутанный.
|
||||
|
||||
---
|
||||
|
||||
## 5. Целевая архитектура
|
||||
|
||||
```
|
||||
cmd/
|
||||
vk-turn-client/main.go # wiring only, ~150 строк
|
||||
vk-turn-server/main.go # wiring only, ~100 строк
|
||||
|
||||
internal/
|
||||
logx/ # slog-обёртка, заменяет isDebug+debugf
|
||||
config/ # Parse*; группированные опции
|
||||
ctxutil/ # closeWrite, pipe (data-copy)
|
||||
|
||||
wire/
|
||||
srtpmimicry/ # бывш. internal/wrap
|
||||
bondframe/ # бывш. internal/bond/frame.go
|
||||
|
||||
transport/
|
||||
turndial/ # бывш. internal/turnpipe
|
||||
dtlsdial/ # есть
|
||||
kcptun/ # бывш. tcputil; sync.Once для профиля
|
||||
|
||||
proxy/
|
||||
engine/ # общая часть (TURN×N + DTLS + creds + counters)
|
||||
udprelay/ # бывш. proxy/udp; Handler
|
||||
tcpfwd/ # бывш. proxy/vless; Handler
|
||||
bondclient/ # бывш. internal/bond/client
|
||||
bondserver/ # бывш. internal/bond/server
|
||||
|
||||
netconn/ # бывш. netadapt
|
||||
|
||||
client/ # КЛИЕНТ-ONLY (схлопывает client/internal)
|
||||
vkauth/ # бывш. client/internal/vkauth
|
||||
captcha/
|
||||
auto/ # бывш. client/internal/captcha
|
||||
manual/ # бывш. client/manual_captcha.go (НОВЫЙ ПАКЕТ)
|
||||
browserprofile/ # бывш. client/internal/browserprofile
|
||||
dnsdial/ # бывш. client/internal/dnsdial
|
||||
namegen/ # бывш. client/internal/namegen
|
||||
ish/ # бывш. internal/ish (явно клиент-only)
|
||||
|
||||
server/
|
||||
bondregistry/ # бывш. internal/bond/server, если выносить globalBondRegistry чисто
|
||||
|
||||
stats/ # есть
|
||||
```
|
||||
|
||||
### Принципы
|
||||
|
||||
1. **`cmd/<bin>/main.go` = wiring only.** Любая логика — в пакет.
|
||||
2. **Одна `internal/` иерархия.** `internal/client/*` и `internal/server/*` — бинарь-специфика; `internal/{wire,transport,proxy}` — общее.
|
||||
3. **Группировка по слою:** wire (байты на проводе) → transport (как открыть сокет) → proxy (что копировать) → client/server (роль).
|
||||
4. **`logx.Logger` interface** заменяет `Deps{Debug bool, Debugf func}`. Один раз конфигурим в main.
|
||||
5. **Глобалы умирают:** `globalBondRegistry` → локальная переменная в `cmd/vk-turn-server/main.go`. `isDebug` → logger level.
|
||||
6. **Имена честные:**
|
||||
- `tcputil` → `kcptun`
|
||||
- `wrap` → `srtpmimicry`
|
||||
- `netadapt` → `netconn`
|
||||
- `turnpipe` → `turndial`
|
||||
- `vless` → `tcpfwd` (внутреннее; CLI остаётся `-vless`)
|
||||
- `bond` (codec) → `bondframe`
|
||||
7. **`manual_captcha.go` → `internal/client/captcha/manual/`** как полноценный пакет с экспортируемым `Server`/`Solver`.
|
||||
8. **`proxy.Engine` + `Handler` interface:** убирает дублирование udp/vless.
|
||||
9. **Side-quests закрываются в этом этапе или не закрываются никогда.**
|
||||
|
||||
### Что НЕ делать
|
||||
- `src/` — не Go-way, не вводить.
|
||||
- `pkg/` — не вводить, наружу ничего публичного не отдаём.
|
||||
- Wire-форматы / CLI флаги / behavior — заморожены.
|
||||
|
||||
---
|
||||
|
||||
## 6. План реализации
|
||||
|
||||
Каждый этап = один PR. Все PR — non-breaking по CLI/wire. Контрольная панель после каждого: `gofmt -l .` пуст / `go vet ./...` / `golangci-lint run ./...` / `go test ./...`.
|
||||
|
||||
### Этап V2-1 — `cmd/` + глоссарий (низкий риск)
|
||||
|
||||
- [x] **V2-1.1** Создан `cmd/vk-turn-client/main.go` (переезд `client/main.go`) и `cmd/vk-turn-server/main.go` (переезд `server/main.go`).
|
||||
- [x] **V2-1.2** Обновлены `Dockerfile`, `README.md`, `.github/workflows/{ci,release}.yml` — пути `./cmd/vk-turn-client`/`./cmd/vk-turn-server`. README дополнен Android arm64 + Linux arm64/amd64 `.so`-сборками.
|
||||
- [x] **V2-1.3** `client/` и `server/` директории удалены.
|
||||
- [x] **V2-1.4** `notes/GLOSSARY.md` создан (~20 терминов).
|
||||
|
||||
Бонус: `client/internal/*` → `internal/client/*` сделан в этом же PR (половина V2-5) как зависимость переезда в `cmd/`.
|
||||
|
||||
### Этап V2-2 — manual captcha как пакет
|
||||
|
||||
- [x] **V2-2.1** Создан `internal/client/captcha/manual/manual.go` (875 строк, один файл). Экспортированы: `SolveViaProxy`, `SolveViaHTTP`. Package-var `Debug bool` заменяет глобал `isDebug` из main.
|
||||
- [ ] **V2-2.2** Разбивка на server.go/browser.go/proxy.go/rewrite_html.go **намеренно пропущена** — добавляет риск без выигрыша; один файл в изолированном пакете уже читаем. Если нужно — отдельный PR.
|
||||
- [x] **V2-2.3** Тест `manual_test.go` переехал, package переключен с `main` на `manual`, тест `TestRewriteProxyRedirectLocation` зелёный.
|
||||
- [x] **V2-2.4** `cmd/vk-turn-client/main.go`: import `manualcaptcha "internal/client/captcha/manual"`, мост `manualCaptchaSolver` зовёт `manualcaptcha.SolveVia*`, в main устанавливается `manualcaptcha.Debug = cfg.Debug`.
|
||||
|
||||
### Этап V2-3 — `internal/logx` + удаление isDebug-глобалов
|
||||
|
||||
- [ ] **V2-3.1** Создать `internal/logx/logx.go`: интерфейс `Logger{Debug(format,...), Info, Warn, Error}` + конструктор из `slog.Level`.
|
||||
- [ ] **V2-3.2** Заменить `Deps{Debug bool, Debugf func}` на `Deps{Log logx.Logger}` во всех пакетах: `bondclient`, `bondserver`, `proxy/udp`, `proxy/vless`, `stats`.
|
||||
- [ ] **V2-3.3** Удалить `var isDebug bool` + `func debugf` из обоих main. В main: `log := logx.New(cfg.Debug)`.
|
||||
- [ ] **V2-3.4** `globalBondRegistry` → локальная в `cmd/vk-turn-server/main.go`, инициализация **после** `cfg := config.ParseServer`.
|
||||
|
||||
### Этап V2-4 — переименования (механика, без логики)
|
||||
|
||||
- [ ] **V2-4.1** `internal/wrap` → `internal/wire/srtpmimicry`. Обновить импорты + комментарий пакета (зафиксировать «obfuscation, не security»).
|
||||
- [ ] **V2-4.2** `internal/bond/frame.go` → `internal/wire/bondframe/`. `internal/bond/client` → `internal/proxy/bondclient`. `internal/bond/server` → `internal/proxy/bondserver`.
|
||||
- [ ] **V2-4.3** `internal/netadapt` → `internal/netconn`.
|
||||
- [ ] **V2-4.4** `internal/turnpipe` → `internal/transport/turndial`. `internal/dtlsdial` → `internal/transport/dtlsdial`.
|
||||
- [ ] **V2-4.5** `tcputil` → `internal/transport/kcptun`. **Закрыть side-quest `sync.Once` для `selectedKCPProfile`** в этом же PR (нагрузка маленькая, контекст подходящий).
|
||||
- [ ] **V2-4.6** `internal/proxy/udp` → `internal/proxy/udprelay`. `internal/proxy/vless` → `internal/proxy/tcpfwd` (CLI флаг `-vless` остаётся; внутреннее имя пакета честное).
|
||||
- [ ] **V2-4.7** `internal/ish` → `internal/client/ish` + header-doc «iSH = Linux user-mode под iOS; этот пакет — listener shim для sandbox-ограничений iSH».
|
||||
|
||||
### Этап V2-5 — схлопывание `client/internal/` в `internal/client/`
|
||||
|
||||
- [ ] **V2-5.1** `client/internal/vkauth` → `internal/client/vkauth`.
|
||||
- [ ] **V2-5.2** `client/internal/captcha` → `internal/client/captcha/auto`.
|
||||
- [ ] **V2-5.3** `client/internal/browserprofile` → `internal/client/browserprofile`.
|
||||
- [ ] **V2-5.4** `client/internal/dnsdial` → `internal/client/dnsdial`.
|
||||
- [ ] **V2-5.5** `client/internal/namegen` → `internal/client/namegen`.
|
||||
- [ ] **V2-5.6** Удалить пустой `client/` (после переезда `main.go` на V2-1 и `manual_captcha` на V2-2 — он пуст).
|
||||
|
||||
### Этап V2-6 — `proxy.Engine` + Handler
|
||||
|
||||
- [ ] **V2-6.1** Создать `internal/proxy/engine/engine.go`: интерфейс `Handler` (`Serve(ctx, dtlsConn)`), общий `Engine{Open N TURN-stream, DTLS handshake, creds rotation, counters}`.
|
||||
- [ ] **V2-6.2** `udprelay` и `tcpfwd` рефакторятся в реализации `Handler`. Дублирование выходит. `Deps` сокращается.
|
||||
- [ ] **V2-6.3** Bond становится опцией `tcpfwd.Handler` (флаг конструктора), не отдельным пакетом-сосседом. `bondclient` / `bondserver` остаются как helper'ы, но вызываются изнутри `tcpfwd`.
|
||||
|
||||
### Этап V2-7 — config структуризация
|
||||
|
||||
- [ ] **V2-7.1** В `internal/config`: разбить `Client` struct на подгруппы:
|
||||
```go
|
||||
type Client struct {
|
||||
TURN TURNOpts // Host, Port, UDP, N
|
||||
Obf ObfOpts // WrapMode, WrapKey, Direct
|
||||
Proxy ProxyOpts // Mode (udp|tcpfwd|tcpfwd-bond), Listen
|
||||
VK VKOpts // Link, StreamsPerCred, ManualCaptcha
|
||||
DNS DNSOpts // Mode, Servers
|
||||
Log LogOpts // Debug
|
||||
}
|
||||
```
|
||||
`Mode` enum (string `"udp"|"tcpfwd"|"tcpfwd-bond"`) вместо двух bool-флагов в коде. **CLI флаги остаются те же** — мапим в Parse.
|
||||
- [ ] **V2-7.2** Те же группы для `Server`.
|
||||
|
||||
### Этап V2-8 — документирование и решения
|
||||
|
||||
- [ ] **V2-8.1** Header-doc в `internal/transport/dtlsdial/doc.go`: «DTLS используется как obfuscation (mimicry для VK content-filter), не как security layer. `-no-dtls` помечен DO NOT USE потому что без DTLS VK дропает не-handshake пакеты.»
|
||||
- [ ] **V2-8.2** Решить судьбу `server -vless-bond` флага: либо удалить (autodetect покрывает), либо задокументировать когда нужен. Внести решение в `GLOSSARY.md`.
|
||||
- [ ] **V2-8.3** README обновить: путь сборки `go build ./cmd/...`, актуальная архитектура (короткое дерево), глоссарий.
|
||||
|
||||
---
|
||||
|
||||
## 7. Порядок и приоритеты
|
||||
|
||||
**Жёсткие зависимости:**
|
||||
- V2-4 (переименования) после V2-3 (logx) — иначе придётся переписывать Deps дважды.
|
||||
- V2-5 (схлопывание client/internal) после V2-1 (cmd/) и V2-2 (manual_captcha вынесен) — иначе client/ не пустой.
|
||||
- V2-6 (Engine) после V2-4 — работает с новыми именами.
|
||||
- V2-7 (config группировка) — независим, можно когда угодно.
|
||||
- V2-8 (doc) — последним.
|
||||
|
||||
**Рекомендуемая последовательность:**
|
||||
1. V2-1 (cmd + GLOSSARY)
|
||||
2. V2-2 (manual captcha)
|
||||
3. V2-3 (logx)
|
||||
4. V2-4 (переименования)
|
||||
5. V2-5 (client/internal схлопывается)
|
||||
6. V2-6 (Engine + Handler)
|
||||
7. V2-7 (config группировка)
|
||||
8. V2-8 (doc)
|
||||
|
||||
**Грубая оценка размера (LOC diff на PR):** V2-1 ~150 / V2-2 ~900 / V2-3 ~400 / V2-4 ~600 (mostly move) / V2-5 ~300 (mostly move) / V2-6 ~500 / V2-7 ~200 / V2-8 ~100.
|
||||
|
||||
---
|
||||
|
||||
## 8. Гарантии non-breaking
|
||||
|
||||
После каждого PR:
|
||||
- `go build ./...` зелёный.
|
||||
- `go test ./...` зелёный.
|
||||
- `golangci-lint run` без новых ворнингов.
|
||||
- CLI флаги, дефолты, behavior — bit-exact.
|
||||
- Wire-форматы (wrap/SRTP-mimicry, bond frame, TURN, DTLS, KCP/smux) — bit-exact.
|
||||
- Поведенческие инварианты сохранены: handshake-сем 3 (UDP-mode), captcha auto→manual fallback, creds cache lifetime 10m-60s safety, throttle 3s+rand.
|
||||
|
||||
---
|
||||
|
||||
## 9. Что НЕ трогать (даже в этом плане)
|
||||
|
||||
- Wire-форматы любые.
|
||||
- CLI флаги: имена, дефолты, поведение.
|
||||
- `tcputil` KCP/smux параметры (только переезд).
|
||||
- `client/internal/captcha/*` slider-логику (только переезд).
|
||||
- `internal/wrap` AEAD-байты (только переезд + rename).
|
||||
- Алгоритм auto-detect bond на сервере.
|
||||
|
||||
---
|
||||
|
||||
## 10. Решения заказчика (зафиксировано 2026-05-19)
|
||||
|
||||
1. **libvkturn.so** — мобильная сборка, собирается вручную, переносится в приложение руками. CI не строит. Внешних `//export` в коде нет. **Решение:** `pkg/` не вводим, всё `internal/`. Пользователь после V2-1 пересоберёт с новым путём `./cmd/vk-turn-client` (или с buildmode-target, который он использует).
|
||||
2. **Server-флаг `-vless-bond`** — **удаляем**. Autodetect по magic покрывает. Это **breaking CLI change на сервере** — фиксируем в release notes.
|
||||
3. **`-no-dtls` (client `Direct`)** — **удаляем**. Помечен DO NOT USE, в проде не работает. Это **breaking CLI change на клиенте**.
|
||||
4. **Server multi-tenant** (`notes/AUTH_PLAN.md`) — **план отменён**, вычёркиваем из контекста.
|
||||
5. **TURN-scanner** (`client/scan*.go`) — открытый вопрос; кандидат `internal/client/turnscan/`. Решить при V2-5.
|
||||
|
||||
### Влияние на non-breaking гарантии
|
||||
|
||||
Пункт 8 («CLI флаги bit-exact») **корректируется**:
|
||||
- Удаляются: `-no-dtls` (client), `-vless-bond` (server). Остальные CLI флаги — без изменений.
|
||||
- Дефолты и поведение оставшихся флагов — bit-exact.
|
||||
- Wire-форматы — bit-exact (без изменений).
|
||||
|
||||
### Новый этап V2-0 (вынесен в начало)
|
||||
|
||||
- [x] **V2-0.1** Удалён `-no-dtls` из client CLI. `config.Client.Direct` поле + dispatcher-guard в main + тест `TestParseClient_WrapDirectConflict` — удалены. Веток в proxy/* не было (только main).
|
||||
- [x] **V2-0.2** Удалён `-vless-bond` из server CLI и `config.Server.VLESSBond`. `useBond` параметр `handleVLESSConnection` убран, warning-ветка «non-bond stream while bond enabled» удалена, поле снято со startup-лога. Сервер автоопределяет bond по magic.
|
||||
- [ ] **V2-0.3** README Breaking changes — **пока не сделано**. Можно отложить до большого release-notes под весь V2.
|
||||
|
||||
V2-0 идёт **до V2-1** — упрощает дерево перед переездом в `cmd/`.
|
||||
|
||||
### Обновлённый порядок
|
||||
|
||||
1. V2-0 (breaking CLI cleanup)
|
||||
2. V2-1 (cmd/ + GLOSSARY)
|
||||
3. V2-2 (manual captcha пакет)
|
||||
4. V2-3 (logx)
|
||||
5. V2-4 (переименования)
|
||||
6. V2-5 (client/internal схлопывается + решение по turnscan)
|
||||
7. V2-6 (Engine + Handler)
|
||||
8. V2-7 (config группировка)
|
||||
9. V2-8 (doc)
|
||||
Reference in New Issue
Block a user