−25%

en Windows con pago anual, hasta el 31/10. Ver planes

EQVPS
Empezar

VPS para un servidor TURN (coturn) para WebRTC

Las llamadas que fallan tras un NAT estricto necesitan un relay TURN. coturn en un servidor con IPv4 propia: puertos, credenciales temporales, config probada.

Tu app WebRTC funciona en tu wifi y falla justo al cliente que llama desde un hotel. El audio y vídeo punto a punto necesitan un camino entre los dos lados; cuando ambos están detrás de un NAT estricto, o un cortafuegos bloquea UDP, no hay camino y la llamada simplemente no conecta. Nadie ve un error: solo un «conectando…» interminable.

Un servidor TURN es el plan B para esas llamadas: los dos lados le envían su audio y vídeo, y él los retransmite. Si estás metiendo vídeo o voz en una app, montando Matrix o Jitsi para un equipo o haciendo chat de voz para un juego, necesitas uno. coturn es la implementación de código abierto de referencia, y es ligera.

Qué plan

TURN gasta poca CPU y memoria. Lo que usa es ancho de banda: cada flujo retransmitido pasa dos veces por el servidor, de entrada y de salida. En nuestros planes el tráfico es ilimitado a 1 Gbit/s, así que la pregunta es cuántas llamadas retransmitidas hay a la vez, no cuánto te van a cobrar.

Llamadas retransmitidas a la vezPlan
Unas pocas: un equipo, una app pequeñaNano-IP: 2 vCPU, 1 GB, 15 GB ($8/mes)
DecenasMicro-IP: 2 vCPU, 2 GB, 25 GB ($10/mes)
Más, o TURN junto a tu servidor de aplicaciónSmall-IP: 4 vCPU, 4 GB, 35 GB ($16/mes)

Tiene que ser un plan con su propia IPv4: TURN consiste en conexiones entrantes en muchos puertos, y los planes NAT solo aceptan SSH desde fuera. En nuestros planes con IP dedicada, la dirección pública está directamente en la interfaz del servidor, así que coturn la encuentra sin línea external-ip. Pon el servidor cerca de tus usuarios: Alemania o Finlandia; la disponibilidad se ve al hacer el pedido. Pago con cripto, sin KYC, si eso te importa.

Puertos que abrir: 3478 UDP y TCP, 49152–65535 UDP para el audio y vídeo retransmitidos, y 5349 TCP si añades TLS.

Instalación y configuración

Como root en Ubuntu 24.04 o Debian 12:

apt install -y coturn
ip -4 addr    # tu IP pública debería aparecer en la interfaz

Escribe la configuración con un secreto compartido nuevo:

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"    # tu backend necesita este valor
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable

No te saltes las líneas denied-peer-ip. Sin ellas, cualquiera con credenciales válidas puede usar tu relay para llegar a direcciones privadas, incluidos servicios del lado interno del propio servidor. Lo comprobamos: con estas líneas, un relay hacia una dirección privada se rechaza con «403 Forbidden IP».

Credenciales que caducan

Con use-auth-secret, coturn acepta un nombre de usuario que contiene una hora de caducidad y una contraseña que es un HMAC de ese nombre. Las genera tu backend; el secreto nunca sale del lado del servidor. En Node.js:

const crypto = require("crypto");

// Usuario/contraseña TURN temporales (el esquema TURN REST API que coturn entiende con 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")));

En el navegador, pide a tu backend un par nuevo y pásalo 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,
    },
  ],
});

Pruébalo

Desde el servidor, con el mismo esquema usando openssl (produce exactamente la misma contraseña que el código de Node.js; lo comparamos):

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

Al final quieres ver «Total lost packets 0». Con una contraseña incorrecta, el cliente se queda en «Cannot complete Allocation»: es el servidor haciendo su trabajo.

También lo comprobamos desde un Chromium real: con iceTransportPolicy: "relay" y credenciales frescas, el navegador obtuvo candidatos relay del servidor; con una contraseña mala, ninguno. Si quieres probar tu propia configuración igual, activa esa opción un momento: obliga a que todas las llamadas pasen por TURN.

TLS, si lo necesitas

Algunas redes bloquean UDP y son quisquillosas con el TCP plano; TURN sobre TLS atraviesa más de ellas. Consigue un certificado para turn.example.com (certbot vale). Sus archivos solo los puede leer root, mientras que coturn se ejecuta como el usuario turnserver, así que dale a coturn su propia copia:

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

Añade turns:turn.example.com:5349?transport=tcp a la lista urls. Los certificados duran poco, así que mete la copia en un deploy hook de certbot; si no, TLS se romperá sin avisar en la primera renovación.

Conviene saber

  • TURN no convierte una mala conexión en buena. Añade un salto, así que coloca el servidor cerca de quienes lo necesitan.
  • Si usas un SFU —el videobridge de Jitsi, por ejemplo—, es una pieza aparte. TURN ayuda a los clientes que no pueden llegar a él directamente.
  • El secreto es todo el modelo de seguridad. Mantenlo fuera del frontend y cámbialo si alguna vez se filtra.

Relacionado

¿Listo para desplegar? Paga en cripto, sin KYC — en línea en aproximadamente un minuto.

Desplegar →

Preguntas frecuentes

¿Por qué las llamadas WebRTC necesitan un servidor TURN?

WebRTC intenta conectar a los participantes directamente, y casi siempre lo consigue. Cuando ambos lados están detrás de un NAT simétrico o de un cortafuegos que bloquea UDP —wifi de hotel, redes de oficina, algunos operadores móviles—, no hay camino directo y la llamada falla sin avisar. Un servidor TURN retransmite el audio y el vídeo justo para esas llamadas; la proporción que suele citarse ronda una de cada diez.

¿Puede funcionar TURN en un plan NAT?

No. Los clientes se conectan a UDP y TCP 3478 y al rango de puertos de relay, y un plan NAT solo acepta desde fuera tu puerto SSH. Necesitas un plan con su propia IPv4.

¿Cuánto ancho de banda consume?

Cada flujo retransmitido pasa dos veces por el servidor: entra desde un lado y sale hacia el otro. Una videollamada de dos a 1–2 Mbit/s por sentido son unos pocos Mbit/s en el servidor. CPU y RAM apenas lo notan; el techo real es el puerto de 1 Gbit/s.

¿Por qué no poner un usuario y contraseña fijos en la app?

Porque todo lo que está en el JavaScript del navegador es público, y un servidor TURN con contraseña conocida es un relay gratis para todo internet. Con use-auth-secret, tu backend reparte credenciales que caducan, firmadas con un secreto que el navegador nunca ve.

¿Necesito TLS en el puerto 5349?

Ayuda en redes que bloquean UDP y son estrictas con el TCP plano. Añádelo cuando el TURN normal ya funcione: dale a coturn un certificado para el nombre de host TURN y abre 5349/tcp. También probamos el relay sobre TLS.

Comentarios

Aún no hay comentarios. Sé el primero.

Deja un comentario

Los comentarios se moderan antes de aparecer.