Bedrud Documentation

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 SFU

Connectivity 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 --> SFU

Layer 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 :

TypeSourcePriorityComment cela fonctionne
hostLocal network interfacesHighestDirect IP depuis machine. Works sur LAN.
srflx (server reflexive)STUN server responseMediumPublic IP discovered via STUN. Works pour la plupart des NAT types.
relayTURN server allocationLowestAddress 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 TypeDescriptionDirect P2PNeeds TURN
Full ConeTous 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.YesNo
Restricted ConeMême mapping que Full Cone, mais seuls les external hosts qui ont reçu un packet peuvent send back.UsuallyNo
Port Restricted ConeSimilaire à Restricted Cone, mais le NAT restreint également le external port number. Most common home router type.UsuallyRarely
SymmetricDiffé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 TLS

config.yaml keys (Bedrud server) :

server:
  port: 8090                    # API port (signaling proxied à travers ceci)
  enableTLS: true               # HTTPS pour signaling
  domain: "meet.example.com"    # Public domain

Debugging Connectivity Issues

SymptomCheck
Can’t connect at allrtc.use_external_ip: true ? Firewall open sur 443 + UDP range ?
Connects mais no audio/videoUDP 50000-60000 blocked ? Check ICE candidates dans browser.
Slow connectionTURN relay active (check candidates). Expected si le client derrière strict NAT.
Fails derrière corporate networkTURN/TLS not configured. Set turn.tls_port: 443 avec valid cert.
Works sur LAN, fails remotelyPublic IP not advertised. Set rtc.use_external_ip: true.

Pour deep TURN troubleshooting, voir le TURN Server Guide.


See also