−25%

på Windows ved årlig betaling, til 31/10. Se pakkerne

EQVPS
Kom i gang

VPS til en TURN-server (coturn) til WebRTC

Opkald, der fejler bag streng NAT, har brug for et TURN-relæ. coturn på en server med egen IPv4: porte, tidsbegrænsede loginoplysninger, testet konfiguration.

Din WebRTC-app virker på dit wifi og fejler hos netop den ene kunde, der ringer fra et hotel. Peer-to-peer-medier skal have en vej mellem de to sider; når begge sidder bag streng NAT, eller en firewall smider UDP væk, er der ingen vej, og opkaldet bliver simpelthen ikke forbundet. Ingen ser en fejl — bare et uendeligt „forbinder…”.

En TURN-server er reserveløsningen til netop de opkald: begge sider sender deres medier til den, og den videresender. Bygger du video eller tale ind i en app, kører du Matrix eller Jitsi for et team eller laver du stemmechat til et spil, så vil du have en. coturn er standardimplementeringen med åben kildekode, og den er let.

Hvilken plan

TURN bruger meget lidt CPU og hukommelse. Det, den bruger, er båndbredde: hver videresendt strøm går to gange gennem serveren, ind og ud. Trafik er ubegrænset ved 1 Gbit/s på vores planer, så spørgsmålet er, hvor mange videresendte opkald der kører samtidig, ikke hvor meget du bliver faktureret.

Videresendte opkald samtidigPlan
En håndfuld — et team, en lille appNano-IP: 2 vCPU, 1 GB, 15 GB ($8/md.)
DusinvisMicro-IP: 2 vCPU, 2 GB, 25 GB ($10/md.)
Flere, eller TURN ved siden af din appserverSmall-IP: 4 vCPU, 4 GB, 35 GB ($16/md.)

Det skal være en plan med egen IPv4 — TURN handler udelukkende om indgående forbindelser på mange porte, og NAT-planer modtager kun SSH udefra. På vores planer med egen IP ligger den offentlige adresse direkte på serverens interface, så coturn finder den uden en external-ip-linje. Placér serveren tæt på dine brugere: Tyskland eller Finland, tilgængeligheden ses ved bestilling. Betaling med krypto, uden KYC, hvis det betyder noget for dig.

Porte, der skal åbnes: 3478 UDP og TCP, 49152–65535 UDP til de videresendte medier og 5349 TCP, hvis du tilføjer TLS.

Installation og konfiguration

Som root på Ubuntu 24.04 eller Debian 12:

apt install -y coturn
ip -4 addr    # din offentlige IP skal stå på interfacet

Skriv konfigurationen med en frisk delt hemmelighed:

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"    # din backend skal bruge denne værdi
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable

Spring ikke linjerne denied-peer-ip over. Uden dem kan enhver med gyldige loginoplysninger bruge dit relæ til at nå private adresser — også tjenester på serverens egen interne side. Vi tjekkede: med disse linjer afvises et relæ til en privat adresse med „403 Forbidden IP”.

Loginoplysninger, der udløber

Med use-auth-secret accepterer coturn et brugernavn, der indeholder et udløbstidspunkt, og en adgangskode, der er en HMAC af det. Din backend genererer dem; hemmeligheden forlader aldrig serversiden. I Node.js:

const crypto = require("crypto");

// Midlertidigt TURN-brugernavn og adgangskode (TURN REST API-skemaet, som coturn forstår via use-auth-secret).
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")));

I browseren beder du din backend om et nyt par og giver det til 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,
    },
  ],
});

Test det

Fra serveren, efter samme skema med openssl (det giver præcis samme adgangskode som Node.js-koden — vi sammenlignede):

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

Til sidst vil du se „Total lost packets 0”. Med en forkert adgangskode stopper klienten ved „Cannot complete Allocation” — det er serveren, der gør sit arbejde.

Vi testede også fra en rigtig Chromium: med iceTransportPolicy: "relay" og friske loginoplysninger fik browseren relay-kandidater fra serveren; med en forkert adgangskode ingen. Vil du teste din egen opsætning på samme måde, så slå den indstilling til et øjeblik — den tvinger hvert opkald gennem TURN.

TLS, hvis du har brug for det

Nogle netværk blokerer UDP og er kræsne med almindelig TCP; TURN over TLS kommer igennem flere af dem. Skaf et certifikat til turn.example.com (certbot er fint). Filerne kan kun læses af root, mens coturn kører som brugeren turnserver, så giv coturn sin egen kopi:

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

Tilføj turns:turn.example.com:5349?transport=tcp til listen urls. Certifikater er kortlivede, så læg kopieringen i et deploy hook til certbot — ellers går TLS stille i stykker ved første fornyelse.

Værd at vide

  • TURN gør ikke en dårlig forbindelse god. Den tilføjer ét hop, så placér serveren tæt på dem, der har brug for den.
  • Kører du en SFU — fx Jitsis videobridge — er det en separat del. TURN hjælper de klienter, der ikke kan nå den direkte.
  • Hemmeligheden er hele sikkerhedsmodellen. Hold den ude af frontenden, og udskift den, hvis den nogensinde lækker.

Relateret

Klar til at deploye? Betal med krypto, ingen KYC — live på cirka et minut.

Deploy nu →

FAQ

Hvorfor har WebRTC-opkald overhovedet brug for en TURN-server?

WebRTC forsøger at forbinde deltagerne direkte, og det lykkes som regel. Når begge sider sidder bag symmetrisk NAT eller en firewall, der smider UDP væk — hotel-wifi, kontornetværk, visse mobiloperatører — findes der ingen direkte vej, og opkaldet fejler uden et ord. En TURN-server videresender medierne for netop de opkald; den andel, der ofte nævnes, ligger omkring ét opkald ud af ti.

Kan TURN køre på en NAT-plan?

Nej. Klienterne forbinder til UDP og TCP 3478 og til relæets portområde, og en NAT-plan modtager udefra kun din SSH-port. Du skal bruge en plan med egen IPv4.

Hvor meget båndbredde bruger den?

Hver videresendt strøm går to gange gennem serveren — ind fra den ene side, ud til den anden. Et videoopkald mellem to på 1–2 Mbit/s i hver retning giver et par Mbit/s på serveren. CPU og RAM mærker det knap; det reelle loft er porten på 1 Gbit/s.

Hvorfor ikke bare lægge et fast brugernavn og en fast adgangskode i appen?

Fordi alt i browserens JavaScript er offentligt, og en TURN-server med kendt adgangskode er et gratis relæ for hele internettet. Med use-auth-secret udleverer din backend loginoplysninger, der udløber, signeret med en hemmelighed, som browseren aldrig ser.

Har jeg brug for TLS på port 5349?

Det hjælper på netværk, der blokerer UDP og er strenge over for almindelig TCP. Tilføj det, når almindelig TURN virker: giv coturn et certifikat til TURN-værtsnavnet, og åbn 5349/tcp. Vi testede også relæet over TLS.

Kommentarer

Ingen kommentarer endnu. Vær den første.

Skriv en kommentar

Kommentarer modereres, før de vises.