Ihre WebRTC-App funktioniert in Ihrem WLAN und scheitert bei genau dem einen Kunden, der aus dem Hotel anruft. Peer-to-Peer-Medien brauchen einen Weg zwischen beiden Seiten; sitzen beide hinter strengem NAT oder verwirft eine Firewall UDP, gibt es keinen Weg, und der Anruf kommt einfach nicht zustande. Niemand sieht einen Fehler – nur ein endloses „Verbinde …“.
Ein TURN-Server ist der Rückfall für genau diese Anrufe: Beide Seiten schicken ihre Medien an ihn, und er leitet weiter. Wenn Sie Video oder Sprache in eine App einbauen, Matrix oder Jitsi für ein Team betreiben oder Voice-Chat für ein Spiel machen, brauchen Sie einen. coturn ist die Standard-Implementierung als Open Source, und sie ist leichtgewichtig.
Welcher Tarif
TURN braucht kaum CPU und Speicher. Was es verbraucht, ist Bandbreite: Jeder weitergeleitete Stream läuft zweimal durch den Server, rein und raus. Der Traffic ist bei unseren Tarifen mit 1 Gbit/s unbegrenzt, die Frage ist also, wie viele weitergeleitete Anrufe gleichzeitig laufen – nicht, was auf der Rechnung steht.
| Gleichzeitig weitergeleitete Anrufe | Tarif |
|---|---|
| Eine Handvoll – ein Team, eine kleine App | Nano-IP – 2 vCPU, 1 GB, 15 GB ($8/Monat) |
| Dutzende | Micro-IP – 2 vCPU, 2 GB, 25 GB ($10/Monat) |
| Mehr, oder TURN neben Ihrem App-Server | Small-IP – 4 vCPU, 4 GB, 35 GB ($16/Monat) |
Es muss ein Tarif mit eigener IPv4 sein – bei TURN dreht sich alles um eingehende Verbindungen auf vielen Ports, und NAT-Tarife nehmen von außen nur SSH an. Bei unseren Tarifen mit eigener IP liegt die öffentliche Adresse direkt auf dem Interface des Servers, also findet coturn sie ohne external-ip-Zeile. Stellen Sie den Server nah an Ihre Nutzer: Deutschland oder Finnland, die Verfügbarkeit sehen Sie bei der Bestellung. Bezahlung mit Krypto, ohne KYC, falls Ihnen das wichtig ist.
Zu öffnende Ports: 3478 UDP und TCP, 49152–65535 UDP für die weitergeleiteten Medien und 5349 TCP, wenn Sie TLS hinzufügen.
Installation und Konfiguration
Als root auf Ubuntu 24.04 oder Debian 12:
apt install -y coturn
ip -4 addr # deine öffentliche IP sollte am Interface stehen
Schreiben Sie die Konfiguration mit einem frischen gemeinsamen Secret:
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" # dieser Wert wird in deinem Backend gebraucht
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable
Lassen Sie die denied-peer-ip-Zeilen nicht weg. Ohne sie kann jeder mit gültigen Zugangsdaten über Ihr Relay private Adressen erreichen – auch Dienste auf der internen Seite des Servers selbst. Wir haben es geprüft: Mit diesen Zeilen wird ein Relay zu einer privaten Adresse mit „403 Forbidden IP“ abgelehnt.
Zugangsdaten, die ablaufen
Mit use-auth-secret akzeptiert coturn einen Benutzernamen, der eine Ablaufzeit enthält, und ein Passwort, das ein HMAC davon ist. Ihr Backend erzeugt sie; das Secret verlässt nie die Serverseite. In Node.js:
const crypto = require("crypto");
// Temporärer TURN-Benutzername und -Passwort (das TURN-REST-API-Schema, das coturn über use-auth-secret versteht).
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")));
Im Browser holen Sie sich vom Backend ein frisches Paar und übergeben es an 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
Auf dem Server, nach demselben Schema mit openssl (es erzeugt genau dasselbe Passwort wie der Node.js-Code – wir haben verglichen):
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
Am Ende wollen Sie „Total lost packets 0“ sehen. Mit falschem Passwort bleibt der Client bei „Cannot complete Allocation“ stehen – das ist der Server, der seine Arbeit macht.
Wir haben auch aus einem echten Chromium getestet: Mit iceTransportPolicy: "relay" und frischen Zugangsdaten bekam der Browser Relay-Kandidaten vom Server, mit falschem Passwort keine. Wenn Sie Ihr eigenes Setup genauso testen wollen, setzen Sie diese Option kurz – sie zwingt jeden Anruf über TURN.
TLS, falls nötig
Manche Netze blockieren UDP und sind bei einfachem TCP wählerisch; TURN über TLS kommt durch mehr davon. Besorgen Sie ein Zertifikat für turn.example.com (certbot reicht). Dessen Dateien kann nur root lesen, coturn läuft aber als Benutzer turnserver – geben Sie coturn also eine eigene 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
Fügen Sie turns:turn.example.com:5349?transport=tcp zur urls-Liste hinzu. Zertifikate sind kurzlebig, also packen Sie das Kopieren in einen certbot-Deploy-Hook – sonst bricht TLS bei der ersten Erneuerung still und leise.
Gut zu wissen
- TURN macht aus einer schlechten Verbindung keine gute. Es fügt einen Hop hinzu, also stellen Sie den Server in die Nähe derer, die ihn brauchen.
- Wenn Sie eine SFU betreiben – etwa die Videobridge von Jitsi –, ist das ein separater Baustein. TURN hilft den Clients, die sie nicht direkt erreichen.
- Das Secret ist das gesamte Sicherheitsmodell. Halten Sie es aus dem Frontend heraus und tauschen Sie es aus, falls es je durchsickert.
Verwandte Themen
- VPS für Jitsi Meet – Videoanrufe auf dem eigenen Server
- Matrix Synapse selbst hosten – auch Anrufe in Matrix brauchen einen TURN-Server
- VPS für eine Website mit eigener IP – die App, die die Zugangsdaten ausgibt
- Eine ufw-Firewall konfigurieren
Kommentare
Noch keine Kommentare. Sei der Erste.