Files
olcrtc/docs/about.md
2026-05-10 15:46:41 +03:00

49 KiB
Raw Blame History

olcRTC - полная документация

olcRTC (OpenLibreCommunity RTC) - инструмент обхода интернет-блокировок через паразитирование на легальных WebRTC-сервисах видеозвонков, уже находящихся в российских белых списках.

Проект: github.com/openlibrecommunity/olcrtc Лицензия: WTFPL Статус: Beta


Содержание

  1. Почему olcRTC существует
  2. Идея и история создания
  3. Как это работает
  4. Архитектура
  5. Структура репозитория
  6. Carriers - провайдеры
  7. Transports - транспорты
  8. Шифрование
  9. Мультиплексирование
  10. SOCKS5 прокси
  11. Mobile / Android
  12. Python PoC скрипты
  13. Сборка и деплой
  14. CLI - все флаги
  15. URI-формат и подписки
  16. Матрица совместимости
  17. CI/CD
  18. Что планируется сделать - Issues
  19. Контрибуторы
  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 Серверная сторона туннеля. Подключается к комнате как второй участник звонка. Создаёт muxconnsmux.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.Linkio.ReadWriteCloser. Каждый Write шифрует блок ChaCha20-Poly1305 и отдаёт в link как одно сообщение. Входящие сообщения дешифруются и буферизуются; Read дренирует буфер в произвольных кусках (smux не знает о границах сообщений). Синхронизация через sync.Cond
conn_test.go Тесты
Файл Что делает
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.Providercarrier.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://<Carrier>?<Transport>@<RoomID>#<Key>%<ClientID>$<MIMO>
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

Использование:

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

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 таргеты

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)

git clone https://github.com/openlibrecommunity/olcrtc --recurse-submodules
cd olcrtc

# на сервере (VPS):
./script/srv.sh

# на клиенте:
./script/cnc.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

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://<Carrier>?<Transport><payload>@<RoomID>#<Key>%<ClientID>$<MIMO>

Где <payload> - опциональный блок <key=value&...> с параметрами транспорта.

Примеры:

olcrtc://wbstream?datachannel@room-01#d823fa...%android-01$RU / olc free sub
olcrtc://wbstream?vp8channel<vp8-fps=60&vp8-batch=64>@room-01#d823fa...%android-01$RU
olcrtc://telemost?seichannel<fps=60&batch=64&frag=900&ack-ms=2000>@room-01#d823fa...%client$RU

Формат подписки (sub.md)

Текстовый файл со списком серверов. Хостится на сервере как plain 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, 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:

# при запуске cnc.sh - в поле DNS ввести:
8.8.8.8:53
# или
77.88.8.8:53

При ручном запуске:

./olcrtc -mode cnc ... -dns 8.8.8.8:53

После смены DNS в логах должна появиться строка:

SOCKS5 server listening on 0.0.0.0:8808

dial tcp4 : i/o timeout на сервере (VPS блокирует исходящий трафик)

Симптомы:

В логах сервера (-mode srv) появляются строки вида:

sid=59 dial 157.240.205.60:443 failed (10.000774052s): dial failed: dial tcp4 157.240.205.60:443: i/o timeout
sid=69 dial 194.221.250.50:443 failed (10.002092858s): dial failed: dial tcp4 194.221.250.50:443: i/o timeout
sid=81 dial 149.154.167.41:5222 failed (10.000219783s): dial failed: dial tcp4 149.154.167.41:5222: i/o timeout

Таймаут всегда ровно 10 секунд (это дефолтный Timeout: 10 * time.Second в server.go). Затронутые сайты открываются нормально с локального браузера через прокси, но сервер до них не добирается.

Причина: хостинг-провайдер или фаервол VPS блокирует исходящие соединения к определённым IP-адресам или портам. Типичные жертвы:

  • 157.240.x.x — Facebook/Meta (порты 80, 443)
  • 194.221.x.x, 149.154.x.x, 91.108.x.x, 91.105.x.x — Telegram (порты 80, 443, 5222)

Российские VPS-провайдеры блокируют исходящий трафик к этим сайтам на уровне фаервола хостинга — независимо от настроек iptables на самой машине.

Диагностика: выполнить прямо на сервере:

curl -v --connect-timeout 5 https://157.240.205.60
curl -v --connect-timeout 5 https://149.154.167.41

Если таймаут — проблема на уровне хостинга.

Решение:

  1. Сменить хостинг-провайдера или локацию на того, кто не блокирует исходящий трафик.
  2. Использовать на сервере исходящий SOCKS5 прокси (-socks-proxy/-socks-proxy-port), который не заблокирован:
./olcrtc -mode srv ... -socks-proxy 1.2.3.4 -socks-proxy-port 1080

Это ошибка не на стороне olcRTC — он корректно логирует ошибки и продолжает работу. Соединения к незаблокированным адресам проходят без проблем. Проблема на стороне хостинга или фаервола.


Контакты