без RTP-профиля паковать нечего, а в tcp-режиме pacing ломает RTT/конгешн
KCP. Раньше флаг в tcp молча игнорировался. Валидация симметрична на
клиенте и сервере.
Флаг -browser chrome|firefox (default firefox, Chrome - escape-hatch), client-local для VK-auth, в freeturn:// URI не идёт. browserprofile.ForKind даёт канонные UA/JA3/Accept-Language; ApplyFhttp шлёт sec-ch-ua* только для Chrome (Firefox их не отправляет). dial.go выбирает profiles.Firefox_147 / Chrome_146 под UA.
Control-plane TLS-dial переведён на MultiSplitWriteConn (фрагментация SNI).
rtpopus2 несёт RTP header extension (RFC 8285 one-byte: X=1,
ssrc-audio-level + transport-cc) - ближе к современному WebRTC, чем
rtpopus (X=0). Wire несовместим с rtpopus, overhead 52 против 40.
wire.Codec - общий контракт профиля; NewClientCodec/Listen диспатчат
по -obf-profile, RelayPacketConn обобщён по Codec. Профиль тянется
в pipeline (раньше шёл только ключ obf).
Попутно: tcpfwd на 1-based streamID (единый базис с udprelay для
CacheID); cmd/client задаёт probe-host login.vk.ru для vk.
freeturn:// теперь несёт base64url(json) вместо query-string. Поля:
v, provider, peer, transport, mode, bond, obf, key, n, spc, cid,
listen, dns, dnss, mcap, name. Версионирован полем v=1.
config.PeekSubURL: pre-parse -sub до ParseClient, URI первой ноды
подсовывается позиционным аргументом - применение общим путём.
ParseClient применяет все новые поля URI (N, StreamsPerCred,
ClientID, Listen, DNSMode, DNSServers, ManualCaptcha, transport).
Клиент всегда отправляет Client ID первой DTLS app-record, сервер
всегда читает. Флаг -auth и URI-параметр auth удалены — рассинхрон
client/server невозможен. -clients-file на сервере включает только
проверку ID по allowlist clients.json.
Также:
- clients.json и client_config.json пишутся с правами 0o600
- исправлены все находки golangci-lint (errcheck, gosec, govet shadow)
Примечание: удалён флаг -auth и URI-параметр auth; Client ID теперь
всегда в первой записи туннеля — старые клиенты/серверы несовместимы.
- internal/clientsdb: БД клиентов с hot-reload + length-prefixed ID wire
- internal/uri: parse/encode share-ссылок freeturn://
- internal/sub: загрузка и парсинг подписок (sub.md)
- client: флаги -auth, -client-id, -sub; позиционный URI; ID через crypto/rand
- server: подкоманда clients (add/remove/list), чтение ID под -clients-file
- запись/чтение ID учитывают DTLS record-orientation (буфер на запись целиком)
- docs: uri.md, sub.md; правки flags/deploy/quickstart
- снят UTF-8 BOM по всем исходникам
Переименовать переменные-указатели флагов под имена флагов 1:1 (vklink→link,
host→turn, obfProfileRaw→obfProfile, убрать суффиксы *Flag/*Raw/*Hex). Урезать
многословные описания флагов; убрать аннотации (default), раз пакет flag
печатает их сам.
Сейчас нужен только VK-провайдер. internal/provider/static и связанные флаги
-static-user/-static-pass/-static-addr удалены, валидация и тесты обновлены.
Интерфейс provider.Provider остаётся — слот для будущих реализаций сохранён в
нейтральных формулировках doc-комментариев.
Вытаскивает источник TURN-creds из захардкоженной привязки к VK в интерфейс
internal/provider.Provider. Pipeline (proxy/udprelay, proxy/tcpfwd) работает
только через интерфейс — без VK-specific импортов и sentinel'ов.
Реализации:
- internal/provider/vk: фасад над client/vkauth (требует -link)
- internal/provider/static: фиксированные creds для self-hosted coturn /
metered / любого RFC 5766/8656 TURN (флаги -static-user/-static-pass/
-static-addr)
Изменения интерфейса:
- common.GetCredsFunc дропнула link (provider держит сам)
- udprelay AuthHandler: LockoutUntilUnix → BackoffUntilUnix
- vkauth sentinels обёрнуты в provider.ErrBackoffActive / ErrFatalNoStreams
через errors.Join (backward-compat сохранён)
Документация: docs/providers.md (новый), docs/glossary.md и docs/flags.md
обновлены.
Заменяет плоские структуры config.Client / config.Server на
доменно-сгруппированные под-структуры, чтобы форма повторяла концептуальные
слои прокси:
type Client struct {
TURN TURNOpts // Host, Port, UDP, N
Obf ObfOpts // WrapMode, WrapKey, GenWrapKey
Proxy ProxyOpts // Mode, Listen, Peer
VK VKOpts // Link, StreamsPerCred, ManualCaptcha
DNS DNSOpts // Mode, Servers
Log LogOpts // Debug
}
type Server struct { Obf; Proxy{Mode, Listen, Connect}; Log }
Enum ProxyMode (udp | tcpfwd | tcpfwd-bond) заменяет два параллельных bool
VLESSMode / VLESSBond в коде вызывающих. Поверхность CLI (-vless, -vless-bond)
не изменена; clientProxyMode / serverProxyMode в Parse* мапят bool в enum.
cmd/vk-turn-{client,server}/main.go: каждый cfg.X теперь cfg.Group.X. Тесты
обновлены; новый TestParseClient_ProxyMode покрывает все четыре комбинации
флагов (включая -vless-bond без -vless, который молча игнорируется как и раньше).
Без изменений флагов CLI, дефолтов, поведения и wire-формата. go build /
go vet / go test / gofmt чисто.
internal/wrap → internal/wire/srtpmimicry; правки doc ("обфускация, не security").
internal/bond/{frame,client,server} → internal/wire/bondframe,
internal/proxy/bondclient, internal/proxy/bondserver.
internal/netadapt → internal/netconn.
internal/turnpipe → internal/transport/turndial; internal/dtlsdial →
internal/transport/dtlsdial.
tcputil → internal/transport/kcptun; selectedKCPProfile и selectedFEC теперь
кешируются через sync.Once (env читается один раз вместо per-connection).
internal/proxy/udp → internal/proxy/udprelay; internal/proxy/vless →
internal/proxy/tcpfwd. Флаг CLI -vless сохранён.
internal/ish → internal/client/ish; doc пакета расширен (iSH = Linux user-mode
эмулятор на iOS, только linux/386).
Чисто механическое переименование + обновление import-путей/идентификаторов.
Wire-формат, флаги CLI и поведение не изменены. go build + go test зелёные.
Чистка CLI (breaking):
- Клиент: убран -no-dtls (был помечен DO NOT USE; VK content-filter дропает
payload без DTLS-handshake, так что прямой путь в проде не работал). Поле
config.Client.Direct, guard диспатчера в main и TestParseClient_WrapDirectConflict
удалены.
- Сервер: убран -vless-bond. Сервер уже автоопределяет bond по magic-префиксу
на первом smux-стриме (bond-autodetect=true), флаг был избыточен. Поле
config.Server.VLESSBond, параметр useBond у handleVLESSConnection и
ветка-предупреждение "non-bond stream while bond enabled" удалены.
- Клиентский -vless-bond остаётся — он по-прежнему управляет страйпингом на
стороне клиента.
Wire-форматы не тронуты. Оба удаления флагов — breaking CLI-изменения.
ParseClient/ParseServer возвращают валидированные структуры; main становится
связкой. Валидация без сайд-эффектов (без DNS/сети); main держит ResolveUDPAddr,
установки dnsdial.* и вывод gen-wrap-key. Сервер теперь переиспользует
wrap.GenKeyHex/wrap.DecodeKey вместо своего hex+rand пути.
client/main.go: 319 → 272. server/main.go: 424 → 402.
19 тестов покрывают дефолты, санитизацию vk-link, отсутствующие флаги,
валидацию -dns, конфликт wrap+no-dtls, декод wrap-key, положительность
streams-per-cred, clamp n, split dns-servers и short-circuit gen-wrap-key.
Флаги CLI, дефолты и поведение не изменены. Две строки ошибок
("Need peer address!" / "Need vk-link!") переведены в нижний регистр под
revive; не часть wire-контракта.