- Removed hardcoded owner/name from release.github – not needed when using GITHUB_TOKEN.
- Replaced explicit repo strings with {{ .Env.GITHUB_REPOSITORY }} for Docker image names and the org.opencontainers.image.source label.
- Makes the config reusable across forks – no manual edits required when moving the project.
без 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).
MultiSplitWriteConn парсит TLS ClientHello, находит SNI host_name и режет первый сегмент внутри него на ~трети с джиттером - registrable-домен гарантированно пересекает границу TCP-сегмента, DPI без реассемблинга не собирает hostname. Фоллбэк на одиночный рез offset 6, если SNI не найден.
turndial: STUN-split offset рандомизирован в [5,7] (рез внутри magic cookie), убран статический фингерпринт фикс-offset.
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.
auto-режим пробил UDP/53 нейтральным dns.google и залипал на UDP
навсегда. При выборочной фильтрации (dns.google резолвится, целевой
хост - нет) это вело к таймаутам резолва. Проба теперь валидирует
резолв реального хоста; при провале UDP уходит на DoH. Добавлен
рантайм-recovery в обе стороны: серия неудач UDP -> DoH, периодическая
перепроба DoH -> UDP.
CacheID делил streamID/streamsPerCache, но streamID 1-based: поток
с номером, кратным streamsPerCache, переваливал в соседний bucket
и тянул лишнюю VK-авторизацию (заметно при -n == -streams-per-cred).
Теперь (streamID-1)/streamsPerCache - блок 1..N делит один кэш.
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).