Commit Graph

108 Commits

Author SHA1 Message Date
samosvalishe 575f278a9a feat(mobile): переименование ios -> mobile, универсальный движок для iOS/Android 2026-06-25 02:44:31 +03:00
Anton fb998547eb Merge pull request #25 from tremendous-stimulus/master
gomobile-биндинг для приложения iOS
2026-06-24 15:25:14 +03:00
samosvalishe 384c350e7d fix: заменить устаревший token_type=messages на анонимные скоупы в VK авторизации 2026-06-24 11:35:59 +03:00
Tremendous Stimulus e2d59ef7e5 feat(ios): ручной fallback решения VK captcha через презентер приложения
Когда авто-решатель captcha не справился, прокидываем в vk-провайдер
ManualSolverFunc, который переиспользует SolveViaProxy и сигналит UI через
gomobile-интерфейс CaptchaPresenter (Show/Hide). Без презентера поведение
прежнее. Файлы библиотеки не затронуты - мостик в новом файле vk/iosmanual.go.
2026-06-23 23:21:08 +03:00
Tremendous Stimulus 72c65c51ed Merge remote-tracking branch 'upstream/master' 2026-06-23 22:48:49 +03:00
samosvalishe b0c3e65c40 fix: bump captcha 2026-06-22 18:25:43 +03:00
samosvalishe d73f42603a fix: captcha 2026-06-22 18:01:16 +03:00
Tremendous Stimulus d255bc5f82 feat(ios): добавить iOS framework 2026-06-19 23:56:49 +03:00
samosvalishe b76e21266d refactor: единая константа версии VK API для calls.* 2026-06-19 15:55:06 +03:00
samosvalishe dd55d96846 chore: getCallPreview v5.282 2026-06-19 15:43:38 +03:00
samosvalishe ebb1f6bf07 fix: оставлены только VK app_id с доступом к calls.getAnonymousToken 2026-06-19 15:43:38 +03:00
samosvalishe e63c93ec41 test: покрытие multi.Provider и shape
multi: round-robin биекция, маршрутизация Handle/Reset, max backoff, panic.
shape: passthrough при interval=0, форвардинг WriteTo, обёртка listener.
2026-06-19 15:11:17 +03:00
samosvalishe e50febc834 fix: -obf-timing допустим только с -mode udp и включённой обфускацией
без RTP-профиля паковать нечего, а в tcp-режиме pacing ломает RTT/конгешн
KCP. Раньше флаг в tcp молча игнорировался. Валидация симметрична на
клиенте и сервере.
2026-06-19 15:11:17 +03:00
samosvalishe bafdcdd027 fix: устранены блокеры линтера в obf/multi
errcheck nolint на bufPool.Get в rtpopus3/listen.go; multi.MultiProvider
переименован в multi.Provider (revive stutter), дедуп vk.New в buildProvider.
2026-06-19 15:11:17 +03:00
samosvalishe 9564f3475f fix: потокобезопасность send-состояния obf-кодеков rtpopus3 и shape 2026-06-19 15:11:15 +03:00
Serj 1c58325862 feat: мультиплексирование звонков (#21) 2026-06-19 14:00:29 +03:00
samosvalishe 7d1ae10a47 fix(dnsdial): вернуть простую UDP-пробу auto до auto-пробы реального хоста 2026-06-17 22:49:00 +03:00
samosvalishe 1ec4fd463d fix(dnsdial): не вешать старт auto на DoH-пробу 2026-06-17 22:03:03 +03:00
samosvalishe 5cbc0ef456 chore: captcha bump 2026-06-17 10:04:18 +03:00
samosvalishe e503aaee33 style: ASCII-пунктуация 2026-06-17 10:03:41 +03:00
samosvalishe 69a68bbc31 feat(vkauth): флаг -browser и профиль Firefox
Флаг -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).
2026-06-17 10:03:41 +03:00
samosvalishe cc405100ab feat(netconn): анти-DPI мульти-сплит ClientHello по SNI
MultiSplitWriteConn парсит TLS ClientHello, находит SNI host_name и режет первый сегмент внутри него на ~трети с джиттером - registrable-домен гарантированно пересекает границу TCP-сегмента, DPI без реассемблинга не собирает hostname. Фоллбэк на одиночный рез offset 6, если SNI не найден.

turndial: STUN-split offset рандомизирован в [5,7] (рез внутри magic cookie), убран статический фингерпринт фикс-offset.
2026-06-17 10:03:41 +03:00
samosvalishe f8e840ccdf feat(wire): профиль rtpopus2 и интерфейс Codec
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.
2026-06-17 10:03:41 +03:00
samosvalishe 1ec2b2610a feat(dnsdial): auto-проба реального хоста с DoH recovery
auto-режим пробил UDP/53 нейтральным dns.google и залипал на UDP
навсегда. При выборочной фильтрации (dns.google резолвится, целевой
хост - нет) это вело к таймаутам резолва. Проба теперь валидирует
резолв реального хоста; при провале UDP уходит на DoH. Добавлен
рантайм-recovery в обе стороны: серия неудач UDP -> DoH, периодическая
перепроба DoH -> UDP.
2026-06-17 10:03:40 +03:00
samosvalishe 745539dc11 fix(vkauth): группировка кэша по 1-based streamID
CacheID делил streamID/streamsPerCache, но streamID 1-based: поток
с номером, кратным streamsPerCache, переваливал в соседний bucket
и тянул лишнюю VK-авторизацию (заметно при -n == -streams-per-cred).
Теперь (streamID-1)/streamsPerCache - блок 1..N делит один кэш.
2026-06-17 10:03:40 +03:00
samosvalishe 4084cce091 fix: миграция на ru домен 2026-06-17 10:03:40 +03:00
samosvalishe 402606e4f7 feat(uri): переход на base64url(json), расширенные параметры
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).
2026-06-11 23:49:31 +03:00
samosvalishe 40796b4844 fix(dnsdial): убрать динамический фоллбэк на DoH
Откат: динамическое переключение ломало one-shot автовыбор UDP/53. Возврат к sticky-пробе при старте.
2026-06-11 21:04:58 +03:00
samosvalishe 2efe415344 chore: captcha version bump 2026-06-11 19:27:36 +03:00
samosvalishe f24c5416de fix(dnsdial): динамический фоллбэк на DoH при отказе UDP/53 после пробы 2026-06-11 19:27:30 +03:00
samosvalishe 2534bbe96a fix(turndial): детект блэкхола по ChannelBind, не CreatePermission refresh
VK реджектит standalone CreatePermission refresh с 400 независимо от здоровья стрима, поэтому permWatch ложно рециклил здоровые аллокации каждые ~60s. Permission держится живым через ChannelBind refresh (RFC 8656 §11), стандартный для VK путь, потому отдельный CreatePermission refresh глушим (PermissionRefreshInterval 24h). Реальный блэкхол ловим по провалу ChannelBind refresh (data-path), сброс на успешном байнде.
2026-06-08 08:34:56 +03:00
samosvalishe 2845874f86 chore: captcha version bump 2026-06-08 00:09:17 +03:00
samosvalishe 40000fde5d feat(turn): фоллбэк по нескольким relay-адресам при allocate
VK отдаёт несколько relay-адресов, но стрим использовал ровно один
(streamID%n). Если этот IP душит DPI/RST — allocate падает без альтернативы.

Credentials несёт список адресов (primary-first по streamID), DialTURN
пробует кандидатов по очереди и берёт первый успешный allocate. Балансировка
relay-IP по стримам сохранена, остальные адреса — фоллбэк. HostOverride (-turn)
схлопывает список до одного адреса.
2026-06-08 00:09:17 +03:00
samosvalishe 106a48533c fix(udprelay): детект блэкхола permission по логу pion вместо трафик-эвристики
Трафик-watchdog (tx растёт, rx заморожен) ложно рециклил здоровые
sender-only стримы: обратный путь WireGuard привязан к endpoint, а не к
стриму, поэтому rx==0 на отправляющем стриме — норма, не блэкхол.

permWatchFactory считает проваленные циклы refresh permission в логе pion
(scope turnc) и закрывает Stream.PermDead после порога. RefreshInterval
урезан 120s→30s. oneTURN рециклит allocation по PermDead.
2026-06-08 00:09:17 +03:00
samosvalishe 1ff8dd9cba fix(captcha): обновить captchaScriptVersion до 1.1.1348 2026-06-04 12:33:31 +03:00
samosvalishe a337bb0a63 fix(udprelay): рециклить стрим при блэкхоле TURN permission
При провале CreatePermission refresh pion роняет permission без ошибки,
relay молча дропает пакеты, стрим висит и ест свою долю WG-трафика.
Watchdog: tx растёт, rx заморожен 20с, отменяем turnctx и делаем свежий
allocate через TURNLoop.
2026-06-04 12:31:43 +03:00
samosvalishe 56da9fecdc fix(vkauth): фрагментировать ClientHello на control plane
ТСПУ читает SNI из ClientHello и инжектит delayed RST в TLS до VK
(login.vk.ru и др.). Дробим первый Write через SplitFirstWriteConn,
SNI уезжает во второй сегмент. Вписано в tls-client через
WithProxyDialerFactory без proxyUrl: прямой транспорт, резолвер сохранён.
2026-06-04 12:31:38 +03:00
samosvalishe 5fc2a09fbb fix(captcha): обновить captchaScriptVersion до 1.1.1346 2026-06-01 18:14:54 +03:00
samosvalishe a0ea846f25 fix(turndial): не переопределять PermissionRefreshInterval (дефолт pion) 2026-06-01 18:14:54 +03:00
samosvalishe 43180f0362 fix(dtlsdial): уникальный self-signed cert на каждый handshake
Cert генерируется заново на каждый Dial вместо переиспользования через
sync.Once: каждая TURN-сессия и реконнект получают свой fingerprint,
чтобы N параллельных стримов с одного IP не коррелировались как ботный
трафик.
2026-06-01 18:14:41 +03:00
samosvalishe a97ad6ca33 fix(udprelay): барьер старта стримов для прогрева кэша creds
Стрим 1 поднимается первым и сигналит okchan; стримы 2..N ждут сигнал
(или ctx/safety-timeout 20s) и переиспользуют тёплый кэш credentials
вместо N одновременных запросов к VK — снимает thundering herd на
старте (частая причина rate-limit/captcha).
2026-06-01 18:14:00 +03:00
samosvalishe 89c390cef5 perf(udprelay): in-place wrap/unwrap obf без копий payload
WrapInPlace/UnwrapInPlace работают прямо в wire-буфере: ingress читает
payload сразу за RTP-заголовком, egress отдаёт subslice расшифровки.
Убирает 2 memcpy (~1400B) и 2 буфера на пакет в obf-режиме, плюс
atomic-запись адреса пайпа теперь один раз. WrapInto/Unwrap делегируют,
wire-формат не изменён.
2026-06-01 18:13:50 +03:00
samosvalishe 98e1d7cc8e fix(turndial): подавить периодический CreatePermission refresh
VK TURN реджектит standalone CreatePermission refresh с 400 Bad Request
каждые 120s, засоряя логи. Данные идут через ChannelData; channel-bind
refresh (RFC 8656 §9) держит permission живым, потому отдельный refresh
избыточен. Выставляем PermissionRefreshInterval в 24h.
2026-05-26 00:20:30 +03:00
samosvalishe f1b047e9e5 feat: Client ID шлётся всегда, симметричный wire авторизации
Клиент всегда отправляет 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 теперь
всегда в первой записи туннеля — старые клиенты/серверы несовместимы.
2026-05-25 00:33:26 +03:00
samosvalishe e061345089 feat: авторизация по client-id, freeturn:// URI и подписки
- 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 по всем исходникам
2026-05-24 01:14:38 +03:00
samosvalishe 41d877dc64 chore: free turn proxy 2026-05-24 00:01:57 +03:00
samosvalishe bf59e5c8b4 refactor(config): единообразные имена переменных флагов, ужать help-текст
Переименовать переменные-указатели флагов под имена флагов 1:1 (vklink→link,
host→turn, obfProfileRaw→obfProfile, убрать суффиксы *Flag/*Raw/*Hex). Урезать
многословные описания флагов; убрать аннотации (default), раз пакет flag
печатает их сам.
2026-05-23 20:52:30 +03:00
samosvalishe 4bedd00662 refactor(wire): переименовать srtpmimicry → rtpopus, заменить bool -obf на -obf-profile
Готовим зонтик `internal/wire/` под будущие профили мимикрии (rtph264, vp8
и т.д.). Сейчас интерфейс/registry не вводим — родится при появлении второго
профиля; пока только перепаковываем единственный профиль в собственный namespace.

Пакет:
- `internal/wire/srtpmimicry` → `internal/wire/rtpopus`
- error-префикс `"wrap: ..."` → `"rtpopus: ..."`
- wire-формат не тронут (заморожен — совместимость с задеплоенными пирами)

CLI (breaking):
- `-obf` (bool) удалён
- добавлен `-obf-profile none|rtpopus` (default `none`)
- `ObfOpts.Mode bool` → `Profile ObfProfile` + `Enabled()` helper
- консты `ObfProfileNone`/`ObfProfileRTPOpus`
- validation invalid-value error для `-obf-profile`

Docker (breaking):
- env `OBF_MODE=true` → `OBF_PROFILE=rtpopus`

Callsites:
- `common.NewClientWrap` → `NewClientObf`
- vars `wc`/`relayWC` → `obfConn`, `wrapListener` → `obfListener`
- log `obf=%t` → `obf-profile=%s`

Доки + тесты подтянуты под новые имена.
2026-05-23 15:24:00 +03:00
samosvalishe cf47f374b3 refactor(provider): убрать static-провайдер, оставить абстракцию
Сейчас нужен только VK-провайдер. internal/provider/static и связанные флаги
-static-user/-static-pass/-static-addr удалены, валидация и тесты обновлены.
Интерфейс provider.Provider остаётся — слот для будущих реализаций сохранён в
нейтральных формулировках doc-комментариев.
2026-05-23 14:54:46 +03:00
samosvalishe 2b85d937ea refactor(provider/vk): перенести vkauth/captcha/browserprofile/namegen под provider/vk/internal
Переносит VK-specific пакеты под internal/provider/vk/internal/* — теперь
недоступны для импорта извне provider/vk (Go internal/ rule). ish остался в
internal/client/ish — не VK-specific.

vk.SetCaptchaLoggers удалён: логгеры captcha/manual подключаются внутри vk.New,
debug-флаг передаётся через новое поле Config.Debug. cmd/client/main.go больше
не импортирует captcha-пакеты.

Документация обновлена.
2026-05-23 14:36:58 +03:00