−25%

su Windows con pagamento annuale, fino al 31/10. Vai ai piani

EQVPS
Inizia

VPS per un server TURN (coturn) per WebRTC

Le chiamate bloccate da un NAT rigido hanno bisogno di un relay TURN. coturn su un server con IPv4 propria: porte, credenziali temporanee, config testata.

La tua app WebRTC funziona sul tuo Wi-Fi e fallisce proprio per il cliente che chiama da un albergo. I flussi peer-to-peer hanno bisogno di un percorso tra i due lati; quando entrambi stanno dietro un NAT rigido, o un firewall blocca l'UDP, il percorso non c'è e la chiamata semplicemente non si connette. Nessuno vede un errore: solo un «connessione in corso…» infinito.

Un server TURN è il ripiego per quelle chiamate: entrambi i lati gli mandano i loro flussi, e lui li inoltra. Se stai integrando video o voce in un'app, gestisci Matrix o Jitsi per un team o fai chat vocale per un gioco, ti serve. coturn è l'implementazione open source di riferimento, ed è leggera.

Quale piano

TURN pesa poco su CPU e memoria. Quello che usa è la banda: ogni flusso inoltrato passa due volte dal server, in entrata e in uscita. Sui nostri piani il traffico è illimitato a 1 Gbit/s, quindi la domanda è quante chiamate inoltrate girano insieme, non quanto ti verrà fatturato.

Chiamate inoltrate in contemporaneaPiano
Poche: un team, una piccola appNano-IP: 2 vCPU, 1 GB, 15 GB ($8/mese)
DecineMicro-IP: 2 vCPU, 2 GB, 25 GB ($10/mese)
Di più, o TURN accanto al server dell'appSmall-IP: 4 vCPU, 4 GB, 35 GB ($16/mese)

Dev'essere un piano con un IPv4 tutto suo: TURN vive di connessioni in entrata su molte porte, e i piani NAT accettano dall'esterno solo SSH. Sui nostri piani con IP dedicato l'indirizzo pubblico sta direttamente sull'interfaccia del server, quindi coturn lo trova senza la riga external-ip. Metti il server vicino ai tuoi utenti: Germania o Finlandia, la disponibilità si vede al momento dell'ordine. Pagamento in cripto, senza KYC, se per te conta.

Porte da aprire: 3478 UDP e TCP, 49152–65535 UDP per i flussi inoltrati e 5349 TCP se aggiungi TLS.

Installazione e configurazione

Come root su Ubuntu 24.04 o Debian 12:

apt install -y coturn
ip -4 addr    # il tuo IP pubblico dovrebbe comparire sull'interfaccia

Scrivi la configurazione con un segreto condiviso nuovo:

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"    # questo valore serve al tuo backend
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable

Non saltare le righe denied-peer-ip. Senza di esse, chiunque abbia credenziali valide può usare il tuo relay per raggiungere indirizzi privati, compresi i servizi sul lato interno del server stesso. Abbiamo verificato: con queste righe un relay verso un indirizzo privato viene rifiutato con «403 Forbidden IP».

Credenziali che scadono

Con use-auth-secret, coturn accetta un nome utente che contiene un'ora di scadenza e una password che ne è l'HMAC. Le genera il tuo backend; il segreto non lascia mai il lato server. In Node.js:

const crypto = require("crypto");

// Utente/password TURN temporanei (lo schema TURN REST API che coturn capisce tramite 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")));

Nel browser, chiedi al backend una coppia nuova e passala a 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,
    },
  ],
});

Provalo

Dal server, con lo stesso schema usando openssl (produce esattamente la stessa password del codice Node.js: abbiamo confrontato):

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

Alla fine vuoi vedere «Total lost packets 0». Con una password sbagliata il client si ferma a «Cannot complete Allocation»: è il server che fa il suo lavoro.

Abbiamo verificato anche da un vero Chromium: con iceTransportPolicy: "relay" e credenziali fresche il browser ha ricevuto candidati relay dal server; con una password sbagliata, nessuno. Se vuoi provare la tua configurazione allo stesso modo, attiva quell'opzione per un momento: costringe ogni chiamata a passare da TURN.

TLS, se serve

Alcune reti bloccano l'UDP e sono pignole con il TCP in chiaro; TURN su TLS ne attraversa di più. Procurati un certificato per turn.example.com (va bene certbot). I suoi file sono leggibili solo da root, mentre coturn gira come utente turnserver, quindi dai a coturn una copia sua:

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

Aggiungi turns:turn.example.com:5349?transport=tcp all'elenco urls. I certificati durano poco, quindi metti la copia in un deploy hook di certbot: altrimenti TLS si rompe in silenzio al primo rinnovo.

Da sapere

  • TURN non rende buona una connessione cattiva. Aggiunge un salto, quindi metti il server vicino a chi ne ha bisogno.
  • Se usi un SFU, per esempio il videobridge di Jitsi, è un pezzo separato. TURN aiuta i client che non riescono a raggiungerlo direttamente.
  • Il segreto è tutto il modello di sicurezza. Tienilo fuori dal frontend e cambialo se mai dovesse trapelare.

Correlati

Pronto a fare il deploy? Paga in crypto, niente KYC — online in circa un minuto.

Fai il deploy ora →

FAQ

Perché le chiamate WebRTC hanno bisogno di un server TURN?

WebRTC prova a collegare i partecipanti direttamente, e di solito ci riesce. Quando entrambi i lati stanno dietro un NAT simmetrico o un firewall che blocca l'UDP — Wi-Fi d'albergo, reti aziendali, alcuni operatori mobili — non c'è un percorso diretto e la chiamata fallisce in silenzio. Un server TURN inoltra i flussi audio e video proprio per quelle chiamate; la quota citata di solito è più o meno una chiamata su dieci.

TURN può girare su un piano NAT?

No. I client si collegano su UDP e TCP 3478 e sull'intervallo di porte del relay, e un piano NAT accetta dall'esterno solo la tua porta SSH. Ti serve un piano con un IPv4 tutto suo.

Quanta banda consuma?

Ogni flusso inoltrato passa due volte dal server: entra da un lato ed esce verso l'altro. Una videochiamata a due da 1–2 Mbit/s per direzione fa pochi Mbit/s sul server. CPU e RAM se ne accorgono appena; il vero tetto è la porta da 1 Gbit/s.

Perché non mettere semplicemente utente e password fissi nell'app?

Perché tutto ciò che sta nel JavaScript del browser è pubblico, e un server TURN con password nota è un relay gratuito per tutto internet. Con use-auth-secret il tuo backend distribuisce credenziali che scadono, firmate con un segreto che il browser non vede mai.

Mi serve TLS sulla porta 5349?

Aiuta sulle reti che bloccano l'UDP e sono rigide con il TCP in chiaro. Aggiungilo quando il TURN normale funziona già: dai a coturn un certificato per il nome host TURN e apri 5349/tcp. Abbiamo testato anche il relay su TLS.

Commenti

Ancora nessun commento. Sii il primo.

Lascia un commento

I commenti sono moderati prima di comparire.