diff --git a/docs/about.md b/docs/about.md new file mode 100644 index 0000000..0c74b65 --- /dev/null +++ b/docs/about.md @@ -0,0 +1,877 @@ +# olcRTC — полная документация + +> **olcRTC** (OpenLibreCommunity RTC) — инструмент обхода интернет-блокировок через паразитирование на легальных WebRTC-сервисах видеозвонков, уже находящихся в российских белых списках. +> +> Проект: [github.com/openlibrecommunity/olcrtc](https://github.com/openlibrecommunity/olcrtc) +> Лицензия: WTFPL +> Статус: **Beta** + +--- + +## Содержание + +1. [Почему olcRTC существует](#1-почему-olcrtc-существует) +2. [Идея и история создания](#2-идея-и-история-создания) +3. [Как это работает](#3-как-это-работает) +4. [Архитектура](#4-архитектура) +5. [Структура репозитория](#5-структура-репозитория) +6. [Carriers — провайдеры](#6-carriers--провайдеры) +7. [Transports — транспорты](#7-transports--транспорты) +8. [Шифрование](#8-шифрование) +9. [Мультиплексирование](#9-мультиплексирование) +10. [SOCKS5 прокси](#10-socks5-прокси) +11. [Mobile / Android](#11-mobile--android) +12. [Python PoC скрипты](#12-python-poc-скрипты) +13. [Сборка и деплой](#13-сборка-и-деплой) +14. [CLI — все флаги](#14-cli--все-флаги) +15. [URI-формат и подписки](#15-uri-формат-и-подписки) +16. [Матрица совместимости](#16-матрица-совместимости) +17. [CI/CD](#17-cicd) +18. [Что планируется сделать — Issues](#18-что-планируется-сделать--issues) +19. [Контрибуторы](#19-контрибуторы) +20. [Частые ошибки](#20-частые-ошибки) + +--- + +## 1. Почему olcRTC существует + +В России работают ТСПУ (технические средства противодействия угрозам). В мобильных сетях провайдеры перешли в режим **белых списков**: ТСПУ дропает все пакеты, кроме явно разрешённых IP-адресов и SNI. + +Фильтрация двухуровневая: +- **L3** — по IP-адресу назначения. Не разрешён → пакет физически не уходит дальше второго хопа. +- **L7** — по SNI в TLS ClientHello. Есть в чёрном списке → RST. + +Классические обходы через VPS ломаются когда VPS не попадает в белый список. Yandex Cloud, VK Cloud, Timeweb в списке — но провайдеры активно банят инстансы используемые как прокси. + +**Решение olcRTC**: не пытаться попасть в белый список — использовать сервисы, которые там уже есть навсегда. Телемост, SaluteJazz и WB Stream — сервисы видеозвонков крупных российских компаний. Пока они живы, olcRTC работает. Чтобы их заблокировать — нужно заблокировать сам сервис. + +Трафик идёт через WebRTC SFU этих сервисов: + +``` +Клиент (cnc) → SFU Яндекса/Сбера/WB → Сервер (srv, ваш VPS) +``` + +Для ТСПУ это выглядит как обычный видеозвонок. + +--- + +## 2. Идея и история создания + +### Хронология + +**2025-04-03** — первый коммит `init repo`. Идея. + +**2025-04-06** — `remove text`. Единственная правка за целый год. + + +**2026-04-04** — `Initialize project with base configuration and assets`. Реальный перезапуск с нуля. + +**2026-04-05** — За один день появляются Python PoC: +- `telemost_poc_datachannel.py` — первое рабочее соединение через Telemost DataChannel +- `vcsend.py` — передача данных QR-кодами через видеопоток +- `flood.py` — стресс-тест соединений +- `limits.py` — обнаружен лимит Telemost DataChannel: 8KB на сообщение, всё что выше молча дропается +- `info.py` — исследование API Telemost + +**2026-04-06** — QR-код двусторонняя передача (`invicible`), первые замеры: **44 Mbps** через DataChannel. + +**2026-04-07** — первый Go бинарник: WebRTC туннель с ChaCha20-Poly1305 шифрованием, SOCKS5 прокси, деплой через Podman. Провайдер: только Telemost. + +**2026-04-08..09** — активная Go разработка: клиент-серверная архитектура, кастомный мультиплексор с sequence numbering, имена участников из файла, graceful shutdown, DNS поддержка, Android мост. + +**2026-04-10..11** — простой UI, Docker образ сервера, SaluteJazz PoC от community-контрибутора `0xcodepunk`. + +**2026-04-12..14** — большой рефакторинг: golangci-lint, Jazz провайдер с protobuf-style пакетами, автогенерация Room ID для Jazz, Windows скрипты от `DeNcHiK3713`. + +**2026-04-19..20** — архитектурный рефакторинг: выделение слоёв `carrier` / `transport` / `link`, WB Stream провайдер через LiveKit SDK, видеоканальный PoC на Python. + +**2026-04-21..22** — `videochannel` транспорт (данные кодируются в QR-коды внутри VP8 видеопотока через ffmpeg), `vp8channel` транспорт (данные в VP8 payload), NVENC поддержка. + +**2026-04-25..30** — tile кодек для videochannel с Reed-Solomon коррекцией ошибок, `vp8channel` поверх KCP для надёжной доставки, замена самописного мультиплексора на smux. + +**2026-05-01..06** — `seichannel` (данные в H264 SEI NAL-юнитах), E2E тесты на реальных провайдерах, URI-формат и формат подписок, `-client-id` для привязки клиента к серверу, SOCKS5 аутентификация. + +**2026-05-07..10** — финальная полировка: исправлен throughput bug в vp8channel (ограничение было в 32 раза ниже реального), документация, SEI конфигурация, `-socks-user`/`-socks-pass`. + +### Статья на Хабре + +Проект описан в двух статьях на Хабре: +- *«Это — всё что вам надо знать о белых списках»* — технический анализ как работает фильтрация, 63k IP в белом списке из 46 млн российских, методы обхода +- *«BAREBONE2022: чтобы заблокировать этот протокол придётся запретить MAX и Yandex»* — описание идеи olcRTC, первые замеры скорости + +--- + +## 3. Как это работает + +``` +Браузер/приложение + │ (обычные TCP соединения) + ▼ + SOCKS5 :8808 ← cnc (клиент), работает на вашей машине + │ + │ ChaCha20-Poly1305 + │ smux поверх muxconn + │ + ▼ + Transport (datachannel / vp8channel / seichannel / videochannel) + │ + ▼ + Carrier (jazz / wbstream / telemost) + │ WebRTC DataChannel или VideoTrack + ▼ + SFU Яндекса / Сбера / WB ← сервер в белом списке у всех провайдеров + │ + ▼ + Transport (datachannel / vp8channel / seichannel / videochannel) + │ + ▼ + srv (сервер), работает на вашем VPS + │ (обычный TCP/DNS) + ▼ + Интернет +``` + +Клиент (`cnc`) поднимает локальный SOCKS5. Любой браузер или приложение подключается к нему как к обычному прокси. Трафик мультиплексируется через smux, шифруется ChaCha20-Poly1305 и передаётся через выбранный транспорт поверх WebRTC SFU. + +Сервер (`srv`) стоит на вашем VPS. Он подключается к той же комнате видеозвонка, получает зашифрованный поток и от своего имени делает TCP соединения к нужным адресам в интернете. + +ТСПУ видит трафик к IP Яндекса/Сбера/WB с корректным TLS и SNI — ничем не отличается от обычного видеозвонка. + +--- + +## 4. Архитектура + +Проект разбит на чёткие слои. Каждый слой можно заменить независимо. + +``` +cmd/olcrtc/ CLI entrypoint, парсинг флагов + │ +internal/app/session/ конфигурация, валидация, роутинг в server/client + │ │ +internal/server/ internal/client/ бизнес-логика: SOCKS5, smux + │ +internal/muxconn/ io.ReadWriteCloser поверх link.Link + AEAD + │ +internal/link/direct/ pass-through, пробрасывает в transport + │ +internal/transport/ интерфейс Transport + реестр + ├── datachannel/ WebRTC DataChannel как byte stream + ├── vp8channel/ VP8 видео + KCP поверх него + ├── seichannel/ H264 SEI NAL-юниты + └── videochannel/ QR-коды / тайлы в VP8 видеофрейме через ffmpeg + │ +internal/carrier/ интерфейс Carrier + реестр + ├── builtin/ регистрация провайдеров + └── bytestream.go ByteStream, VideoTrack capability + │ +internal/provider/ WebRTC реализации + ├── jazz/ SaluteJazz (salutejazz.ru) + ├── telemost/ Yandex Telemost (telemost.yandex.ru) + └── wbstream/ WB Stream (stream.wb.ru) через LiveKit SDK + │ +internal/crypto/ ChaCha20-Poly1305 AEAD +internal/names/ генератор имён участников +internal/protect/ Android VPN protect() интеграция +internal/logger/ структурированное логирование +internal/link/ интерфейс Link + реестр +internal/e2e/ E2E тесты на реальных провайдерах +``` + +--- + +## 5. Структура репозитория + +### Корень + +| Файл/папка | Что это | +|---|---| +| `readme.md` | Краткое описание, команды сборки, ссылки | +| `about.md` | Этот документ | +| `SECURITY.md` | Политика безопасности | +| `magefile.go` | Система сборки на Mage (аналог Makefile для Go). Таргеты: `build`, `cross`, `mobile`, `docker`, `podman`, `lint`, `test`, `e2e` | +| `Dockerfile` | Многоэтапный образ: Alpine build → Alpine runtime с непривилегированным пользователем `olcrtc` | +| `docker-compose.server.yml` | Compose для серверного режима | +| `.gitmodules` | Субмодуль `internal/transport/videochannel/gr` — кастомные кодеки QR и tile | +| `.golangci.yml` | Конфиг линтера golangci-lint | +| `.github/workflows/ci.yml` | CI: тесты, покрытие, E2E, lint, сборка CLI для всех платформ, сборка Android AAR | + +### `cmd/olcrtc/` + +| Файл | Что делает | +|---|---| +| `main.go` | Точка входа. Парсит флаги (`flag.FlagSet`), настраивает логирование, подавляет шум LiveKit/pion в не-debug режиме, запускает `session.Run` или `session.Gen`. Graceful shutdown по SIGTERM/SIGINT с 5-секундным таймаутом | +| `main_test.go` | Юнит-тесты CLI: валидация флагов, режимы, edge cases | + +### `internal/app/session/` + +| Файл | Что делает | +|---|---| +| `session.go` | Главная точка конфигурации. `RegisterDefaults()` регистрирует все carriers, links, transports. `Validate()` проверяет все флаги. `Run()` роутит в `server.Run` или `client.Run`. `Gen()` генерирует Room ID для jazz/wbstream с ретраями. `buildRoomURL()` строит URL для каждого carrier | +| `session_test.go` | Тесты валидации конфига | + +### `internal/server/` + +| Файл | Что делает | +|---|---| +| `server.go` | Серверная сторона туннеля. Подключается к комнате как второй участник звонка. Создаёт `muxconn` → `smux.Session`. Для каждого входящего smux-стрима читает JSON `ConnectRequest` от клиента с адресом назначения, устанавливает TCP соединение и гоняет байты туда-обратно. Поддерживает SOCKS5 прокси для исходящего трафика. Умеет переподключаться при разрыве | +| `server_test.go` | Тесты серверной логики | + +### `internal/client/` + +| Файл | Что делает | +|---|---| +| `client.go` | Клиентская сторона. Поднимает SOCKS5-сервер. Для каждого входящего подключения: SOCKS5 handshake (поддержка RFC 1929 username/password auth), создаёт smux-стрим, шлёт JSON `ConnectRequest` с адресом, гоняет байты. Переподключается при разрыве WebRTC сессии | +| `client_test.go` | Тесты клиентской логики | + +### `internal/muxconn/` + +| Файл | Что делает | +|---|---| +| `conn.go` | Адаптер `link.Link` → `io.ReadWriteCloser`. Каждый `Write` шифрует блок ChaCha20-Poly1305 и отдаёт в link как одно сообщение. Входящие сообщения дешифруются и буферизуются; `Read` дренирует буфер в произвольных кусках (smux не знает о границах сообщений). Синхронизация через `sync.Cond` | +| `conn_test.go` | Тесты | + +### `internal/link/` + +| Файл | Что делает | +|---|---| +| `link.go` | Интерфейс `Link` (`Send`, `SetOnData`, `Connect`, `Close` и т.д.) + реестр | +| `link_test.go` | Тесты реестра | +| `direct/direct.go` | Единственная реализация Link. Pass-through: создаёт Transport и форвардит вызовы. Называется "direct" потому что нет промежуточного relay — данные идут прямо в transport | +| `direct/direct_test.go` | Тесты | + +### `internal/transport/` + +| Файл | Что делает | +|---|---| +| `transport.go` | Интерфейс `Transport` + реестр. `Features` описывает: надёжность, упорядоченность, message-oriented или stream, макс. размер payload | +| `transport_test.go` | Тесты реестра | +| `datachannel/transport.go` | Самый простой транспорт. Открывает ByteStream у carrier (DataChannel), просто форвардит байты. Лимит payload: 12KB | +| `vp8channel/transport.go` | Данные кодируются в VP8 видеофреймы. Поверх carrier строится KCP (надёжный UDP-подобный протокол) для реорганизации и ретрансмиссии. Данные батчатся по N фреймов за тик. Keepalive через keyframe | +| `vp8channel/kcp.go` | KCP сессия: conv ID = `0xC0FFEE01`, MTU 1400, окно 4096 сегментов. Length-prefix framing поверх KCP stream mode (workaround бага kcp-go с фрагментацией) | +| `vp8channel/kcpconn.go` | `io.ReadWriteCloser` адаптер для KCP | +| `seichannel/transport.go` | Данные передаются в SEI NAL-юнитах внутри H264 видеопотока. Собственный бинарный протокол с magic `OVC1`, версией, типами фреймов Data/Ack, CRC32, sequence numbers. ACK timeout, фрагментация, ретрансмиссия | +| `seichannel/h264.go` | Сборка H264 Access Unit с SEI payload. UUID для SEI: `5dc03ba8-450f-4b55-9a77-1f916c5b0739`. Статичные SPS/PPS/IDR как базовые заголовки | +| `videochannel/transport.go` | Данные визуально кодируются в кадры (QR-коды или тайлы), кадры транслируются через VP8 видеопоток. ffmpeg запускается как subprocess для кодирования/декодирования. ACK-based flow control с sequence numbers | +| `videochannel/visual.go` | Рендеринг кадров: QR-коды через `gr/qr`, тайлы через `gr/tile` с Reed-Solomon. Декодирование входящих кадров | +| `videochannel/ffmpeg.go` | ffmpeg encoder/decoder как subprocess с pipe. Поддержка VP8, H264. Hardware acceleration через NVENC. Таймаут на получение фрейма | +| `videochannel/frame.go` | Протокол фреймов videochannel | + +### `internal/carrier/` + +| Файл | Что делает | +|---|---| +| `carrier.go` | Интерфейс `Session` + реестр. `Capabilities` описывает что умеет carrier: ByteStream и/или VideoTrack | +| `bytestream.go` | `ByteStream` и `VideoTrack` интерфейсы | +| `carrier_test.go` | Тесты | +| `builtin/register.go` | Регистрирует jazz, telemost, wbstream в реестре carrier | +| `builtin/provider_adapter.go` | Адаптер `provider.Provider` → `carrier.Session` | + +### `internal/provider/` + +| Файл | Что делает | +|---|---| +| `provider.go` | Интерфейс `Provider`: Connect, Send, Close, SetReconnectCallback, WatchConnection, CanSend, GetSendQueue, AddVideoTrack и т.д. | +| `jazz/provider.go` | SaluteJazz провайдер. Обёртка над `Peer` | +| `jazz/peer.go` | WebRTC peer для jazz. Signaling через HTTP API SaluteJazz. Автопереподключение, очередь отправки, backpressure | +| `jazz/api.go` | HTTP клиент API SaluteJazz: создание комнаты, получение SDP | +| `jazz/datapacket.go` | Protobuf-style пакетное кодирование сообщений DataChannel jazz (специфика протокола jazz) | +| `telemost/provider.go` | Yandex Telemost провайдер | +| `telemost/peer.go` | WebRTC peer для Telemost. Signaling через WebSocket. Двухуровневый keepalive (WS ping + app ping). Автопереподключение | +| `telemost/api.go` | HTTP/WS клиент API Telemost | +| `wbstream/provider.go` | WB Stream провайдер через LiveKit SDK | +| `wbstream/peer.go` | WebRTC peer для wbstream. Самый стабильный провайдер — минимальная прослойка, почти прямой relay | +| `wbstream/api.go` | API клиент wbstream: создание стрима/комнаты | + +### `internal/crypto/` + +| Файл | Что делает | +|---|---| +| `chacha.go` | ChaCha20-Poly1305 AEAD. 32-байтовый ключ. Каждый Encrypt генерирует случайный nonce и prepend его к ciphertext. Decrypt проверяет AEAD тег | +| `chacha_test.go` | Тесты | + +### `internal/names/` + +| Файл | Что делает | +|---|---| +| `names.go` | Генератор случайных имён участников для WebRTC комнаты. Имена загружаются из `data/names` и `data/surnames` (встроены через `//go:embed`). Можно переопределить внешними файлами. `Generate()` возвращает "Имя Фамилия" с крипто-рандомом | +| `names_test.go` | Тесты | + +### `internal/protect/` + +| Файл | Что делает | +|---|---| +| `protect.go` | Android VPN protect() интеграция. `Protector func(fd int) bool` — если установлен, вызывается перед каждым connect чтобы сокет не роутился через VPN (нужно для корректной работы в связке с VPN-приложением на Android) | +| `protect_test.go` | Тесты | + +### `internal/logger/` + +| Файл | Что делает | +|---|---| +| `logger.go` | Структурированный логгер с уровнями Info/Warn/Error/Debug/Verbose. В не-debug режиме подавляет шум pion/LiveKit | +| `logger_test.go` | Тесты | + +### `internal/e2e/` + +| Файл | Что делает | +|---|---| +| `tunnel_test.go` | E2E тесты на реальных провайдерах. Матрица всех carrier × transport комбинаций. Запускается с флагом `-olcrtc.real-e2e`. В CI запускается на каждый push | + +### `mobile/` + +| Файл | Что делает | +|---|---| +| `mobile.go` | gomobile-совместимый API для Android/iOS. Синглтон: `Start()`, `Stop()`, `IsRunning()`. `SocketProtector` интерфейс для Android VPN bypass. `LogWriter` интерфейс для получения логов в Kotlin/Java. По умолчанию использует `vp8channel` транспорт | +| `mobile_test.go` | Тесты mobile API | + +### `code/` — Python PoC скрипты + +| Файл | Что делает | +|---|---| +| `telemost_poc_datachannel.py` | Базовый PoC: два гостя в одной Telemost комнате, обмен данными через DataChannel | +| `telemost_poc_videochannel.py` | Передача данных QR-кодами в видеопотоке Telemost | +| `telemost_info.py` | Сбор полной информации о Telemost конференции: участники, кодеки, ICE серверы, SDP | +| `jazz_poc_datachannel.py` | PoC DataChannel через SaluteJazz | +| `jazz_info.py` | Информация о Jazz конференции | +| `wbstream_poc_datachannel.py` | PoC DataChannel через WB Stream | +| `wbstream_poc_videochannel.py` | PoC видеоканала через WB Stream | +| `wbstream_info.py` | Информация о WB Stream комнате | +| `secretny_ddoos.py` | Утилита для стресс-тестирования (flood) | +| `init.sh` | Скрипт инициализации окружения | +| `requirements.txt` | Python зависимости: aiortc, opencv, pyzbar и др. | + +### `script/` + +| Файл | Что делает | +|---|---| +| `srv.sh` | Интерактивный скрипт запуска сервера через Podman. Задаёт вопросы про carrier/transport/room/key, собирает образ, запускает контейнер | +| `cnc.sh` | Интерактивный скрипт запуска клиента через Podman | +| `docker/olcrtc-entrypoint.sh` | Docker entrypoint: читает env переменные, формирует CLI флаги, запускает `olcrtc` | +| `docker/olcrtc-healthcheck.sh` | Docker healthcheck: проверяет что процесс запущен | + +### `data/` + +| Файл | Что делает | +|---|---| +| `names` | Список русских имён для генератора имён участников | +| `surnames` | Список русских фамилий | + +### `docs/` + +| Файл | Что делает | +|---|---| +| `fast.md` | Быстрый старт через скрипты (Podman) | +| `manual.md` | Мануальная сборка: Go, mage, кросс-компиляция, все шаги | +| `settings.md` | Матрица совместимости carrier×transport, все CLI флаги с описанием, готовые команды | +| `uri.md` | URI формат для клиентских приложений: `olcrtc://?@#%$` | +| `sub.md` | Формат подписок: список серверов в одном файле с метаданными | + +--- + +## 6. Carriers — провайдеры + +Carrier — это WebRTC сервис видеозвонков, через который идёт туннель. Все три в белых списках у российских провайдеров. + +### SaluteJazz (`jazz`) + +- Сервис видеозвонков от Сбера: `salutejazz.ru` +- Не требует регистрации для участника (только организатор) +- DataChannel работает, но Jazz **банит IP** за паттерны трафика характерные для DataChannel туннеля +- VideoTrack работает стабильно +- Поддерживает автогенерацию Room ID (`-mode gen`) +- Инициализация звонка изнутри автоматически реализована + +### Yandex Telemost (`telemost`) + +- Сервис видеозвонков от Яндекса: `telemost.yandex.ru` +- **Удалил DataChannel** — его больше нет в Telemost +- VideoTrack работает +- Требует создания комнаты вручную через сайт (нет автогенерации) +- Двухуровневый keepalive: WebSocket ping + app-level ping + +### WB Stream (`wbstream`) + +- Сервис трансляций от Wildberries: `stream.wb.ru` +- **Рекомендуется** — самый стабильный +- Минимальная прослойка, почти прямой relay +- Работает со всеми транспортами: datachannel, vp8channel, seichannel, videochannel +- Поддерживает автогенерацию Room ID (`-mode gen`) +- Инициализация звонка автоматически + +--- + +## 7. Transports — транспорты + +Transport определяет как именно данные упаковываются в WebRTC поток. + +### datachannel + +Самый простой и быстрый. Данные идут напрямую через WebRTC DataChannel (SCTP over DTLS). + +- Лимит payload: 12KB на сообщение (ограничение SFU) +- Надёжный, упорядоченный (SCTP гарантирует) +- Работает с jazz (нежелательно — банят) и wbstream +- **Лучшая комбинация: `wbstream + datachannel`** + +### vp8channel + +Данные упаковываются в VP8 видеофреймы. Поверх этого строится KCP — надёжный протокол с повторной передачей, работающий поверх ненадёжного канала. + +- Работает везде где есть VideoTrack (jazz, telemost, wbstream) +- Большой пинг из-за батчинга фреймов +- KCP параметры: MTU 1400, окно 4096, conv ID `0xC0FFEE01` +- Рекомендуется: `-vp8-fps 60 -vp8-batch 64` + +### seichannel + +Данные передаются в SEI (Supplemental Enhancement Information) NAL-юнитах H264 видеопотока. SEI — стандартный механизм для метаданных в H264. + +- Собственный бинарный протокол: magic `OVC1` (0x4f564331), версия, тип Data/Ack, CRC32, sequence numbers +- UUID для SEI payload: `5dc03ba8-450f-4b55-9a77-1f916c5b0739` +- ACK timeout (по умолчанию 3с), фрагментация, ретрансмиссия до 4 попыток +- Не работает с telemost +- Рекомендуется: `-fps 60 -batch 64 -frag 900 -ack-ms 2000` + +### videochannel + +Данные визуально кодируются в видеофреймы через ffmpeg. Два визуальных кодека: + +**qrcode** — данные кодируются в QR-код, QR рендерится в VP8 кадр. На приёмнике VP8 декодируется и QR сканируется. Использует библиотеку `gr/qr` (субмодуль). Настройки: разрешение, ECC уровень (`low`/`medium`/`high`/`highest`), размер фрагмента. + +**tile** — тайловый кодек, только 1080x1080. Пиксели кодируют биты напрямую. Reed-Solomon коррекция ошибок. Параметры: размер тайла в пикселях (1..270), процент избыточности (0..200). Быстрее QR но нестабильнее. + +Общее: ffmpeg как subprocess, поддержка NVENC, VP8 видеопоток. Самый медленный транспорт, но работает везде. + +--- + +## 8. Шифрование + +Весь туннельный трафик шифруется **ChaCha20-Poly1305** (XChaCha20-Poly1305 через `golang.org/x/crypto`). + +- Ключ: 32 байта, передаётся как hex строка (64 символа) +- Генерация: `openssl rand -hex 32` +- Каждое сообщение: случайный nonce (24 байта) prepend к ciphertext + AEAD тег +- Ключ должен совпадать на сервере и клиенте +- Шифрование происходит в `muxconn` — до передачи в transport/carrier + +WebRTC сам по себе шифрует трафик через DTLS-SRTP, но olcRTC добавляет поверх свой слой — провайдер видит только зашифрованный blob. + +--- + +## 9. Мультиплексирование + +Через один WebRTC DataChannel / VideoTrack одновременно могут идти сотни TCP соединений браузера. + +Реализация через **smux** (`github.com/xtaci/smux`) — библиотека мультиплексирования потоков, аналог HTTP/2 multiplexing. + +До мая 2026 был самописный мультиплексор с sequence numbering и ручным out-of-order handling. Заменён на smux поверх KCP для vp8channel, и smux напрямую для datachannel. + +`muxconn.Conn` адаптирует `link.Link` (message-oriented) в `io.ReadWriteCloser` (stream-oriented) который нужен smux. Каждый `Write` = одно зашифрованное сообщение в link. + +--- + +## 10. SOCKS5 прокси + +Клиент (`cnc`) поднимает локальный SOCKS5-сервер. + +**Поддерживается:** +- SOCKS5 (RFC 1928) с командой CONNECT +- Аутентификация username/password (RFC 1929) через `-socks-user`/`-socks-pass` +- SOCKS5h (hostname resolution на стороне сервера) — DNS запросы идут через туннель +- Без аутентификации (по умолчанию) + +**Адрес по умолчанию:** `127.0.0.1:8808` + +**Использование:** +```sh +curl --socks5-hostname 127.0.0.1:8808 https://icanhazip.com +export all_proxy=socks5h://127.0.0.1:8808 +export all_proxy=socks5h://user:pass@127.0.0.1:8808 # с авторизацией +``` + +**Сервер** (`srv`) может сам ходить через SOCKS5 прокси для исходящего трафика (`-socks-proxy`, `-socks-proxy-port`). + +--- + +## 11. Mobile / Android + +`mobile/mobile.go` — gomobile-совместимый API. + +Собирается в `olcrtc.aar` через `mage mobile` (`gomobile bind`). + +Community Android клиент: [alananisimov/olcbox](https://github.com/alananisimov/olcbox) + +**API:** +- `Start(carrier, roomID, clientID, keyHex string)` — запустить туннель +- `Stop()` — остановить +- `IsRunning() bool` +- `SetProtector(p SocketProtector)` — Android VPN bypass (VpnService.protect) +- `SetLogWriter(w LogWriter)` — получать логи в Kotlin/Java + +По умолчанию использует `vp8channel` транспорт (наиболее совместимый). Если carrier — wbstream или jazz и DataChannel доступен — переключается на `datachannel`. + +`protect.go` — механизм Android VPN protect: перед каждым `connect()` вызывается Kotlin-коллбэк который вызывает `VpnService.protect(fd)`. Без этого трафик olcRTC может рекурсивно идти через тот же VPN. + +--- + +## 12. Python PoC скрипты + +Исторический слой — с этого всё начиналось. Используются для исследования API провайдеров и проверки гипотез. + +**Telemost:** +- `telemost_poc_datachannel.py` — первый рабочий туннель, обнаружен лимит 8KB DataChannel (молча дропает больше) +- `telemost_poc_videochannel.py` — QR в видео, `vcsend.py` — передача файлов +- `telemost_info.py` — полный дамп SDP, ICE серверов, участников + +**Jazz:** +- `jazz_poc_datachannel.py` — DataChannel через Jazz SFU +- `jazz_info.py` — информация о конференции + +**WB Stream:** +- `wbstream_poc_datachannel.py` — DataChannel +- `wbstream_poc_videochannel.py` — видеоканал +- `wbstream_info.py` — информация + +Для запуска: `pip install -r code/requirements.txt` + +--- + +## 13. Сборка и деплой + +### Зависимости + +- Go 1.25+ +- Mage (`go install github.com/magefile/mage@latest`) +- ffmpeg (для videochannel транспорта) +- git с `--recurse-submodules` (субмодуль `gr` для videochannel кодеков) +- gomobile (для Android сборки) + +### Mage таргеты + +```sh +mage build # текущая платформа +mage buildCLI # только CLI +mage buildCLIB # CLI + b-codec (клонирует внешний репо, собирает libb.so) +mage cross # все платформы: linux/amd64, linux/arm64, windows/amd64, + # darwin/amd64, darwin/arm64, freebsd/amd64, freebsd/arm64, + # openbsd/amd64, openbsd/arm64 +mage mobile # Android AAR через gomobile +mage podman # Docker образ через podman +mage docker # Docker образ через docker +mage lint # golangci-lint +mage test # go test -race ./... +mage e2e # E2E тесты (нужны реальные провайдеры) +mage clean # удалить build/ +``` + +### Быстрый старт через скрипты (Podman) + +```sh +git clone https://github.com/openlibrecommunity/olcrtc --recurse-submodules +cd olcrtc + +# на сервере (VPS): +./script/srv.sh + +# на клиенте: +./script/cnc.sh +``` + +### Мануальный запуск + +```sh +# генерация ключа +openssl rand -hex 32 + +# генерация room ID (для jazz/wbstream) +./olcrtc -mode gen -carrier wbstream -dns 1.1.1.1:53 -amount 1 -data data + +# сервер +./olcrtc -mode srv -carrier wbstream -transport datachannel \ + -id ROOM_ID -client-id default -key HEX_KEY \ + -link direct -dns 1.1.1.1:53 -data data + +# клиент +./olcrtc -mode cnc -carrier wbstream -transport datachannel \ + -id ROOM_ID -client-id default -key HEX_KEY \ + -link direct -dns 1.1.1.1:53 -data data \ + -socks-host 127.0.0.1 -socks-port 8808 +``` + +### Docker + +```sh +docker run -e OLCRTC_CARRIER=wbstream \ + -e OLCRTC_ROOM_ID=... \ + -e OLCRTC_KEY=... \ + olcrtc/server:local +``` + +--- + +## 14. CLI — все флаги + +### Обязательные (для всех режимов) + +| Флаг | Описание | +|---|---| +| `-mode` | `srv` — сервер, `cnc` — клиент, `gen` — генерация Room ID | +| `-carrier` | `telemost`, `jazz`, `wbstream` | +| `-transport` | `datachannel`, `vp8channel`, `seichannel`, `videochannel` | +| `-id` | Room ID | +| `-client-id` | Идентификатор клиента, должен совпадать на srv и cnc | +| `-key` | Ключ шифрования hex 64 символа | +| `-link` | Всегда `direct` | +| `-data` | Всегда `data` | +| `-dns` | DNS сервер, например `1.1.1.1:53` | + +### Необязательные + +| Флаг | Описание | +|---|---| +| `-debug` | Verbose логи | + +### Только для клиента (`-mode cnc`) + +| Флаг | По умолчанию | Описание | +|---|---|---| +| `-socks-host` | `127.0.0.1` | Адрес SOCKS5 | +| `-socks-port` | `1080` | Порт SOCKS5 | +| `-socks-user` | — | Логин (опционально) | +| `-socks-pass` | — | Пароль (опционально) | + +### Только для сервера (`-mode srv`) + +| Флаг | Описание | +|---|---| +| `-socks-proxy` | Адрес SOCKS5 прокси для исходящего трафика | +| `-socks-proxy-port` | Порт этого прокси | + +### Режим генерации (`-mode gen`) + +| Флаг | Описание | +|---|---| +| `-amount` | Количество комнат для генерации | + +### vp8channel + +| Флаг | Default | Описание | +|---|---|---| +| `-vp8-fps` | 25 | FPS VP8 потока | +| `-vp8-batch` | 1 | Кадров за тик | + +### seichannel + +| Флаг | Default | Описание | +|---|---|---| +| `-fps` | 20 | FPS H264 потока | +| `-batch` | 1 | Кадров за тик | +| `-frag` | 900 | Размер фрагмента в байтах | +| `-ack-ms` | 2000 | ACK timeout в мс | + +### videochannel + +| Флаг | Default | Описание | +|---|---|---| +| `-video-codec` | `qrcode` | `qrcode` или `tile` | +| `-video-w` | 1920 | Ширина | +| `-video-h` | 1080 | Высота | +| `-video-fps` | 30 | FPS | +| `-video-bitrate` | `2M` | Битрейт | +| `-video-hw` | `none` | `none` или `nvenc` | +| `-video-qr-recovery` | `low` | ECC: `low`/`medium`/`high`/`highest` | +| `-video-qr-size` | 0 (авто) | Размер фрагмента QR в байтах | +| `-video-tile-module` | 4 | Размер тайла в пикселях 1..270 | +| `-video-tile-rs` | 20 | Reed-Solomon паритет % 0..200 | + +--- + +## 15. URI-формат и подписки + +### URI формат + +Соглашение для клиентских приложений. Сам `olcrtc` не парсит — используется в сторонних клиентах. + +``` +olcrtc://?@#%$ +``` + +Где `` — опциональный блок `` с параметрами транспорта. + +**Примеры:** +``` +olcrtc://wbstream?datachannel@room-01#d823fa...%android-01$RU / olc free sub +olcrtc://wbstream?vp8channel@room-01#d823fa...%android-01$RU +olcrtc://telemost?seichannel@room-01#d823fa...%client$RU +``` + +### Формат подписки (sub.md) + +Текстовый файл со списком серверов. Хостится на сервере как plain text. + +```text +#name: Zarazaex Free RU +#update: 1778011200 +#refresh: 10m +#icon: 🇷🇺 + +olcrtc://wbstream?datachannel@room-01#key%client-id$RU / free +##name: RU-1 +##ip: 1.2.3.4 +##comment: basic free node +``` + +Клиентские приложения читают этот файл и предлагают список серверов пользователю (аналог подписок в v2ray/sing-box). + +--- + +## 16. Матрица совместимости + +| Transport | telemost | jazz | wbstream | +|---|:---:|:---:|:---:| +| datachannel | — | `*` | `+` | +| vp8channel | `+` | `+` | `+` | +| seichannel | — | `+` | `+` | +| videochannel | `+` | `+` | `+` | + +- `+` работает +- `—` не поддерживается +- `*` работает, но jazz банит IP за паттерны datachannel трафика + +**Рекомендуется:** `wbstream + datachannel` — максимальная скорость, минимальный пинг, без бана. + +**Скорость по убыванию:** `datachannel` > `vp8channel` > `seichannel` > `videochannel` + +--- + +## 17. CI/CD + +`.github/workflows/ci.yml` — GitHub Actions, запускается на каждый push/PR в master. + +| Job | Что делает | +|---|---| +| `test` | `go test -count=1 ./...` | +| `coverage` | `go test --cover ./...` | +| `real-e2e` | E2E матрица всех carrier×transport на реальных провайдерах (25 мин таймаут) | +| `lint` | golangci-lint | +| `build-cli` | `mage cross` — кросс-компиляция для 9 платформ, артефакты в Actions | +| `build-android` | `mage mobile` — Android AAR, артефакт в Actions | + +Go версия в CI: 1.25.x + +--- + +## 18. Что планируется сделать — Issues + +### Открытые + +**Issue #22 — реализовать поддержку stream.wb.ru** `enhancement` + +WB Stream — текущий приоритет. Основа уже реализована, остаётся: +- [ ] Симуляция XHR телеметрии (маскировка под легитимный клиент) +- [ ] Симуляция задержек и обрезание до размера реальных сообщений +- [ ] Система завершения звонка +- [ ] Авто перезапуск звонка если идёт слишком долго +- [ ] Юзать TLS стек Chrome как naiveproxy + +**Issue #2 — реализовать поддержку telemost.yandex.ru** `enhancement` + +- [ ] Симуляция XHR телеметрии +- [ ] Симуляция задержек +- [ ] Инициализация звонка изнутри автоматически +- [ ] Система завершения звонка +- [ ] Авто перезапуск звонка +- [ ] TLS стек Chrome + +**Issue #1 — реализовать поддержку salutejazz.ru** `enhancement` + +- [ ] Симуляция XHR телеметрии +- [ ] Симуляция задержек +- [ ] Система завершения звонка +- [ ] Авто перезапуск звонка +- [ ] TLS стек Chrome + +### Закрытые (уже сделано) + +| Issue | Что было | +|---|---| +| #44 | Very high ping — исправлен throughput bug vp8channel | +| #40 | Подключение нескольких устройств — реализовано через client-id | +| #39 | Oracle VPS поддержка | +| #38 | Стандартный URI формат — реализован | +| #37 | Jitsi Meet — не планируется | +| #33 | iOS клиент — в планах | +| #27 | Инструкция — написана | +| #26 | SIP003 transport — не планируется | +| #25 | TLS/DTLS фингерпринтинг | +| #9 | Нормальный мультиплексор — реализован (smux) | +| #3 | macOS/Linux/Android/Windows поддержка — реализована | + +--- + +## 19. Контрибуторы + +| Контрибутор | Коммиты | Вклад | +|---|---|---| +| **zarazaex69** (zarazaex@tuta.io) | 417 | Автор проекта. Вся архитектура, все транспорты, carriers, crypto, mobile API, CI, документация | +| **zowue** (heminpo49@gmail.com) | 24 | Соавтор. Упомянут в оригинальной статье на Хабре | +| **TheDevisi** (devisinov@gmail.com) | 20 | UI, SOCKS5 улучшения, Windows поддержка, фиксы | +| **Qtozdec** | 10 | Фиксы, URI добавление | +| **Alexander Anisimov** / alananisimov | 6 | Android клиент [olcbox](https://github.com/alananisimov/olcbox), mobile.go фиксы, mobile provider config | +| **s0me0ne-25** | 3 | Расширение датасета имён и фамилий | +| **Kot-nikot** | 3 | Фиксы | +| **HLNikNiky** / Sesdear | 2 | URI добавление, фиксы | +| **Denis Suchok** / DeNcHiK3713 | 1 | Windows Podman скрипты | +| **0xcodepunk** | 1 | SaluteJazz PoC DataChannel (issue #10) | +| **scalebb2** | 1 | — | + +--- + +## 20. Частые ошибки + +### `Connection refused` на порту SOCKS5 + `i/o timeout` при резолве + +**Симптомы:** +``` +curl: (7) Failed to connect to 127.0.0.1 port 8808 after 0 ms: Connection refused +``` + +Клиент сообщает `[+] Client started successfully!`, но SOCKS5 порт не слушает. + +В логах контейнера: +``` +client: failed to connect link: transport connect: stream connect: connect: +get room token: register guest: do request: Post "https://stream.wb.ru/...": +dial tcp: lookup stream.wb.ru: i/o timeout +``` + +**Причина:** клиент не смог зарезолвить `stream.wb.ru` через указанный DNS сервер. Соединение не установилось, SOCKS5 не поднялся. + +**Решение:** указать другой DNS сервер в скрипте. Вместо дефолтного `1.1.1.1` попробовать `8.8.8.8` или `77.88.8.8`: + +```sh +# при запуске cnc.sh — в поле DNS ввести: +8.8.8.8:53 +# или +77.88.8.8:53 +``` + +При ручном запуске: +```sh +./olcrtc -mode cnc ... -dns 8.8.8.8:53 +``` + +После смены DNS в логах должна появиться строка: +``` +SOCKS5 server listening on 0.0.0.0:8808 +``` + +--- + +## Контакты + +- Telegram канал: [@openlibrecommunity](https://t.me/openlibrecommunity) — бесплатный прокси в закрепе, обновления, анонсы +- Telegram автора: [@zarazaexe](https://t.me/zarazaexe) +- Email: [zarazaex@tuta.io](mailto:zarazaex@tuta.io) +- GitHub: [openlibrecommunity](https://github.com/openlibrecommunity) +- Android клиент: [alananisimov/olcbox](https://github.com/alananisimov/olcbox) +- Белые списки (еженедельное обновление): [openlibrecommunity/twl](https://github.com/openlibrecommunity/twl)