RU /EN
Обсудить проект
← Избранные проекты
Разбор проекта

turna

Собственный TURN/STUN-сервер на Rust, созданный для закрытой системы видеосвязи, где нужен контролируемый networking stack вместо внешней инфраструктуры.

  • Rust
  • RFC 5389 · 5766 · 8656
  • непрерывный фаззинг парсеров
  • Production GA 0.3.0

Что это

TURN/STUN-сервер на Rust. Когда два устройства не могут соединиться напрямую — обычная ситуация за NAT и корпоративным файрволом — трафик звонка идёт через relay. turna и есть такой relay, только развёрнутый и контролируемый самостоятельно.

Реализованы STUN (RFC 5389) и TURN (RFC 5766, RFC 8656). Apache 2.0.

Почему появился

Проекту нужна была закрытая система видеосвязи. Relay в такой системе — не второстепенная деталь: через него проходит весь медиатрафик тех звонков, которые не соединились напрямую. Значит через него проходят и вопросы доступа, лимитов и того, куда физически уходит поток.

Внешний сервис здесь означает передачу этого контура наружу. Поэтому networking stack был написан вместо подключения чужой инфраструктуры.

Что сделал

Протокольный слой, архитектура и весь эксплуатационный контур — самостоятельно. Воркспейс разделён по доменам: протокол (proto-stun, proto-turn, proto-rtp, packet), датапуть (transport, relay, session, qos), аутентификация и криптография, состояние и кластер, control-плоскость и наблюдаемость, бинари и инструменты.

Что технически интересно

Батчевый UDP I/O. Recv-воркеры на SO_REUSEPORT с recvmmsg/sendmmsg и арена-буферами на каждый батч. Relay читает и пишет пачками системных вызовов вместо одного пакета за раз — на медиатрафике это основная точка, где теряется пропускная способность.

Channel binding. Компактный режим пересылки без полного STUN-заголовка на каждом пакете. На потоке медиа разница в накладных расходах заметна.

Безопасность памяти под контролем. Парсеры STUN и TURN под непрерывным фаззингом (cargo-fuzz), а весь unsafe-код инвентаризован отдельным аудитом и ограничен транспортом и relay. Парсер сетевого протокола принимает данные из внешнего мира — валидными кадрами его проверять недостаточно.

Эксплуатация как часть продукта. gRPC control plane и CLI turnactl для управления на живом сервере, Prometheus-метрики и OpenTelemetry-трейсы из коробки, graceful drain с ограниченным по времени ожиданием, session migration по RFC 8016. Команды управления идемпотентны: у каждой есть целевой узел, ожидаемая версия и ключ идемпотентности, а результат берётся из durable-состояния узла, а не из локального состояния control-плоскости.

Многопользовательский контур. Realm’ы с отдельными пулами relay-портов и лимитами на арендатора, long-term credentials и JWT, ротация учётных данных, лимиты на субъект. Состояние — подключаемый backend: in-memory или Tarantool, с восстановлением конфигурации и лимитов после перезапуска.

Что готово, а что preview

Это, пожалуй, самая важная часть.

Production-путь — Tokio-датапуть: STUN binding, TURN allocation lifecycle, relay поверх UDP и TCP, аутентификация, наблюдаемость, управление, graceful drain.

За Cargo-фичами лежат и не считаются проверенными для production: датапути на io_uring и AF_XDP, транспорты DTLS, QUIC, WebTransport и TLS-over-TCP. RFC 6062 (TCP-аллокации) реализован, но обкатан меньше. Кластеризация — gossip-обнаружение, hash ring, TURN-редиректы — экспериментальная: она не гарантирует прозрачного выживания активных аллокаций и rolling-upgrade без разрыва.

В репозитории это оформлено таблицей гарантий, где явно написано и то, чего сервер не обещает: аллокация не гарантированно переживает падение процесса, активный медиапуть не переезжает на другой узел, прозрачный failover активной сессии вне рамок GA.

Такая таблица полезнее списка галочек. Инфраструктурный компонент выбирают по тому, что он гарантирует под нагрузкой, а не по длине списка поддерживаемых протоколов.

Бенчмарки

Воспроизводимые бенчмарки против coturn лежат в репозитории, в bench/.

Конкретных цифр здесь нет намеренно: пока прогон не выполнен с фиксированной методикой, указанной версией coturn и описанным железом, публиковать числа означает выдавать за измерение то, что им не является.