84 Commits

Author SHA1 Message Date
samosvalishe 6f84a18b43 feat(tcp): вернуть поддержку bond 2026-09-22 22:33:56 +03:00
samosvalishe a8b8363b79 refactor: сложность функций под лимиты линтера 2026-09-22 20:05:10 +03:00
samosvalishe c13490ff55 fix(udp): ошибка obf до аллокации, без петли allocate 2026-09-22 20:05:02 +03:00
samosvalishe 5b175bf4be fix(udp): датаграммы до 2048 байт на всём пути 2026-09-22 20:04:44 +03:00
samosvalishe 5b6ac18332 perf(tcp): смерть smux-сессии без поллинга 2026-09-22 20:04:05 +03:00
samosvalishe f4e8e0cfe0 fix(udp): завершать релей при отказе чтения локального сокета 2026-09-22 20:03:54 +03:00
samosvalishe 05bbe996c1 fix: отбрасывать опоздавший повтор client id, общий backoff квоты 2026-09-22 00:43:06 +03:00
samosvalishe d3e4cfc1db feat(auth)!: подтверждение Client ID с повтором по таймеру 2026-09-22 00:07:29 +03:00
samosvalishe caa8fea5bf fix(udp): логировать причину обрыва DTLS-сессии перед паузой 2026-09-22 00:07:29 +03:00
samosvalishe 5508cd65a7 fix(udp): ограничить очередь между сокетом и DTLS 2026-09-22 00:07:29 +03:00
samosvalishe ee30afc922 feat(client): провайдер direct - прямо на сервер без TURN-реле
Тот же DTLS с обфускацией, сервер не меняется. По умолчанию один поток.
2026-09-22 00:07:28 +03:00
samosvalishe c116e427f7 test: убрать гонки в проверках учёта трафика 2026-09-21 13:43:21 +03:00
samosvalishe a0c4656025 perf(udp): убрать сисколлы и аллокации с горячего пути релея 2026-09-21 13:43:20 +03:00
samosvalishe fd5c4f92a5 fix(server): не ронять процесс паникой в обработчике соединения 2026-09-21 13:42:24 +03:00
samosvalishe 6570cd9dd7 fix(relay): восстановление потоков при отказах turn и занятой квоте 2026-09-12 17:29:09 +03:00
samosvalishe f7129099f7 feat(proxy): tcp-режим для xray/sing-box поверх turn 2026-08-25 15:44:16 +03:00
samosvalishe e63279db18 perf(udprelay): общий шлюз на allocate вместо per-stream джиттера 2026-08-25 15:44:16 +03:00
samosvalishe 03eb41e2fb fix(udprelay): фатальная ошибка не ждёт барьер прогрева 2026-08-25 15:44:16 +03:00
samosvalishe 748d5a07ce fix(core): паника горутины больше не убивает процесс приложения 2026-08-25 15:44:16 +03:00
samosvalishe 48631616f1 fix(udprelay): не зависать на фатальной ошибке провайдера
Дедлайн, будивший runListener, ставился по родительскому ctx, а фатальная ошибка отменяет только runCtx: на молчащем LocalPipe wg.Wait() не возвращался никогда.
2026-08-25 15:44:15 +03:00
samosvalishe 7fc7fe2e79 fix(vkauth): сбрасывать реквизиты при неподтверждённом deallocate 2026-08-25 15:44:15 +03:00
samosvalishe c2a9f0f1d7 fix(logs): убрать пострим-шум из лога без debug
TURN urls, персона, попытки кредов и DTLS connect/close - на debug: на 8 стримах это десятки строк на старте.
2026-08-25 15:44:15 +03:00
samosvalishe fd9c6abf1e fix(udprelay): рецикл turn-аллокации пересоздаёт dtls-сессию
смерть аллокации теперь роняет и dtls: у новой аллокации другой relayed-адрес,
а миграция по dtls connection id под obf-профилем на сервере не работает.
логи turn-клиента уведены в logx - коды отказа vk не было видно нигде.
2026-08-18 15:29:32 +03:00
samosvalishe 49eecb3478 fix: устранение предупреждений линтера 2026-08-18 00:21:35 +03:00
samosvalishe 65bc8a8993 fix: устранение предупреждений линтера 2026-08-18 00:15:52 +03:00
samosvalishe 0bef2e8ab5 fix: soft reconnect on network handover without tunnel drop 2026-08-17 23:29:19 +03:00
samosvalishe 3cf78316df perf: меньше фоновых таймеров при поднятом туннеле и опрос метрик только при видимом окне 2026-08-17 17:14:10 +03:00
samosvalishe a033cfb9a2 fix(udprelay): рецикл аллокации на простое туннеля 2026-08-17 17:13:44 +03:00
samosvalishe 74241de764 break!: выпил tcp-режим туннеля
убраны флаги -mode и -bond: остался только udp-релей для wireguard.
удалены tcpfwd, tcpfwdserver, bondclient, bondserver, bondframe, kcptun,
wire/relay; proxy/common переехал в udprelay/dial.

BREAKING CHANGE: флаги -mode и -bond удалены; конфиги и ссылки freeturn://
с tcp-режимом больше не принимаются.
2026-08-17 00:27:23 +03:00
samosvalishe 648c55415b feat: comment cleanup 2026-08-16 23:13:01 +03:00
samosvalishe 681dde8a6d feat(mobile): переживание сна и рестарта на Android 2026-08-16 21:19:14 +03:00
samosvalishe a7798cd851 feat(proxy): встроенное управление маршрутами к TURN-серверам
- Добавлен пакет `internal/routemgr` для автоматического создания
  host-маршрутов (/32) через шлюз ОС (Windows, Linux, macOS).
- В `config.Client` и CLI добавлен флаг `-routes` (по умолчанию отключен).
- Интегрирован callback `OnTURNServer` в `udprelay` и `tcpfwd`
  для динамического добавления маршрутов при старте стримов.
- Для Android (и переименованных JNI-бинарей Linux) добавлено
  graceful-отключение менеджера маршрутов.
- Обновлена документация (`quickstart.md`): добавлены примеры с
  использованием `-routes` и `-client-id`.
2026-08-01 15:07:37 +03:00
samosvalishe 1f86fda104 refactor: перенос логики сессии в internal/session и обновление mobile-фасада 2026-08-01 03:05:14 +03:00
samosvalishe 12161aed4a feat(vk): улучшение браузерных отпечатков для captcha
- Добавлена поддержка Safari в -browser.
    Обновлена валидация флага, документация и выбор TLS/HTTP2-профиля для
    chrome, firefox и safari.

  - Улучшено переиспользование сохранённого браузерного профиля.
    Добавлен VK_PROFILE_PATH, сохраняется Accept-Language, определяется семейство
    браузера и mobile-профиль, а TLS-клиент пересобирается под захваченный UA.

  - Обновлена форма запросов VK Smart Captcha.
    Учитываются domain из redirect_uri, id.vk.ru origin/referer, settings_key для
    slider captcha, сохранённый browser_fp и device JSON.

  - Улучшено автоматическое решение captcha.
    Обновлён формат PoW-ответа, добавлена mobile accelerometer телеметрия,
    NetworkInformation отправляется только для Chromium-профилей, а slider solver
    получил обратный скоринг и более естественные cursor traces.

  - Убрано шумное throughput debug-логирование в relay-путях.
    Удалён Stats.LogEvery и его вызовы в UDP/TCP relay, при этом агрегированная
    TrafficStats-статистика сохранена.

  - Обновлены тесты и инфраструктура сборки.
    Добавлены проверки Safari, browser profile storage, captcha telemetry и
    saved-profile fallback; tls-client обновлён до v1.15.1; Android bind в
    Taskfile разделён для Windows и Unix-платформ
2026-06-30 19:16:35 +03:00
samosvalishe 575f278a9a feat(mobile): переименование ios -> mobile, универсальный движок для iOS/Android 2026-06-25 02:44:31 +03:00
Serj 1c58325862 feat: мультиплексирование звонков (#21) 2026-06-19 14:00:29 +03:00
samosvalishe e503aaee33 style: ASCII-пунктуация 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 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 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 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 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 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 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 12c1ad6283 feat: абстракция провайдера (vk + static)
Вытаскивает источник 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
обновлены.
2026-05-23 14:11:05 +03:00
samosvalishe dd8233208c fix(lint): устранить замечания golangci-lint + переход на dockers_v2
Проход lint (52 → 0):
- vkauth/token: переименовать затенённый err (govet shadow x3)
- udprelay/loop: явный _ = conn.Close() (errcheck x2)
- captcha/manual: ReadHeaderTimeout + html.EscapeString (G112, G705)
- proxy/tcpfwd: хелпер nonNegUint64 для байтовых счётчиков io.Copy (G115)
- proxy/bondclient, wire/bondframe: bounds-проверки на len->uint16/uint32
- wire/srtpmimicry: задокументирована усечка RTP seq mod 2^16
- dnsdial/doh: bounds-проверка + binary.BigEndian.PutUint16
- captcha/slider: clamp luma до 255 перед конверсией uint8
- vkauth/types: обоснованный nolint для публичных учёток VK SDK

Новый пакет internal/randx — Intn/IntN/Float64 на crypto/rand, drop-in замена
math/rand. Мигрированы все места antifingerprint-jitter (~22) в captcha, slider,
namegen, vkauth, udprelay.

GoReleaser:
- bump GORELEASER_VERSION v2.5.0 → v2.15.4 в Taskfile и обоих CI-workflow;
  текущий синтаксис .goreleaser.yaml (archives.ids, format_overrides.formats)
  требует v2.8+
- миграция dockers + docker_manifests → dockers_v2 (единый блок, multi-platform
  buildx); Dockerfile.goreleaser использует конвенцию ARG TARGETPLATFORM
2026-05-23 01:37:42 +03:00