Безопасность в Slyber SFU Server разделена на три независимых контура. Первый контур проверяет права клиентов при входе в комнату (через JWT, Redis или HMAC Secret). Второй контур защищает внутренние административные шлюзы и телеметрию с помощью выделенного ключа NODE_SECRET. Третий контур обеспечивает сквозное шифрование медиапакетов по стандарту RFC 9605 SFrame и ограничивает входящий битрейт каждого участника.
Три режима аутентификации клиентов (AUTH_MODE)
Выбор режима проверки клиентских токенов задается переменной окружения AUTH_MODE или флагом -auth-mode (значения параметров запуска приведены в статье Запуск в Docker и переменные окружения). Во всех режимах сверка подписей и секретов выполняется за константное время через хеширование SHA256 и функцию subtle.ConstantTimeCompare, что полностью исключает атаки по времени отклика.
1. Режим JWT (по умолчанию)
В режиме jwt сервер проверяет токены стандарта HS256, подписанные секретным ключом JWT_SECRET. Полезная нагрузка токена должна соответствовать структуре TokenClaims.
{
"sub": "user-101",
"room_id": "conference-alpha",
"profile": "conference",
"iat": 1763090000,
"exp": 1763093600,
"require_e2ee": false,
"caps": {
"can_publish": true,
"can_subscribe": true,
"can_use_data": true,
"max_spatial_layer": 2,
"max_bitrate_kbps": 3500,
"allowed_transports": ["udp", "tcp", "turn"]
}
}
Поле exp (время истечения срока действия в формате Unix timestamp) является строго обязательным. Токены с пустым или нулевым полем exp автоматически отвергаются сервером. Поле room_id привязывает токен к конкретной комнате (либо принимает значение * для доступа к любой комнате). Вложенный объект caps позволяет тонко ограничить права участника, например выдать зрителю вебинара токен только на просмотр с флагом can_publish в значении false (при таком токене сервер заблокирует любую попытку отправить SDP оффер с атрибутами a=sendonly или a=sendrecv).
2. Режим Redis (динамические сессии с мгновенным отзывом)
В режиме redis сервер использует встроенный пул постоянных TCP соединений к вашей базе Redis и ищет ключ вида slyber:session:<TOKEN>. Перед отправкой запроса токен проверяется на отсутствие пробелов и символов перевода строки для защиты протокола RESP от инъекций. Значением ключа в Redis может быть как простая строка с идентификатором участника (тогда ему выдаются полные права по умолчанию), так и полная JSON строка со структурой TokenClaims. Удаление ключа из Redis позволяет мгновенно отозвать доступ пользователя.
3. Режим Secret (временные HMAC SHA1 токены)
В режиме secret токен формируется без обращения к базе данных по формуле <EXPIRES_UNIX>:<PARTICIPANT_ID>:<BASE64_HMAC_SHA1>, где подпись вычисляется от строки <EXPIRES_UNIX>:<PARTICIPANT_ID> с использованием ключа TURN_SECRET.
Внешние серверы TURN и генератор тестовых токенов
Slyber SFU Server не включает внутрь себя тяжелый TURN релей, а работает в связке с внешними серверами (например с выделенным узлом Slyber TURN Server). Если в конфигурации заданы переменные EXTERNAL_TURN_URLS и TURN_SECRET, то при каждом входе участника в комнату (а также в HTTP заголовках Link при запросах WHIP и WHEP) сервер автоматически генерирует временные учетные данные по спецификации TURN REST API (логин вида timestamp:participant_id и пароль HMAC SHA1).
Для быстрой генерации готовых токенов со стороны вашего бэкенда предусмотрен защищенный эндпоинт GET /auth/token?room=<ROOM_ID>&user=<USER_ID>. Запрос к нему требует заголовок X-Slyber-Node-Secret и возвращает JSON с готовым jwt_token, turn_hmac_token и массивом ice_servers. Также обратите внимание, что полное принудительное закрытие комнаты со всеми участниками через сигнальное сообщение leave с полем track_id равным * разрешено исключительно административному токену с идентификатором sub равным node-admin.
Защита от флуда и ограничение битрейта (TrafficPolice)
Каждый входящий RTP пакет проходит через неблокирующий ограничитель скорости TrafficPolice, построенный на атомарных алгоритмах AtomicTokenBucket. Сервер параллельно контролирует два лимита.
- Лимит на отдельный медиапоток по его SSRC (
MAX_KBPS_PER_TRACK). - Суммарный лимит на все потоки одного участника по его сессии (
MAX_KBPS_PER_SESSION).
Если участник превышает разрешенную полосу пропускания, лишние пакеты отбрасываются до попадания в комнату, а счетчик отброшенных пакетов фиксируется в метрике ratelimit_drops. Таблица бакетов ограничена 16384 записями с автоматической очисткой неактивных записей старше 60 секунд.
Сквозное шифрование SFrame E2EE и ротация ключей MLS
Когда для комнаты включен флаг RequireE2EE (через глобальную настройку REQUIRE_E2EE=true или через поле require_e2ee внутри токена участника), сервер переходит в режим нулевого доверия и блокирует любые незашифрованные медиапакеты (за исключением внутренних пакетов от доверенного ИИ шлюза ProtoAIPipe).
Валидатор TrackE2EEValidator обеспечивает промышленную проверку пакетов RFC 9605 SFrame без расшифровки самого медиаконтента.
- Блокировка до регистрации ключа. Сразу после публикации трека список разрешенных ключей пуст, и любые пакеты отвергаются до тех пор, пока издатель не зарегистрирует активный
KeyID. - Бесшовная ротация ключей MLS (
e2ee_key_ratchet). Издатель отправляет сигнальное сообщениеe2ee_key_ratchetсо списком своихssrcs, новым идентификаторомe2ee_key_idи опциональным пакетомmls_key_package(размером до 16 КБ). Сервер проверяет, что указанные SSRC действительно принадлежат этому участнику, увеличивает номер эпохи комнатыe2ee_epochи рассылает новый ключ остальным участникам. Для каждого трека хранится до 16 активных ключей с независимыми счетчиками, поэтому при смене ключа на новыйKeyIDсо сброшенным счетчикомCounter = 0поток не прерывается. - Поддержка фрагментации и анти реплей. Стартовый пакет кадра обязан содержать валидный заголовок SFrame и минимум 16 байт криптографического тега GCM, а последующие фрагменты того же кадра (с тем же RTP Timestamp, до 256 фрагментов на кадр) пропускаются по кешу проверенных кадров. Дубликаты и повторно отправленные пакеты отсекаются скользящим битовым окном на 512 RTP номеров и 64-битным окном счетчиков SFrame.
- Маршрутизация слоев по RFC 9626 Frame Marking. Поскольку полезная нагрузка видео зашифрована сквозным ключом, сервер считывает признак ключевого кадра
IsKeyFrame, а также индексы пространственного и временного слоев из открытого RTP расширенияurn:ietf:params:rtp-hdrext:framemarking(поддерживаются профили0xBEDEи0x1000).