Bedrud Документация

Bedrud встраивает TURN-сервер через LiveKit для ретрансляции медиа клиентам за ограничительными NAT или файрволами. Эта страница описывает архитектуру, конфигурацию и устранение неполадок.


Что такое TURN

TURN (Traversal Using Relays around NAT) - это протокол, который пересылает медиапакеты через сервер, когда две конечные точки не могут соединиться напрямую.

Связанные протоколы:

ПротоколРольНагрузка
STUNОбнаружение публичного IP/порта. Лёгкий.Отсутствует (сервер видит только небольшие binding-запросы)
ICEФреймворк, который проверяет все варианты подключения в порядке приоритета.Отсутствует (только координация)
TURNРетрансляция всех медиаданных, когда прямой маршрут не работает. Последнее средство.Высокая (пропускная способность сервера = все ретранслируемые медиа)

См. Подключение WebRTC для полного стека подключения.


TURN в Bedrud

LiveKit включает встроенный TURN-сервер. Внешняя инфраструктура не требуется.

Архитектура ретрансляции

flowchart LR
    subgraph Client["Client"]
        A[WebRTC Peer]
    end
 
    subgraph NAT["NAT / Firewall"]
        direction TB
        N{Direct P2P<br/>possible?}
    end
 
    subgraph Server["Bedrud Server"]
        STUN[STUN Server<br/>port 3478]
        TURN[TURN Relay<br/>port 3478 UDP<br/>port 5349 TLS]
        SFU[LiveKit SFU]
    end
 
    A -->|"ICE candidates"| N
    N -->|"Yes"| SFU
    N -->|"No"| TURN
    TURN -->|"relayed media"| SFU
    A -.->|"discover public IP"| STUN

Приоритет подключений

LiveKit проверяет типы подключений по порядку. Каждый откат добавляет задержку и нагрузку на сервер:

flowchart TD
    A[ICE over UDP<br/>port 50000-60000] -->|"~80% succeed"| S[Connected]
    A -->|"fail"| B[TURN over UDP<br/>port 3478]
    B -->|"succeed"| S
    B -->|"UDP blocked"| C[ICE over TCP<br/>port 7881]
    C -->|"succeed"| S
    C -->|"TCP blocked"| D[TURN over TLS<br/>port 5349 / 443]
    D -->|"succeed"| S
    D -->|"fail"| E[Connection failed]
ПриоритетТипПортТипичный сценарий
1ICE/UDP (прямое)50000-60000Большинство соединений. Без ретрансляции.
2TURN/UDP3478Симметричный NAT, P2P заблокирован.
3ICE/TCP7881UDP заблокирован (VPN, некоторые файрволы).
4TURN/TLS5349 или 443Корпоративный файрвол, разрешён только исходящий HTTPS.

Когда активируется TURN

TURN активируется, когда прямой маршрут передачи медиа не работает. Типичные причины:

  • Симметричный NAT у обоих участников - И у клиента, и у сервера симметричный NAT. NAT назначает разные публичные порты для каждого направления, поэтому адрес, обнаруженный через STUN, становится недоступным.
  • Корпоративный файрвол - блокирует весь исходящий UDP. Разрешён только TCP-порт 443.
  • Ограничения VPN - некоторые VPN перехватывают или блокируют трафик WebRTC.
  • Облачные ВМ без публичного IP - некоторые облачные провайдеры используют NAT, нарушающий прямое ICE.

Большинство пользователей (~80%) никогда не используют TURN. Прямой UDP-маршрут работает.

Нагрузка на канал

Когда TURN ретранслирует, сервер передаёт все медиаданные для этого участника. Приблизительная пропускная способность на поток:

Тип потокаБитрейтНа одного ретранслируемого участника
Аудио (Opus)~32 Кбит/с~32 Кбит/с
Видео 720p (VP8)~1.5 Мбит/с~1.5 Мбит/с входящий + 1.5 Мбит/с исходящий на каждую подписанную дорожку
Демонстрация экрана 1080p~2.5 Мбит/с~2.5 Мбит/с

Для 5—person конференции с одним ретранслируемым участником: сервер обрабатывает ~1.5 Мбит/с дополнительно для ретрансляции видео этого участника. Умножьте эти значения на количество ретранслируемых участников для оценки общей пропускной способности сервера.


Конфигурация

Файл: server/config/livekit.yaml (разработка) или /etc/bedrud/livekit.yaml (продакшен)

turn:
  enabled: true
  domain: "turn.example.com"
  udp_port: 3478
  tls_port: 5349
  cert_file: /etc/bedrud/turn.crt
  key_file: /etc/bedrud/turn.key
  relay_range_start: 30000
  relay_range_end: 40000
  external_tls: false

Справочник ключей

КлючПо умолчаниюОписание
enabledtrueВключить встроенный TURN-сервер.
domainlocalhostДомен, анонсируемый клиентам. Должен разрешаться в публичный IP сервера.
udp_port3478Порт TURN/UDP. Также обслуживает STUN binding-запросы, когда TURN включён.
tls_port5349Порт TURN/TLS. Установите 443, если нет балансировщика нагрузки, терминирующего TLS.
cert_file-TLS-сертификат для TURN/TLS. Необходим при наличии клиентов TURN/TLS.
key_file-TLS-приватный ключ, соответствующий cert_file.
relay_range_start30000Начало диапазона UDP-портов для ретранслируемых медиапакетов.
relay_range_end40000Конец диапазона портов ретрансляции. Каждый ретранслируемый участник использует порты из этого диапазона.
external_tlsfalseУстановите true, когда балансировщик нагрузки уровня 4 терминирует TURN/TLS. LiveKit пропускает собственный TLS на порту TURN.

Взаимодействие с use_external_ip

В том же файле livekit.yaml, в секции rtc::

rtc:
  use_external_ip: true

Должно быть true для корректной работы TURN. При значении false ICE-кандидаты содержат внутренние (приватные) IP-адреса, недоступные клиентам из интернета.


Настройка TLS в продакшене

TURN/TLS требует собственный TLS-сертификат. Два подхода:

Единый домен (без балансировщика нагрузки)

Используйте TLS-сертификат сервера повторно. Установите tls_port на 443:

turn:
  enabled: true
  domain: "meet.example.com"
  tls_port: 443
  cert_file: /etc/bedrud/meet.example.com.crt
  key_file: /etc/bedrud/meet.example.com.key

Домен TURN и домен сервера совпадают. Порт 443 обслуживает и HTTPS API, и TURN/TLS - LiveKit различает их по протоколу.

Выделенный домен TURN (с балансировщиком нагрузки)

flowchart LR
    C[Client] --> LB[Layer 4<br/>Load Balancer]
    LB -->|"HTTPS :443"| API[Bedrud API<br/>:8090]
    LB -->|"TURN/TLS :5349"| LK1[LiveKit Node 1<br/>:7880]
    LB -->|"TURN/TLS :5349"| LK2[LiveKit Node 2<br/>:7880]
 
    C -.->|"TURN/UDP :3478"| LK1
turn:
  enabled: true
  domain: "turn.example.com"
  tls_port: 5349
  external_tls: true

Балансировщик нагрузки терминирует TLS. external_tls: true указывает LiveKit ожидать уже расшифрованный трафик.


Справочник портов и файрвола

flowchart TB
    subgraph Internet["Internet"]
        C[Client]
    end
 
    subgraph FW["Firewall"]
        direction LR
        P443["443/TCP<br/>HTTPS + TURN/TLS"]
        P3478["3478/UDP<br/>TURN/UDP + STUN"]
        P7881["7881/TCP<br/>ICE/TCP"]
        P5349["5349/TCP<br/>TURN/TLS"]
        PRANGE["50000-60000/UDP<br/>RTC Media"]
    end
 
    subgraph Bedrud["Bedrud Server"]
        API[API Server]
        LK[LiveKit SFU]
    end
 
    C --> P443 --> API
    C --> P3478 --> LK
    C --> P7881 --> LK
    C --> P5349 --> LK
    C --> PRANGE --> LK
ПортПротоколСервисОбязателенПримечания
443TCPHTTPS + TURN/TLSДаAPI + веб-интерфейс. Также TURN/TLS, если tls_port: 443.
3478UDPTURN/UDP + STUNРекомендуетсяДвойное назначение: STUN binding + ретрансляция TURN.
5349TCPTURN/TLSЕсли нет LBВыделенный порт TURN/TLS. Пропустите, если используется порт 443.
7881TCPICE/TCPРекомендуетсяЗапасной вариант при заблокированном UDP без необходимости TLS.
50000-60000UDPRTC-медиаДаПорты ICE-кандидатов. Каждый участник использует 2 порта.
7880TCPLiveKit APIВнутреннийСигнализация WebSocket. Не открывается напрямую в продакшене.

Минимальные правила файрвола

Для базовой связности:

Allow TCP 443    (HTTPS + TURN/TLS)
Allow UDP 3478   (TURN/UDP + STUN)
Allow UDP 50000-60000  (RTC media)

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

Also allow TCP 7881  (ICE/TCP)
Also allow TCP 5349  (TURN/TLS, if not using port 443)

Тестирование и отладка

Браузер: chrome://webrtc-internals

  1. Откройте chrome://webrtc-internals в Chrome/Edge перед подключением к конференции.
  2. Создайте дамп.
  3. Найдите ICE candidate pairs на вкладке Stats.
  4. Типы кандидатов показывают маршрут соединения:
Тип кандидатаЗначение
hostЛокальный IP. Прямой интерфейс.
srflx (server reflexive)Публичный IP, обнаруженный через STUN. Прямое P2P работает.
relayРетрансляция TURN активна. Медиа проходит через сервер.

Если вы видите кандидатов relay как активную пару, TURN обрабатывает это соединение.

События LiveKit Client SDK

Все SDK LiveKit генерируют события состояния соединения:

room.on(RoomEvent.Connected, () => {
  console.log("Connected");
});
 
room.on(RoomEvent.Reconnecting, () => {
  console.log("Connection lost, reconnecting...");
});

Проверяйте room.localParticipant.connectionQuality для статистики соединения.

Логи сервера LiveKit

Увеличьте уровень логирования для отладки в livekit.yaml:

logging:
  level: debug

Ищите записи логов, содержащие:

  • ICE - статус сбора кандидатов
  • TURN - события выделения ретрансляции
  • relay - активные ретрансляционные соединения

Ручное тестирование TURN с turnutils

Установите пакет coturn-utils, затем проверьте связность TURN:

turnutils_uclient -t -p 3478 -W devkey -u devkey turn.example.com
  • -t - использовать TCP
  • -p - порт TURN
  • Замените учётные данные на продакшен-значения

Успешный вывод покажет выделенные адреса ретрансляции.


Устранение неполадок

СимптомВероятная причинаРешение
Клиенты не могут подключиться, тайм-аутПорты TURN заблокированы файрволомОткройте UDP 3478, TCP 5349, UDP 50000-60000
TURN/TLS не работаетОтсутствует или несоответствующий TLS-сертификатПроверьте пути cert_file/key_file. Убедитесь, что сертификат соответствует domain.
TURN/TLS не работает с LBexternal_tls не установленУстановите external_tls: true в конфигурации.
Одностороннее аудио/видеоДиапазон портов ретрансляции заблокированОткройте UDP с relay_range_start до relay_range_end.
Высокая пропускная способность сервераМногие клиенты за NAT используют ретрансляциюОжидаемо. Масштабируйте сервер или уменьшите число ретранслируемых пользователей.
Кандидаты relay, хотя ожидаются srflxuse_external_ip: falseУстановите rtc.use_external_ip: true.
Домен TURN не разрешаетсяОшибка конфигурации DNSdig +short turn.example.com должен возвращать публичный IP сервера.
Клиенты за корпоративным файрволомРазрешён только порт 443Установите turn.tls_port: 443. Убедитесь, что сертификат валиден.
turn.enabled: true, но ретрансляции нетПрямой маршрут работает (это хорошо)TURN - запасной вариант. Нет ретрансляции = лучше. Проверьте через chrome://webrtc-internals.

Быстрый контрольный список диагностики

  1. dig +short <turn.domain> возвращает корректный публичный IP?
  2. Файрвол разрешает UDP 3478, TCP 5349, UDP 50000-60000?
  3. tls_port: 443 или 5349 соответствует правилам файрвола?
  4. cert_file и key_file существуют и доступны для чтения?
  5. CN/SAN сертификата соответствует turn.domain?
  6. Установлено rtc.use_external_ip: true?
  7. Логи LiveKit не содержат ошибок, связанных с TURN?

См. также