Архитектура Slyber TURN Server

• мин чтения
Архитектура Slyber TURN Server

Написать базовый STUN и TURN сервер на Go с использованием библиотеки pion/turn/v4 можно за один вечер в сотню строк кода. Но как только такой прототип попадает на боевой сервер с сотнями одновременных медиапотоков, вскрываются системные проблемы очередь одного UDP сокета упирается в блокировки ядра Linux, мобильные клиенты при смене сети забивают пул портов мертвыми аллокациями, а открытый релей становится мишенью для сканирования внутренней облачной сети.

В прошлой статье про альтернативу Coturn на Linux я разбирал операционные проблемы ручной настройки конфигурационных файлов и причину перехода на единый исполняемый файл. Ниже подробно разберем внутреннее устройство Slyber TURN Server и технические решения, которые позволили выжать максимум из сетевого стека Linux внутри одного статического бинарника.

Обход узкого горлышка одного UDP сокета через SO_REUSEPORT и тюнинг буферов ядра

В стандартной реализации сетевого сервера приложение открывает один UDP сокет на порту 3478 и читает из него пакеты в цикле. Под высокой нагрузкой в WebRTC трафике, где идут тысячи мелких аудио и видео пакетов в секунду на каждую сессию, единый сокет становится главной точкой деградации. Ядро Linux тратит процессорное время на блокировки очереди приема одного файлового дескриптора, пока соседние ядра процессора простаивают.

В slyber_turn сетевой уровень изначально спроектирован под многоядерную обработку:

  1. Масштабирование листенеров по числу ядер. При старте сервер считывает количество доступных ядер процессора TURN_THREADS=NumCPU и поднимает независимые UDP сокеты на одном и том же порту с системным флагом SO_REUSEPORT. Распределение входящих датаграмм по потокам берет на себя сетевой стек ядра Linux без конкуренции за блокировки в пространстве пользователя.
  2. Автоматическое расширение сокетных буферов до 8 МБ. Дефолтный лимит net.core.rmem_max и net.core.wmem_max в 208 КБ переполняется при первом же всплеске битрейта от видеокамер. Установочный скрипт и сам сервер поднимают системные буферы чтения и записи до 8 МБ, полностью исключая тихие потери пакетов на уровне сетевой карты и ядра.
  3. Генерация сертификатов в памяти. Для шифрованного транспорта не требуется возиться с файлами ключей на диске: сервер на лету генерирует в оперативной памяти сертификат на базе кривой ECDSA P-256.

Атомарный шейпинг трафика и очистка сокетов при переходе с WiFi на LTE

Вторая проблема боевой эксплуатации связана с контролем ресурсов. Пул релейных портов от 49152 до 65535 вмещает 16384 одновременных сессии. В реальных условиях этот пул быстро деградирует по двум причинам: бесконтрольное потребление полосы пропускания отдельными пирами и зависшие мобильные соединения.

Когда пользователь смартфона выходит из зоны домашнего роутера и переключается с WiFi на мобильную сеть 4G или LTE, его IP адрес мгновенно меняется. Клиентское приложение запрашивает новую аллокацию на TURN сервере, но старый релейный сокет продолжает висеть в памяти до истечения стандартного многоминутного времени жизни. Если таких переключений тысячи, сервер исчерпывает лимит портов.

В slyber_turn эта задача решена через привязку аллокаций к идентификатору пользователя:

  • При запросе ключей через встроенный эндпоинт /api/turn-credentials?user_id=user_42 идентификатор зашивается в структуру сессии.
  • Как только тот же user_id поднимает новую активную сессию с другого сетевого интерфейса, старые неактивные сокеты этого пользователя принудительно очищаются и возвращаются в пул через 5 секунд.
  • Для защиты канала от перегрузки на каждую сессию навешивается неблокирующий ограничитель скорости MAX_KBPS_PER_SESSION, построенный по алгоритму Token Bucket на атомарных операциях sync/atomic без использования мьютексов.
Сетевой механизмРеализация в Slyber TURN ServerЭффект в продакшене
Прием UDP трафикаПул сокетов с флагом SO_REUSEPORTРавномерная загрузка всех ядер CPU
Буферы сокетов ядраАвтоматический тюнинг до 8 МБОтсутствие потерь при пиках видео
Шейпинг полосыАтомарный Token Bucket без мьютексовСтабильная задержка без блокировок потоков
Смена сети WiFi и LTEГруппировка по user_id и сброс за 5 сЗащита пула из 16384 портов от утечек

Фильтрация SSRF атак в облаках с сохранением поддержки TURN Hairpinning

Поскольку TURN сервер пересылает трафик от имени своего сетевого интерфейса, любая ошибка в фильтрации адресов назначения превращает его в открытый прокси внутрь вашей серверной инфраструктуры. Через команды CreatePermission и ChannelBind злоумышленник может попытаться прочитать метаданные облачного провайдера или просканировать соседние сервисы в локальной сети.

В slyber_turn фильтр безопасности работает на уровне ядра релея до отправки первого пакета и включен по умолчанию без настройки внешних списков доступа:

  • Жёстко блокируются обращения к облачным метаданным IPv4 169.254.0.0/16 и IPv6 fd00:ec2::254/128, петлевым интерфейсам loopback и всем приватным диапазонам локальных подсетей.
  • Автоматически отсекается сетевой шум, когда браузеры по ошибке пытаются пробросить через TURN свои внутренние локальные кандидаты.
  • При всей строгости фильтра полностью сохранена поддержка TURN Hairpinning. Если два клиента за строгими симметричными NAT подключены к одному и тому же узлу slyber_turn, сервер корректно распознает свой собственный внешний IP на релейных портах и замыкает маршрут между пирами внутри памяти без выхода в локальную подсеть.

Методика нагрузочного тестирования через встроенный slyber_turn bench

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

Чтобы проверять сервер в боевых условиях без установки сторонних пакетов на клиенте, я встроил два инструмента прямо в основной бинарный файл: slyber_turn doctor для быстрой диагностики после старта и slyber_turn bench для нагрузочного тестирования.

При запуске sudo slyber_turn doctor утилита проверяет конфигурацию, валидирует защиту HTTP API, сверяет внешний IP через STUN и проводит живую аллокацию релейного порта:

Plaintext

Code
[OK] Configuration valid (realm: turn.example.com, relay port pool: 49152-65535, capacity: 16384 sessions)
[OK] HTTP API protection active (origins: 1, require_secret: false)
[OK] STUN check passed in 12ms: PUBLIC_IP (203.0.113.50) matches external IP
[OK] HTTP API (:8080/healthz) responded normally (200 OK)
[OK] TURN Allocate succeeded in 390µs (allocated relay address: 203.0.113.50:50124)

Полный цикл выделения релейного адреса занимает 390µs. Когда нужно проверить поведение сервера под конкурентной нагрузкой, запускается встроенный генератор трафика:

Bash

Bash
sudo slyber_turn bench -clients 20 -duration 5s

Команда поднимает 20 одновременных клиентских сессий, проходит реальную процедуру получения токенов и аллокации портов, гонит поток медиапакетов через релей и на выходе считает круговую задержку RTT, процент потерь и сетевой джиттер строго по формуле стандарта RFC 3550. Это дает точный ответ, сколько реальных звонков выдержит конкретная виртуальная машина еще до пуска живого трафика.

Наблюдаемость в продакшене и переход к групповой маршрутизации

Для постоянного контроля узла в slyber_turn встроены три механизма телеметрии, которые не требуют подключения внешних баз данных:

  1. Эндпоинт /metrics отдает метрики в формате Prometheus для построения графиков в Grafana.
  2. Запрос к /api/node-stats возвращает агрегированную статистику за последние 24 часа, текущую утилизацию пула портов и список Top Offenders с клиентами, которые создают аномальную нагрузку или чаще других получают отказы фильтра безопасности.
  3. Все критические системные события и срабатывания защиты записываются на диск в структурированный лог /opt/slyber_turn/events.jsonl, который сохраняется даже при переустановке бинарника.

Установить сервер одной командой и посмотреть полную документацию по API можно на странице проекта Slyber TURN Server.

Нужна высоконагруженная архитектура или индивидуальное инженерное решение?

Я проектирую и создаю отказоустойчивые Go-бэкенды, системы WebRTC-стриминга в реальном времени, кастомные протоколы и fullstack-приложения. Давайте обсудим ваши технические задачи и архитектуру.

Читайте также

Почему я отказался от древнего Coturn для своего TURN сервера

Когда запускаешь WebRTC проект в локальной сети или тестируешь звонки между двумя домашними роутерами, прямое соединение через STUN работает идеально. Проблемы начинаются в продакшене. Около 15 или 20 процентов пользователей находятся за NAT, операторским CGNAT у мобильных провайдеров или жесткими корпоративными файрволами. Без надежного сервера посредника (TURN) такие клиенты видят бесконечный экран подключения и уходят.

Все что нужно знать про IPv4, IPv6, Dual Stack, DNS64 и NAT64

Понятный разбор сетевых технологий для веб разработчиков без сложной теории. Разбираем с самого нуля, чем отличаются белые и серые адреса, как работают механизмы Dual Stack, DNS64, NAT64 и 464XLAT в мобильных сетях, почему Cloudflare выдает ошибку при добавлении адреса IPv6 из Hetzner и как правильно настроить базу данных, лимиты запросов и файрвол на сервере.