34 Commits

Author SHA1 Message Date
samosvalishe a8b8363b79 refactor: сложность функций под лимиты линтера 2026-09-22 20:05:10 +03:00
samosvalishe 6f81528a34 fix(turn): отмена контекста прерывает allocate 2026-09-22 20:04:26 +03:00
samosvalishe 05bbe996c1 fix: отбрасывать опоздавший повтор client id, общий backoff квоты 2026-09-22 00:43:06 +03:00
samosvalishe ee30afc922 feat(client): провайдер direct - прямо на сервер без TURN-реле
Тот же DTLS с обфускацией, сервер не меняется. По умолчанию один поток.
2026-09-22 00:07:28 +03:00
samosvalishe 7df3a3fd91 refactor(dtls): убрать дублирующий doc.go 2026-09-21 13:43:52 +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 fd9c6abf1e fix(udprelay): рецикл turn-аллокации пересоздаёт dtls-сессию
смерть аллокации теперь роняет и dtls: у новой аллокации другой relayed-адрес,
а миграция по dtls connection id под obf-профилем на сервере не работает.
логи turn-клиента уведены в logx - коды отказа vk не было видно нигде.
2026-08-18 15:29:32 +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
smediainfo 3481de79a3 feat(mobile): add host socket protector (SetProtect) for tun/VPN hosts
Checked type assertions (errcheck) and Close() error returns to satisfy golangci-lint.
2026-06-28 15:31:04 +03:00
samosvalishe e503aaee33 style: ASCII-пунктуация 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 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 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 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 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 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 971b1ac8fc chore: правка форматирования 2026-05-23 00:33:45 +03:00
samosvalishe 31e35efbf3 refactor: переименовать флаги и поля CLI/конфига
- wrap → obf: -wrap/-wrap-key/-gen-wrap-key → -obf/-obf-key/-gen-obf-key;
  ObfOpts.WrapMode/WrapKey/GenWrapKey → Mode/Key/GenKey
- vless → mode: -vless/-vless-bond → -mode tcp / -bond;
  clientProxyMode/serverProxyMode принимают string вместо bool
- -udp → -transport tcp|udp; TURNOpts.UDP → TransportUDP (везде)
- -vk-link → -link; -dns → -dns-mode; DNSModeUDP → DNSModePlain ("plain")
- KCP: убрать LoadProfileFromEnv/LoadFECFromEnv — хардкодить DefaultProfile/FEC{}
- Добавить валидацию -transport/-mode/-bond/-dns-mode в ParseClient/ParseServer
2026-05-21 19:19:40 +03:00
samosvalishe 6c3d3d341c chore(lint): расширить golangci-конфиг и устранить замечания
- Добавить nilerr, contextcheck, noctx, unconvert, unparam, gocritic, prealloc;
  убрать пресет std-error-handling и check-blank
- Заменить net.Dial/Listen/ListenPacket на context-aware варианты в tcpfwd,
  bondserver, tcpfwdserver, udprelay, udpserver
- Убрать параметр typ из writeToNextLane (всегда FrameData)
- Убрать лишний DohEndpoint из возвращаемых значений forwardRaw
- Анонимные receivers для методов без доступа к self (logx, vkauth, doh)
- Переименовать неиспользуемые параметры в _ (bondclient, bondserver, netconn,
  dtlsdial тесты)
- cmd/client: unlambda fix StreamsAlive → connectedStreams.Load
2026-05-21 16:49:59 +03:00
samosvalishe e417dac087 style: перевести комментарии на русский, убрать очевидные 2026-05-21 12:31:50 +03:00
samosvalishe 3b73d720f1 test: покрыть NopAuthenticator, GenerateSelfSignedCert, HandshakeSem
Минимальное покрытие для заготовки auth и хелперов dtlsdial:
- NopAuthenticator.Authenticate возвращает (Anonymous, nil)
- GenerateSelfSignedCert выдаёт рабочий сертификат с приватным ключом
- HandshakeSem блокирует захват при заполнении и уважает отмену ctx

Также документирует на Authenticator, что интерфейс stream-ориентирован; auth
UDP-режима получит отдельный token-based интерфейс.
2026-05-21 02:02:23 +03:00
samosvalishe 21138fef26 fix(dtlsdial): Dial использует хелпер GenerateSelfSignedCert внутри
Унификация 0b3d8a1 пропустила in-package место вызова: Dialer.Dial всё ещё звал
selfsign.GenerateSelfSigned напрямую вместо нового хелпера
GenerateSelfSignedCert. Маршрутизируем через хелпер, чтобы любая будущая правка
генерации сертификата применялась единообразно.
2026-05-21 01:33:18 +03:00
samosvalishe ef549dc2b8 fix(dtlsdial): унифицировать генерацию self-signed сертификата
Добавляет dtlsdial.GenerateSelfSignedCert() как единственное место создания
self-signed сертификата. cmd/server теперь использует его вместо прямого импорта
selfsign; Dialer.Dial уже использовал ленивый путь certOnce, который внутри
зовёт ту же функцию.
2026-05-21 01:11:08 +03:00
samosvalishe 242862397a chore: переименовать модуль в github.com/samosvalishe/btp; обновить зависимости
- путь модуля: github.com/cacggghp/vk-turn-proxy → github.com/samosvalishe/btp
- директории cmd: cmd/vk-turn-{client,server} → cmd/{client,server}
- зависимости: pion/turn v5.0.4, kcp-go v5.6.72, smux v1.5.57, x/crypto v0.51,
  klauspost/{compress,cpuid,reedsolomon}, x/{net,sys,text,tools,mod,time}
- README, workflows, GLOSSARY обновлены под новые пути
2026-05-20 12:39:26 +03:00
samosvalishe 483e45d68a refactor(kcptun): передавать Profile/FEC явно через config вместо process-wide env 2026-05-20 11:52:27 +03:00
samosvalishe 52e7cb83e6 fix: утечки, уровни logx, обход логгера
- logx: добавить префиксы [DEBUG]/[INFO]/[WARN]/[ERROR]; уровни были
  неразличимы в выводе (всё шло через голый log.Printf).
- logx: добавить хелпер OrNop для nil-проверок на стороне конструктора.
- vkauth/{client,token}.go: заменить прямой log.Printf на c.log.Infof
  (97 мест обходили унифицированный логгер после прошлого рефакторинга).
- udprelay.oneTURN: буферизовать error chan (cap 1) + select на ctx.Done в
  TURNLoop — небуферизованный send блокировался навсегда, когда TURNLoop
  выходил по ctx до чтения, утекали горутина + TURN-стрим.

- udprelay: перенести write-цикл conn2->relay в wg.Go (был голый go func, мог
  пережить wg.Wait и читать из закрытого conn).
- udprelay.TURNLoop: заменить time.Sleep(2s) на select+ctx, чтобы shutdown не
  блокировался per-stream.
- udprelay.Run / tcpfwd.Run: возвращать error вместо log.Panicf при сбое listen;
  cmd/* теперь log.Fatalf на всплывшей ошибке.
- cmd/*: log.Panicf → log.Fatalf для CLI-ошибок (без stack trace на плохой флаг).
- kcptun.NewKCPOverDTLS: закрывать серверный kcp.Listener на error-путях после
  SetDeadline/AcceptKCP (утекал при любом сбое).
- doc пакета udprelay: переписать устаревшее утверждение "avoid importing
  vkauth" (файл импортирует vkauth ради sentinel-ошибок).
- udprelay: lifecycle-сообщения ("Established/Closed DTLS connection")
  Errorf → Infof; строка "relayed-address" под DebugEnabled использует Debugf.
- tcpfwd: lifecycle-сообщения ("connected/disconnected/waiting/listening")
  Errorf → Infof, "failed to wrap listener" → Warnf.
- tcpfwd.maintainSession doc: "fixed 2-3s backoff" было неверно (3s при сбое
  setup, 2s после disconnect).
- pool.go doc: "bond client (in main)" → internal/proxy/bondclient.
- srtpmimicry.Unwrap: doc предупреждает, что AEAD открывает in-place внутри
  wire, поэтому вызыватели должны считать wire потреблённым.
- комментарии-алиасы GetCredsFunc udprelay/tcpfwd: убрать фикцию "cmd/main
  wiring stability" (всё в internal/).

Build чисто, go vet чисто, все тесты проходят.
2026-05-19 22:24:21 +03:00
samosvalishe 51bda46446 refactor: симметрия, вынос серверных хендлеров
- internal/proxy/udpserver: handleUDPConnection вынесен из server-main
- internal/proxy/tcpfwdserver: handleVLESSConnection + prefixedConn + pipeConn
  вынесены из server-main
- cmd/vk-turn-server/main.go: 396 → 134 строк, глобалы убраны
- internal/proxy/udprelay: добавлен entrypoint Run() симметрично tcpfwd.Run;
  Pool → packetPool (unexported); listener+fan-in вынесены из client-main
- cmd/vk-turn-client/main.go: 262 → 130 строк, package-глобалы убраны
- dtlsdial.Dialer: кеш self-signed сертификата на Dialer (sync.Once) вместо
  регенерации на каждый handshake
- captcha.solveCaptchaPoW: переиспользование буфера (вместо 10M конкатенаций
  строк), ctx-проверка каждые 1024 итерации (было 4096)

Тесты + lint проходят.
2026-05-19 21:53:13 +03:00
samosvalishe 7e3369f478 docs: заметка DTLS-как-обфускация + breaking changes в README
- internal/transport/dtlsdial/doc.go: объяснить, что DTLS используется как слой
  обфускации под content-фильтр VK TURN, а не как граница безопасности;
  задокументировать, почему -no-dtls был убран и почему решения вроде
  self-signed сертификатов / send-only CID намеренны.
- README: добавить врезку breaking-changes под "Защита от блокировок"; убрать
  строки -no-dtls и server -vless-bond из таблиц флагов; отметить, что bond
  автоопределяется по magic-префиксу на сервере.

Завершает рефакторинг. Все этапы зелёные: go build / go vet / go test / gofmt.
CLI и wire-форматы бит-в-бит кроме двух удалений (-no-dtls на клиенте,
-vless-bond на сервере).
2026-05-19 21:18:58 +03:00
samosvalishe 1fb869b3e1 refactor(layout): переименовать пакеты (split wire/transport/proxy)
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 зелёные.
2026-05-19 20:42:46 +03:00