Security in Slyber SFU Server is divided into three independent layers. The first layer verifies client permissions upon joining a room (via JWT, Redis, or HMAC Secret). The second layer protects internal administrative gateways and telemetry using a dedicated NODE_SECRET key. The third layer provides end-to-end media packet encryption according to the RFC 9605 SFrame standard and enforces per-participant incoming bitrate limits.
Three Client Authentication Modes (AUTH_MODE)
The client token verification mode is configured via the AUTH_MODE environment variable or the -auth-mode CLI flag (startup parameter values are listed in Docker Deployment and Environment Variables). Across all modes, signatures and secrets are verified in constant time using SHA256 hashing and subtle.ConstantTimeCompare, completely eliminating timing side-channel attacks.
1. JWT Mode (default)
In jwt mode, the server validates HS256 tokens signed with the JWT_SECRET key. The token payload must conform to the TokenClaims structure.
{
"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"]
}
}
The exp field (expiration time as a Unix timestamp) is strictly mandatory. Tokens with a missing or zero exp field are automatically rejected by the server. The room_id field binds the token to a specific room (or accepts * to grant access to any room). The nested caps object allows fine-grained control over participant permissions—for example, issuing a view-only token to a webinar attendee with can_publish set to false (with such a token, the server blocks any attempt to send an SDP offer containing a=sendonly or a=sendrecv attributes).
2. Redis Mode (Dynamic Sessions with Instant Revocation)
In redis mode, the server uses a built-in pool of persistent TCP connections to your Redis database and looks up keys formatted as slyber:session:<TOKEN>. Before querying Redis, the token is checked to ensure it contains no spaces or newline characters to protect the RESP protocol against injection. The value stored in Redis can be either a plain string containing the participant ID (granting full default permissions) or a complete JSON string matching the TokenClaims structure. Deleting the key from Redis immediately revokes the user's access.
3. Secret Mode (Temporary HMAC-SHA1 Tokens)
In secret mode, tokens are generated statelessly without querying a database using the format <EXPIRES_UNIX>:<PARTICIPANT_ID>:<BASE64_HMAC_SHA1>, where the signature is computed over <EXPIRES_UNIX>:<PARTICIPANT_ID> using the TURN_SECRET key.
External TURN Servers and Test Token Generator
Slyber SFU Server does not embed a heavy TURN relay, instead operating alongside external relay servers (such as a dedicated Slyber TURN Server node). When EXTERNAL_TURN_URLS and TURN_SECRET are configured, every time a participant joins a room (as well as in HTTP Link headers on WHIP and WHEP responses), the server automatically generates temporary credentials following the TURN REST API specification (a username formatted as timestamp:participant_id and an HMAC-SHA1 password).
To quickly generate ready-to-use tokens from your backend, the server exposes the protected endpoint GET /auth/token?room=<ROOM_ID>&user=<USER_ID>. Requests require the X-Slyber-Node-Secret header and return a JSON payload containing a ready-to-use jwt_token, turn_hmac_token, and ice_servers array. Note also that forcibly tearing down an entire room and disconnecting all participants via a leave signaling message with track_id set to * is permitted exclusively for administrative tokens with sub equal to node-admin.
Flood Protection and Bitrate Limiting (TrafficPolice)
Every incoming RTP packet passes through the non-blocking TrafficPolice rate limiter built on atomic AtomicTokenBucket algorithms. The server enforces two limits in parallel:
- A per-track bitrate limit keyed by SSRC (
MAX_KBPS_PER_TRACK). - An aggregate bitrate limit across all streams belonging to a single participant session (
MAX_KBPS_PER_SESSION).
If a participant exceeds their allowed bandwidth, excess packets are dropped before entering the room, and the drop count is recorded in the ratelimit_drops metric. The token bucket table is capped at 16,384 entries with automatic eviction of inactive entries older than 60 seconds.
SFrame E2EE End-to-End Encryption and MLS Key Rotation
When RequireE2EE is enabled for a room (either globally via REQUIRE_E2EE=true or via the require_e2ee field inside a participant's token), the server switches to zero-trust mode and blocks any unencrypted media packets (excluding internal packets originating from the trusted ProtoAIPipe AI gateway).
The TrackE2EEValidator enforces production-grade validation of RFC 9605 SFrame packets without decrypting the media payload itself:
- Blocked until key registration. Immediately after a track is published, its allowed key list is empty, and all packets are rejected until the publisher registers an active
KeyID. - Seamless MLS key rotation (
e2ee_key_ratchet). The publisher sends ane2ee_key_ratchetsignaling message containing its list ofssrcs, the newe2ee_key_id, and an optionalmls_key_packagepayload (up to 16 KB). The server verifies that the specified SSRCs belong to that participant, increments the room'se2ee_epoch, and broadcasts the new key to other participants. Up to 16 active keys with independent counters are maintained per track, ensuring uninterrupted streaming when rotating to a newKeyIDwith a reset counter (Counter = 0). - Fragmentation support and anti-replay protection. The starting packet of a frame must carry a valid SFrame header and at least 16 bytes of GCM authentication tag, while continuation fragments of the same frame (sharing the same RTP Timestamp, up to 256 fragments per frame) are admitted via a validated-frame cache. Duplicate and replayed packets are rejected using a 512-packet RTP sequence sliding bitmap window and a 64-bit SFrame counter window.
- Layer routing via RFC 9626 Frame Marking. Because the video payload is end-to-end encrypted, the server reads the
IsKeyFrameflag as well as spatial and temporal layer indices from the unencryptedurn:ietf:params:rtp-hdrext:framemarkingRTP header extension (supporting both0xBEDEand0x1000profiles).