−25%

op Windows bij jaarbetaling, tot 31/10. Naar de pakketten

EQVPS
Aan de slag

VPS voor een TURN-server (coturn) voor WebRTC

Gesprekken die vastlopen achter strenge NAT hebben een TURN-relay nodig. coturn op een server met eigen IPv4: poorten, tijdelijke inloggegevens, geteste config.

Je WebRTC-app werkt op je eigen wifi en faalt bij precies die ene klant die vanuit een hotel belt. Peer-to-peer-media hebben een route tussen beide kanten nodig; zitten beide achter strenge NAT, of laat een firewall UDP vallen, dan is er geen route en komt het gesprek gewoon niet tot stand. Niemand ziet een foutmelding — alleen een eindeloos „verbinden…”.

Een TURN-server is de terugvaloptie voor precies die gesprekken: beide kanten sturen hun media ernaartoe en hij stuurt ze door. Bouw je video of spraak in een app, draai je Matrix of Jitsi voor een team of maak je voicechat voor een game, dan wil je er een. coturn is de standaard opensource-implementatie, en die is licht.

Welk plan

TURN vraagt weinig CPU en geheugen. Wat het gebruikt is bandbreedte: elke doorgestuurde stream gaat twee keer door de server, erin en eruit. Verkeer is op onze plannen onbeperkt op 1 Gbit/s, dus de vraag is hoeveel doorgestuurde gesprekken er tegelijk lopen, niet hoeveel je gefactureerd krijgt.

Tegelijk doorgestuurde gesprekkenPlan
Een handvol — een team, een kleine appNano-IP: 2 vCPU, 1 GB, 15 GB ($8/mnd)
TientallenMicro-IP: 2 vCPU, 2 GB, 25 GB ($10/mnd)
Meer, of TURN naast je appserverSmall-IP: 4 vCPU, 4 GB, 35 GB ($16/mnd)

Het moet een plan met een eigen IPv4 zijn — bij TURN draait alles om inkomende verbindingen op veel poorten, en NAT-plannen accepteren van buitenaf alleen SSH. Op onze plannen met een eigen IP staat het publieke adres direct op de interface van de server, dus coturn vindt het zonder external-ip-regel. Zet de server dicht bij je gebruikers: Duitsland of Finland, de beschikbaarheid zie je bij het bestellen. Betalen met crypto, zonder KYC, als je dat belangrijk vindt.

Te openen poorten: 3478 UDP en TCP, 49152–65535 UDP voor de doorgestuurde media en 5349 TCP als je TLS toevoegt.

Installeren en configureren

Als root op Ubuntu 24.04 of Debian 12:

apt install -y coturn
ip -4 addr    # je publieke IP hoort op de interface te staan

Schrijf de configuratie met een vers gedeeld geheim:

SECRET=$(openssl rand -hex 32)
cat > /etc/turnserver.conf <<EOF
listening-port=3478
fingerprint
use-auth-secret
static-auth-secret=$SECRET
realm=turn.example.com
min-port=49152
max-port=65535
no-cli
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
EOF
echo "$SECRET"    # je backend heeft deze waarde nodig
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable

Sla de denied-peer-ip-regels niet over. Zonder die regels kan iedereen met geldige inloggegevens via je relay private adressen bereiken — ook diensten aan de interne kant van de server zelf. We hebben het gecontroleerd: met deze regels wordt een relay naar een privéadres geweigerd met „403 Forbidden IP”.

Inloggegevens die verlopen

Met use-auth-secret accepteert coturn een gebruikersnaam die een verlooptijd bevat en een wachtwoord dat daar een HMAC van is. Je backend genereert ze; het geheim verlaat nooit de serverkant. In Node.js:

const crypto = require("crypto");

// Tijdelijke TURN-gebruikersnaam en -wachtwoord (het TURN REST API-schema dat coturn via use-auth-secret begrijpt).
function turnCredentials(secret, user, ttlSeconds = 3600) {
  const username = `${Math.floor(Date.now() / 1000) + ttlSeconds}:${user}`;
  const credential = crypto.createHmac("sha1", secret).update(username).digest("base64");
  return { username, credential };
}

console.log(JSON.stringify(turnCredentials(process.env.TURN_SECRET, "alice")));

Vraag in de browser je backend om een vers paar en geef het aan RTCPeerConnection:

const { username, credential } = await fetch("/api/turn-credentials").then((r) => r.json());

const pc = new RTCPeerConnection({
  iceServers: [
    { urls: "stun:turn.example.com:3478" },
    {
      urls: ["turn:turn.example.com:3478?transport=udp", "turn:turn.example.com:3478?transport=tcp"],
      username,
      credential,
    },
  ],
});

Testen

Vanaf de server, met hetzelfde schema via openssl (het levert precies hetzelfde wachtwoord als de Node.js-code — we hebben het vergeleken):

U="$(( $(date +%s) + 3600 )):test"
P=$(echo -n "$U" | openssl dgst -binary -sha1 -hmac "$SECRET" | base64)
turnutils_uclient -y -n 10 -u "$U" -w "$P" YOUR_SERVER_IP

Aan het eind wil je „Total lost packets 0” zien. Met een verkeerd wachtwoord stopt de client bij „Cannot complete Allocation” — dat is de server die zijn werk doet.

We hebben ook getest vanuit een echte Chromium: met iceTransportPolicy: "relay" en verse inloggegevens kreeg de browser relay-kandidaten van de server; met een fout wachtwoord geen enkele. Wil je je eigen opzet op dezelfde manier testen, zet die optie dan even aan — ze dwingt elk gesprek via TURN.

TLS, als je het nodig hebt

Sommige netwerken blokkeren UDP en zijn kieskeurig over gewone TCP; TURN over TLS komt door meer daarvan heen. Haal een certificaat voor turn.example.com (certbot volstaat). De bestanden ervan zijn alleen leesbaar voor root, terwijl coturn draait als gebruiker turnserver, dus geef coturn een eigen kopie:

mkdir -p /etc/coturn
cp /etc/letsencrypt/live/turn.example.com/fullchain.pem /etc/letsencrypt/live/turn.example.com/privkey.pem /etc/coturn/
chown turnserver: /etc/coturn/*.pem && chmod 640 /etc/coturn/privkey.pem
cat >> /etc/turnserver.conf <<'EOF'
tls-listening-port=5349
cert=/etc/coturn/fullchain.pem
pkey=/etc/coturn/privkey.pem
EOF
systemctl restart coturn && ufw allow 5349/tcp

Voeg turns:turn.example.com:5349?transport=tcp toe aan de urls-lijst. Certificaten zijn kortlevend, dus zet het kopiëren in een certbot-deploy-hook — anders gaat TLS bij de eerste vernieuwing stilletjes stuk.

Goed om te weten

  • TURN maakt van een slechte verbinding geen goede. Het voegt één hop toe, dus zet de server dicht bij de mensen die hem nodig hebben.
  • Draai je een SFU — de videobridge van Jitsi bijvoorbeeld —, dan is dat een apart onderdeel. TURN helpt de clients die die niet direct kunnen bereiken.
  • Het geheim is het hele beveiligingsmodel. Houd het uit de frontend en vervang het als het ooit uitlekt.

Gerelateerd

Klaar om te implementeren? Betaal met crypto, geen KYC — live in ongeveer een minuut.

Nu implementeren →

FAQ

Waarom hebben WebRTC-gesprekken überhaupt een TURN-server nodig?

WebRTC probeert deelnemers direct te verbinden, en dat lukt meestal. Zitten beide kanten achter symmetrische NAT of een firewall die UDP laat vallen — hotelwifi, kantoornetwerken, sommige mobiele providers — dan is er geen directe route en mislukt het gesprek zonder melding. Een TURN-server stuurt de media precies voor die gesprekken door; het aandeel dat vaak genoemd wordt, ligt rond één op de tien gesprekken.

Kan TURN op een NAT-plan draaien?

Nee. Clients verbinden met UDP en TCP 3478 en met de reeks relaypoorten, en een NAT-plan accepteert van buitenaf alleen je SSH-poort. Je hebt een plan met een eigen IPv4 nodig.

Hoeveel bandbreedte gebruikt het?

Elke doorgestuurde stream gaat twee keer door de server — binnen van de ene kant, naar buiten naar de andere. Een videogesprek met twee personen op 1–2 Mbit/s per richting is een paar Mbit/s op de server. CPU en RAM merken er nauwelijks iets van; het echte plafond is de 1 Gbit/s-poort.

Waarom niet gewoon een vaste gebruikersnaam en wachtwoord in de app zetten?

Omdat alles in browser-JavaScript openbaar is, en een TURN-server met een bekend wachtwoord is een gratis relay voor het hele internet. Met use-auth-secret geeft je backend inloggegevens uit die verlopen, ondertekend met een geheim dat de browser nooit ziet.

Heb ik TLS op poort 5349 nodig?

Het helpt op netwerken die UDP blokkeren en streng zijn met gewone TCP. Voeg het toe zodra gewone TURN werkt: geef coturn een certificaat voor de TURN-hostnaam en open 5349/tcp. We hebben de relay over TLS ook getest.

Reacties

Nog geen reacties. Wees de eerste.

Laat een reactie achter

Reacties worden gemodereerd voordat ze verschijnen.