−25%

na Windows przy płatności rocznej, do 31.10. Do planów

EQVPS
Zacznij

VPS na serwer TURN (coturn) dla WebRTC

Połączenia, które padają za restrykcyjnym NAT, potrzebują przekaźnika TURN. coturn na serwerze z własnym IPv4: porty, tymczasowe hasła, sprawdzony config.

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ń narazPlan
Kilka — zespół, mała aplikacjaNano-IP: 2 vCPU, 1 GB, 15 GB ($8/mies.)
DziesiątkiMicro-IP: 2 vCPU, 2 GB, 25 GB ($10/mies.)
Więcej, albo TURN obok serwera aplikacjiSmall-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

Gotowy na wdrożenie? Płać kryptowalutą, bez KYC — online w około minutę.

Wdróż teraz →

FAQ

Po co połączeniom WebRTC w ogóle serwer TURN?

WebRTC próbuje połączyć uczestników bezpośrednio i zwykle mu się to udaje. Gdy obie strony siedzą za symetrycznym NAT albo zaporą, która odrzuca UDP — hotelowe Wi-Fi, sieci biurowe, niektórzy operatorzy komórkowi — bezpośredniej drogi nie ma i połączenie po cichu się nie udaje. Serwer TURN przekazuje media właśnie dla takich połączeń; zwykle mówi się o mniej więcej jednym połączeniu na dziesięć.

Czy TURN zadziała na planie NAT?

Nie. Klienci łączą się na UDP i TCP 3478 oraz na zakres portów przekaźnika, a plan NAT przyjmuje z zewnątrz tylko Twój port SSH. Potrzebujesz planu z własnym IPv4.

Ile pasma zużywa?

Każdy przekazywany strumień przechodzi przez serwer dwa razy — do środka od jednej strony i na zewnątrz do drugiej. Rozmowa wideo jeden na jeden po 1–2 Mbit/s w każdą stronę to kilka Mbit/s na serwerze. CPU i RAM prawie tego nie zauważają; prawdziwym sufitem jest port 1 Gbit/s.

Dlaczego po prostu nie wpisać stałego loginu i hasła w aplikacji?

Bo wszystko w JavaScripcie przeglądarki jest publiczne, a serwer TURN ze znanym hasłem to darmowy przekaźnik dla całego internetu. Z use-auth-secret Twój backend wydaje dane logowania, które wygasają, podpisane sekretem, którego przeglądarka nigdy nie widzi.

Czy potrzebuję TLS na porcie 5349?

Pomaga w sieciach, które blokują UDP i są surowe wobec zwykłego TCP. Dodaj go, gdy zwykły TURN już działa: daj coturn certyfikat dla nazwy hosta TURN i otwórz 5349/tcp. Przekazywanie przez TLS też przetestowaliśmy.

Komentarze

Brak komentarzy. Bądź pierwszy.

Zostaw komentarz

Komentarze są moderowane przed pojawieniem się.