Files
olcrtc/docs/about.md
2026-05-14 03:58:39 +03:00

50 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. YAML конфигурация
  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-формат и формат подписок, SOCKS5 аутентификация.

2026-05-07..10 - финальная полировка: исправлен throughput bug в vp8channel (ограничение было в 32 раза ниже реального), документация, SEI конфигурация, SOCKS5 аутентификация (username/password).

Статья на Хабре

Проект описан в двух статьях на Хабре:

  • «Это - всё что вам надо знать о белых списках» - технический анализ как работает фильтрация, 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, загрузка YAML конфига
    │
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 Точка входа. Загружает YAML конфиг (olcrtc config.yaml), настраивает логирование, подавляет шум 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 больше не поддерживает автогенерацию - руму нужно создавать вручную через stream.wb.ru)
session_test.go Тесты валидации конфига

internal/server/

Файл Что делает
server.go Серверная сторона туннеля. Подключается к комнате как второй участник звонка. Создаёт muxconnsmux.Session. Первый smux-стрим — контрольный (handshake CLIENT_HELLO / SERVER_WELCOME). Для каждого последующего стрима читает JSON ConnectRequest от клиента, устанавливает TCP соединение и гоняет байты. Поддерживает хуки: OnSessionOpen, OnSessionClose, OnTraffic. Умеет переподключаться при разрыве
server_test.go Тесты серверной логики

internal/client/

Файл Что делает
client.go Клиентская сторона. Поднимает SOCKS5-сервер. Для каждого входящего подключения: SOCKS5 handshake (поддержка RFC 1929 username/password auth), создаёт smux-стрим, шлёт JSON ConnectRequest с адресом, гоняет байты. Первый smux-стрим — контрольный (handshake). Переподключается при разрыве WebRTC сессии с retry loop
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, генерирует YAML конфиг, собирает образ, запускает контейнер. Флаги: --branch=<name> (сменить ветку), --no-cache (очистить Go-кеш перед сборкой)
cnc.sh Интерактивный скрипт запуска клиента через Podman
script/docker/olcrtc-entrypoint.sh Docker entrypoint: читает env переменные, генерирует YAML конфиг, запускает olcrtc
docker/olcrtc-healthcheck.sh Docker healthcheck: проверяет что процесс запущен

data/

Файл Что делает
names Список русских имён для генератора имён участников
surnames Список русских фамилий

docs/

Файл Что делает
fast.md Быстрый старт через скрипты (Podman)
manual.md Мануальная сборка: Go, mage, кросс-компиляция, все шаги
settings.md Матрица совместимости carrier×transport, описание всех YAML полей, готовые примеры конфигов
uri.md URI формат для клиентских приложений: olcrtc://<Carrier>?<Transport>@<RoomID>#<Key>$<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
  • Работает с vp8channel, seichannel, videochannel
  • DataChannel поддерживается условно: WB Stream должен выдать участникам право canPublishData, обычно через модераторские/permission права комнаты. В обычном guest flow DC не рекомендуется.
  • Room ID нужно создавать вручную через stream.wb.ru
  • Инициализация звонка автоматически

7. Transports - транспорты

Transport определяет как именно данные упаковываются в WebRTC поток.

datachannel

Самый простой и быстрый. Данные идут напрямую через WebRTC DataChannel (SCTP over DTLS).

  • Лимит payload: 12KB на сообщение (ограничение SFU)
  • Надёжный, упорядоченный (SCTP гарантирует)
  • Работает с jazz (нежелательно - банят) и условно с wbstream
  • WB Stream DataChannel требует canPublishData=true у участников. Без модераторских/permission прав WB Stream может поднять соединение, но не маршрутизировать data packets.

vp8channel

Данные упаковываются в VP8 видеофреймы. Поверх этого строится KCP - надёжный протокол с повторной передачей, работающий поверх ненадёжного канала.

  • Работает везде где есть VideoTrack (jazz, telemost, wbstream)
  • Большой пинг из-за батчинга фреймов
  • KCP параметры: MTU 1400, окно 4096, conv ID 0xC0FFEE01
  • Рекомендуется: vp8.fps: 60, vp8.batch_size: 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
  • Рекомендуется: sei.fps: 60, sei.batch_size: 64, sei.fragment_size: 900, sei.ack_timeout_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 в YAML конфиге
  • 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_addr, socks.proxy_port в YAML конфиге).


11. Mobile / Android

mobile/mobile.go - gomobile-совместимый API.

Собирается в olcrtc.aar через mage mobile (gomobile bind).

Community Android клиент: alananisimov/olcbox

API:

  • Start(carrier, roomID, 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

# создать конфиг (пример: wbstream + vp8channel)
cat > server.yaml <<EOF
mode: srv
link: direct
auth:
  provider: wbstream
room:
  id: "ROOM_ID_HERE"
crypto:
  key: "REPLACE_WITH_64_HEX"
net:
  transport: vp8channel
  dns: "1.1.1.1:53"
data: data
EOF

# запустить сервер
./olcrtc server.yaml

# конфиг клиента
cat > client.yaml <<EOF
mode: cnc
link: direct
auth:
  provider: wbstream
room:
  id: "ROOM_ID_HERE"
crypto:
  key: "REPLACE_WITH_64_HEX"
net:
  transport: vp8channel
  dns: "1.1.1.1:53"
socks:
  host: "127.0.0.1"
  port: 8808
data: data
EOF

# запустить клиент
./olcrtc client.yaml

Docker

# Mount your YAML config into the container:
docker run -v ./server.yaml:/etc/olcrtc/server.yaml \
           olcrtc/server:local /etc/olcrtc/server.yaml

14. YAML конфигурация

olcrtc читает конфигурацию из единственного YAML-файла. CLI-флагов нет.

olcrtc config.yaml

Полная схема описана в configuration.md. Примеры:

Основные поля

YAML путь Описание
mode srv - сервер, cnc - клиент, gen - генерация Room ID
link Всегда direct
auth.provider telemost, jazz, wbstream или none
room.id Room ID
crypto.key Ключ шифрования hex 64 символа
net.transport datachannel, vp8channel, seichannel, videochannel
net.dns DNS сервер, например 1.1.1.1:53
data Путь к директории данных
debug Verbose логи

Только клиент (mode: cnc)

YAML путь Описание
socks.host Адрес SOCKS5 (по умолчанию 127.0.0.1)
socks.port Порт SOCKS5 (по умолчанию 8808)
socks.user Логин (опционально)
socks.pass Пароль (опционально)

Только сервер (mode: srv)

YAML путь Описание
socks.proxy_addr Адрес SOCKS5 прокси для исходящего трафика
socks.proxy_port Порт этого прокси

Генерация (mode: gen)

YAML путь Описание
gen.amount Количество комнат для генерации

Транспорты

Настройки транспортов задаются в секциях vp8, sei, video YAML конфига. Подробнее в configuration.md.


15. URI-формат и подписки

URI формат

Соглашение для клиентских приложений. Сам olcrtc не парсит - используется в сторонних клиентах.

olcrtc://<Carrier>?<Transport><payload>@<RoomID>#<Key>$<MIMO>

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

Примеры:

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

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

Текстовый файл со списком серверов. Хостится на сервере как plain text.

#name: Zarazaex Free RU
#update: 1778011200
#refresh: 10m
#icon: 🇷🇺

olcrtc://wbstream?vp8channel<vp8-fps=60&vp8-batch=64>@room-01#key$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 трафика
  • ! работает только если WB Stream выдал участникам право canPublishData (обычно через модераторские/permission права)

Рекомендуется для wbstream: vp8channel как обычный режим. wbstream + datachannel быстрый, но не рекомендуется без модераторских прав: в guest flow WB Stream может выдавать токены с canPublishData=false, и DC не будет маршрутизировать данные.

Скорость по убыванию: datachannel > vp8channel > seichannel > videochannel

Рекордный замер: на связке wbstream + datachannel (test by x2827262628281872727) зафиксированы пинг 7 мс и скорость 792.62 Mbps на вход / 749.69 Mbps на выход - максимум, измеренный через olcRTC. Сейчас этот режим зависит от WB Stream permission canPublishData и не считается рекомендуемым для обычного guest flow.

speedtest

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 Подключение нескольких устройств
#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

При ручном запуске — указать другой DNS в YAML конфиге:

net:
  dns: "8.8.8.8:53"

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

SOCKS5 server listening on 0.0.0.0:8808

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

Симптомы:

В логах сервера появляются строки вида:

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 прокси через YAML конфиг:
socks:
  proxy_addr: "1.2.3.4"
  proxy_port: 1080

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


Контакты