Twoja aplikacja WebRTC działa na Twoim Wi-Fi i nie działa u tego jednego klienta, który dzwoni z hotelu. Media peer-to-peer potrzebują drogi między obiema stronami; gdy obie są za restrykcyjnym NAT albo zapora odrzuca UDP, drogi nie ma i połączenie po prostu się nie zestawia. Nikt nie widzi błędu — tylko niekończące się „łączenie…”.
Serwer TURN to wyjście awaryjne dla takich połączeń: obie strony wysyłają do niego media, a on je przekazuje. Jeśli wbudowujesz wideo lub głos w aplikację, prowadzisz Matrix albo Jitsi dla zespołu albo robisz czat głosowy do gry — potrzebujesz go. coturn to standardowa otwarta implementacja i jest lekka.
Jaki plan
TURN prawie nie obciąża CPU i pamięci. Zużywa pasmo: każdy przekazywany strumień przechodzi przez serwer dwa razy, na wejściu i wyjściu. Ruch na naszych planach jest bez limitu przy 1 Gbit/s, więc pytanie brzmi, ile przekazywanych połączeń działa naraz, a nie ile zapłacisz.
| Przekazywanych połączeń naraz | Plan |
|---|---|
| Kilka — zespół, mała aplikacja | Nano-IP: 2 vCPU, 1 GB, 15 GB ($8/mies.) |
| Dziesiątki | Micro-IP: 2 vCPU, 2 GB, 25 GB ($10/mies.) |
| Więcej, albo TURN obok serwera aplikacji | Small-IP: 4 vCPU, 4 GB, 35 GB ($16/mies.) |
To musi być plan z własnym IPv4 — TURN to w całości połączenia przychodzące na wielu portach, a plany NAT przyjmują z zewnątrz tylko SSH. Na naszych planach z własnym IP publiczny adres jest bezpośrednio na interfejsie serwera, więc coturn znajduje go bez linii external-ip. Postaw serwer blisko użytkowników: Niemcy albo Finlandia, dostępność widać przy zamówieniu. Płatność kryptowalutą, bez KYC, jeśli to dla Ciebie ważne.
Porty do otwarcia: 3478 UDP i TCP, 49152–65535 UDP dla przekazywanych mediów i 5349 TCP, jeśli dodajesz TLS.
Instalacja i konfiguracja
Jako root na Ubuntu 24.04 lub Debianie 12:
apt install -y coturn
ip -4 addr # publiczny IP powinien być widoczny na interfejsie
Zapisz konfigurację ze świeżym wspólnym sekretem:
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" # ta wartość jest potrzebna backendowi
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable
Nie pomijaj linii denied-peer-ip. Bez nich każdy z ważnymi danymi logowania może przez Twój przekaźnik dostać się do adresów prywatnych — w tym do usług po wewnętrznej stronie samego serwera. Sprawdziliśmy: z tymi liniami przekazywanie na adres prywatny jest odrzucane z „403 Forbidden IP”.
Dane logowania, które wygasają
Z use-auth-secret coturn przyjmuje nazwę użytkownika zawierającą czas wygaśnięcia i hasło będące jej HMAC. Generuje je Twój backend; sekret nigdy nie opuszcza strony serwera. W Node.js:
const crypto = require("crypto");
// Tymczasowy login/hasło TURN (schemat TURN REST API, który coturn rozumie przez 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")));
W przeglądarce poproś backend o świeżą parę i przekaż ją do 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
Na serwerze, według tego samego schematu przez openssl (daje dokładnie to samo hasło co kod w Node.js — porównaliśmy):
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
Na końcu powinno być „Total lost packets 0”. Ze złym hasłem klient zatrzymuje się na „Cannot complete Allocation” — to serwer robi swoje.
Sprawdziliśmy też z prawdziwego Chromium: z iceTransportPolicy: "relay" i świeżymi danymi logowania przeglądarka dostała od serwera kandydatów relay; ze złym hasłem — żadnego. Jeśli chcesz tak samo sprawdzić swoją konfigurację, włącz tę opcję na chwilę — wymusza przejście każdego połączenia przez TURN.
TLS, jeśli potrzebny
Niektóre sieci blokują UDP i są wybredne wobec zwykłego TCP; TURN przez TLS przechodzi przez więcej z nich. Zdobądź certyfikat dla turn.example.com (certbot wystarczy). Jego pliki może czytać tylko root, a coturn działa jako użytkownik turnserver, więc daj coturn własną 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
Dodaj turns:turn.example.com:5349?transport=tcp do listy urls. Certyfikaty żyją krótko, więc umieść kopiowanie w deploy hooku certbota — inaczej TLS po cichu przestanie działać przy pierwszym odnowieniu.
Warto wiedzieć
- TURN nie zrobi z kiepskiego połączenia dobrego. Dodaje jeden przeskok, więc postaw serwer blisko tych, którzy go potrzebują.
- Jeśli masz SFU — na przykład videobridge w Jitsi — to osobny element. TURN pomaga klientom, którzy nie mogą dotrzeć do niego bezpośrednio.
- Cały model bezpieczeństwa opiera się na sekrecie. Trzymaj go z dala od frontendu i zmień, jeśli kiedyś wycieknie.
Powiązane
- VPS dla Jitsi Meet — rozmowy wideo na własnym serwerze
- Własny Matrix Synapse — rozmowy w Matrix też potrzebują serwera TURN
- VPS dla strony na własnym IP — aplikacja, która wydaje dane logowania
- Jak skonfigurować zaporę ufw
Komentarze
Brak komentarzy. Bądź pierwszy.