Comment les clients établissent des real-time media connections dans Bedrud. Couvre la full connectivity stack : signaling, ICE, STUN, TURN, et le SFU media path.
Overview
WebRTC nécessite une série de steps avant que l’audio et la vidéo ne flow entre le client et le serveur. Bedrud utilise LiveKit’s SFU (Selective Forwarding Unit) architecture - les clients connectent au serveur, pas les uns aux autres. Cela signifie que seul le client-to-server network path matters, pas la connection entre les individual participants.
sequenceDiagram
participant C as Client
participant S as Bedrud Server
participant LK as LiveKit SFU
C->>S: POST /api/room/join
S->>S: Validate permissions
S->>C: LiveKit JWT token
C->>LK: WebSocket connect (with token)
LK->>C: Join response + SDP offer
Note over C,LK: ICE Candidate Gathering
C->>LK: Host candidates (local IPs)
C->>LK: STUN candidates (public IPs)
C->>LK: TURN candidates (relay addresses)
alt Direct path available
Note over C,LK: ICE/UDP - direct media
C-->>LK: Media via UDP 50000-60000
else UDP blocked, TURN available
Note over C,LK: TURN - relayed media
C-->>LK: Media via TURN relay (3478/5349)
else Corporate firewall
Note over C,LK: TURN/TLS - relayed via 443
C-->>LK: Media via TLS tunnel
end
Note over C,LK: Audio/video tracks flow through SFUConnectivity Stack
Cinq layers travaillent ensemble pour établir le media path :
flowchart TB
subgraph Layers["Connectivity Stack"]
direction TB
SIG["1. Signaling<br/>WebSocket - exchange SDP offers/answers"]
ICE["2. ICE<br/>Orchestrate all candidate paths"]
STUN["3. STUN<br/>Discover public IP/port"]
TURN["4. TURN<br/>Relay when direct fails"]
SFU["5. SFU<br/>Route media between participants"]
end
SIG --> ICE
ICE --> STUN
ICE --> TURN
STUN --> SFU
TURN --> SFULayer Details
1. Signaling - Le client et le serveur exchange connection metadata en utilisant SDP (Session Description Protocol) offers et answers via WebSocket. Ce n’est pas du media - c’est le setup phase. Bedrud proxies signaling à travers le API server vers l’embedded LiveKit instance.
2. ICE (Interactive Connectivity Establishment) - Gathers tous les possible connection paths, appelés candidates, et les tests en order de priority. ICE est un framework - il coordonne les connection attempts mais n’est pas un protocol lui-même.
3. STUN (Session Traversal Utilities for NAT) - Lightweight protocol. Le client envoie un binding request au STUN server, qui répond avec le client’s public IP et port. Ce “server reflexive” candidate est ensuite testé pour direct connectivity. Works pour ~80% des connections.
4. TURN (Traversal Using Relays around NAT) - Quand la direct connectivity échoue, TURN alloue un relay address sur le serveur. Tous les media packets sont forwarded à travers ce relay. Highest cost - le server bandwidth scales avec les relayed users. Voir le TURN Server Guide pour deep coverage.
5. SFU (Selective Forwarding Unit) - Une fois le transport path établi, LiveKit’s SFU routes media entre les participants. Chaque participant envoie un stream up ; le SFU forwards copies aux autres participants. Ce n’est pas peer-to-peer - le serveur est toujours dans le path.
ICE Candidate Gathering
flowchart TD
START[Start ICE Gathering] --> HOST
START --> SRFLX
START --> TURN_C
HOST["Host candidates<br/>Local interface IPs<br/>e.g. 192.168.1.5:50001"]
SRFLX["STUN candidates (srflx)<br/>Public IP discovered via STUN<br/>e.g. 203.0.113.5:50001"]
TURN_C["TURN candidates (relay)<br/>Relay address on server<br/>e.g. 203.0.113.10:30001"]
HOST --> TEST
SRFLX --> TEST
TURN_C --> TEST
TEST{Test candidate<br/>connectivity}
TEST -->|"Host works"| CONNECTED[Connected via host]
TEST -->|"srflx works"| CONNECTED2[Connected via STUN<br/>direct P2P]
TEST -->|"Only relay works"| CONNECTED3[Connected via TURN relay]
TEST -->|"None work"| FAIL[Connection failed]ICE gathers trois candidate types simultanément :
| Type | Source | Priority | Comment cela fonctionne |
|---|---|---|---|
| host | Local network interfaces | Highest | Direct IP depuis machine. Works sur LAN. |
| srflx (server reflexive) | STUN server response | Medium | Public IP discovered via STUN. Works pour la plupart des NAT types. |
| relay | TURN server allocation | Lowest | Address sur TURN server. Always works. Highest cost. |
ICE teste tous les candidates et sélectionne le highest-priority pair qui succeeds. Si srflx works, il skips relay.
NAT Types & Connectivity
Différents NAT types affectent si la direct connectivity works :
flowchart LR
subgraph NAT1["Client A NAT"]
direction TB
F["Full Cone"]
R["Restricted Cone"]
PR["Port Restricted"]
S["Symmetric"]
end
subgraph NAT2["Client B / Server NAT"]
direction TB
F2["Full Cone"]
R2["Restricted Cone"]
PR2["Port Restricted"]
S2["Symmetric"]
end
F -->|"Direct"| F2
R -->|"Direct"| R2
PR -->|"Direct"| PR2
S -->|"TURN required"| S2
S -.->|"TURN required"| PR2
PR -.->|"TURN required"| S2
| NAT Type | Description | Direct P2P | Needs TURN |
|---|---|---|---|
| Full Cone | Tous les requests depuis la même internal IP/port map vers la même public IP/port. N’importe quel external host peut lui envoyer. | Yes | No |
| Restricted Cone | Même mapping que Full Cone, mais seuls les external hosts qui ont reçu un packet peuvent send back. | Usually | No |
| Port Restricted Cone | Similaire à Restricted Cone, mais le NAT restreint également le external port number. Most common home router type. | Usually | Rarely |
| Symmetric | Différent public IP/port mapping par destination. Le STUN-discovered address ne peut pas être réutilisé. | No (quand les deux sont symmetric) | Yes |
Key insight : Puisque le serveur a une public IP et predictable port range, la plupart des NAT types work directement. TURN est principalement nécessaire quand le client’s firewall blocks outbound UDP entièrement.
Configuration Summary
Quelles Bedrud/LiveKit config keys affectent la WebRTC connectivity :
livekit.yaml keys :
rtc:
port_range_start: 50000 # UDP media port range start
port_range_end: 60000 # UDP media port range end
tcp_port: 7881 # ICE/TCP fallback port
stun_servers: # External STUN servers (optional)
- stun:stun.l.google.com:19302
use_external_ip: true # Advertise public IP dans ICE candidates
turn:
enabled: true # Enable embedded TURN
domain: "turn.example.com" # TURN domain (DNS doit résoudre)
udp_port: 3478 # TURN/UDP + STUN port
tls_port: 5349 # TURN/TLS port (ou 443)
cert_file: /path/to/turn.crt # TLS cert pour TURN/TLS
key_file: /path/to/turn.key # TLS key pour TURN/TLS
relay_range_start: 30000 # Relay port range start
relay_range_end: 40000 # Relay port range end
external_tls: false # L4 LB terminates TLSconfig.yaml keys (Bedrud server) :
server:
port: 8090 # API port (signaling proxied à travers ceci)
enableTLS: true # HTTPS pour signaling
domain: "meet.example.com" # Public domainDebugging Connectivity Issues
| Symptom | Check |
|---|---|
| Can’t connect at all | rtc.use_external_ip: true ? Firewall open sur 443 + UDP range ? |
| Connects mais no audio/video | UDP 50000-60000 blocked ? Check ICE candidates dans browser. |
| Slow connection | TURN relay active (check candidates). Expected si le client derrière strict NAT. |
| Fails derrière corporate network | TURN/TLS not configured. Set turn.tls_port: 443 avec valid cert. |
| Works sur LAN, fails remotely | Public IP not advertised. Set rtc.use_external_ip: true. |
Pour deep TURN troubleshooting, voir le TURN Server Guide.
See also
- TURN Server Guide - TURN architecture, configuration, TLS, debugging
- LiveKit Integration - comment Bedrud embeds LiveKit
- Architecture Overview - full system architecture
- Internal TLS - TLS pour isolated networks