Din WebRTC-app fungerar på ditt wifi och misslyckas för just den kund som ringer från ett hotell. Peer-to-peer-media behöver en väg mellan de två sidorna; när båda sitter bakom strikt NAT, eller en brandvägg släpper UDP, finns ingen väg och samtalet kopplas helt enkelt inte upp. Ingen ser något fel — bara ett ändlöst ”ansluter…”.
En TURN-server är reservvägen för just de samtalen: båda sidor skickar sina media till den, och den vidarebefordrar. Bygger du in video eller röst i en app, kör Matrix eller Jitsi för ett team eller gör röstchatt för ett spel, vill du ha en. coturn är den vanliga implementationen med öppen källkod, och den är lätt.
Vilken plan
TURN kräver lite CPU och minne. Det som går åt är bandbredd: varje vidarebefordrad ström passerar servern två gånger, in och ut. Trafiken på våra planer är obegränsad på 1 Gbit/s, så frågan är hur många vidarebefordrade samtal som pågår samtidigt, inte hur mycket du blir debiterad.
| Vidarebefordrade samtal samtidigt | Plan |
|---|---|
| En handfull — ett team, en liten app | Nano-IP: 2 vCPU, 1 GB, 15 GB ($8/mån) |
| Dussintals | Micro-IP: 2 vCPU, 2 GB, 25 GB ($10/mån) |
| Fler, eller TURN bredvid din appserver | Small-IP: 4 vCPU, 4 GB, 35 GB ($16/mån) |
Det måste vara en plan med egen IPv4 — TURN handlar helt om inkommande anslutningar på många portar, och NAT-planer tar bara emot SSH utifrån. På våra planer med egen IP ligger den publika adressen direkt på serverns gränssnitt, så coturn hittar den utan en external-ip-rad. Placera servern nära dina användare: Tyskland eller Finland, tillgängligheten syns vid beställning. Betalning med krypto, utan KYC, om det spelar roll för dig.
Portar att öppna: 3478 UDP och TCP, 49152–65535 UDP för vidarebefordrad media och 5349 TCP om du lägger till TLS.
Installera och konfigurera
Som root på Ubuntu 24.04 eller Debian 12:
apt install -y coturn
ip -4 addr # din publika IP ska synas på gränssnittet
Skriv konfigurationen med en ny delad hemlighet:
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 behöver det här värdet
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable
Hoppa inte över raderna denied-peer-ip. Utan dem kan vem som helst med giltiga uppgifter använda ditt relä för att nå privata adresser — även tjänster på serverns egen interna sida. Vi kontrollerade: med de här raderna nekas ett relä till en privat adress med ”403 Forbidden IP”.
Inloggningsuppgifter som går ut
Med use-auth-secret accepterar coturn ett användarnamn som innehåller en utgångstid och ett lösenord som är en HMAC av det. Din backend genererar dem; hemligheten lämnar aldrig serversidan. I Node.js:
const crypto = require("crypto");
// Tillfälligt TURN-användarnamn och lösenord (TURN REST API-schemat som coturn förstå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 webbläsaren ber du din backend om ett nytt par och ger det till 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,
},
],
});
Testa
Från servern, med samma schema via openssl (det ger exakt samma lösenord som Node.js-koden — vi jämförde):
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
I slutet vill du se ”Total lost packets 0”. Med fel lösenord stannar klienten vid ”Cannot complete Allocation” — det är servern som gör sitt jobb.
Vi testade också från en riktig Chromium: med iceTransportPolicy: "relay" och färska uppgifter fick webbläsaren relay-kandidater från servern; med fel lösenord inga alls. Vill du testa din egen uppsättning på samma sätt, slå på det alternativet en stund — det tvingar varje samtal genom TURN.
TLS, om du behöver det
Vissa nät blockerar UDP och är petiga med vanlig TCP; TURN över TLS tar sig igenom fler av dem. Skaffa ett certifikat för turn.example.com (certbot duger). Filerna kan bara läsas av root, medan coturn körs som användaren turnserver, så ge coturn en egen kopia:
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
Lägg till turns:turn.example.com:5349?transport=tcp i listan urls. Certifikat är kortlivade, så lägg kopieringen i en deploy hook för certbot — annars går TLS tyst sönder vid första förnyelsen.
Bra att veta
- TURN gör inte en dålig anslutning bra. Den lägger till ett hopp, så placera servern nära dem som behöver den.
- Kör du en SFU — till exempel Jitsis videobridge — är det en separat del. TURN hjälper klienterna som inte når den direkt.
- Hemligheten är hela säkerhetsmodellen. Håll den borta från frontend och byt ut den om den någonsin läcker.
Relaterat
- VPS för Jitsi Meet: videosamtal på din egen server
- Kör Matrix Synapse själv: även samtal i Matrix behöver en TURN-server
- VPS för en webbplats på egen IP: appen som delar ut inloggningsuppgifterna
- Så konfigurerar du en ufw-brandvägg
Kommentarer
Inga kommentarer än. Bli först.