LGMdevs
Voltar ao blog
Equipe LGMdevs

WebRTC em rede móvel: por que o servidor TURN é obrigatório

Uma chamada de vídeo que funciona no Wi-Fi do escritório falha no 4G do usuário. O que STUN e TURN resolvem, como gerar credenciais temporárias e os outros cuidados que aprendemos construindo um interfone por vídeo.

ArquiteturaCloudBackend

No Portal dos Ipês, o visitante chama o morador por um interfone na portaria, e o morador atende por vídeo no próprio celular, de onde estiver. Em desenvolvimento, com os dois aparelhos na mesma rede Wi-Fi, qualquer configuração funciona. Em produção, o celular do morador está no 4G, e ali uma parte das chamadas não conecta sem ajuda. O motivo é o caminho da rede entre os dois aparelhos, e a solução é um servidor TURN, que por isso entrou na arquitetura antes do lançamento.

Como uma chamada WebRTC se conecta

WebRTC separa duas coisas:

  • Sinalização: os aparelhos trocam a descrição da chamada (SDP) e os possíveis endereços de cada um (candidatos ICE). Isso passa pelo seu servidor, normalmente por WebSocket.
  • Mídia: áudio e vídeo vão direto de um aparelho para o outro, sem passar pelo servidor, sempre que possível.

O "sempre que possível" é o problema. Cada aparelho está atrás de um roteador ou da rede da operadora, que traduz endereços (NAT). Para a mídia ir direto, cada lado precisa descobrir um endereço pelo qual o outro consiga alcançá-lo.

STUN resolve o caso fácil

Um servidor STUN responde ao aparelho: "é assim que eu vejo o seu endereço público". Com NATs comuns, isso basta para os dois lados se encontrarem, e a chamada fica totalmente ponto a ponto.

Redes móveis costumam usar CGNAT, em que a operadora compartilha um mesmo IP público entre muitos clientes. Quando esse NAT atribui uma porta de saída diferente para cada destino (o chamado NAT simétrico), o endereço que o STUN enxergou não serve para o outro aparelho, e a conexão direta falha.

TURN resolve o resto

Um servidor TURN retransmite a mídia: os dois aparelhos se conectam a ele, e ele repassa os pacotes. Funciona em praticamente qualquer rede, porque cada lado só precisa sair para a internet. O preço é que o vídeo passa a consumir banda do seu servidor.

O ICE escolhe sozinho: tenta o caminho direto primeiro e só usa o TURN quando nada mais funciona. Basta oferecer os dois:

const conexao = new RTCPeerConnection({
  iceServers: [
    { urls: "stun:stun.l.google.com:19302" },
    {
      urls: [
        "turn:turn.exemplo.com.br:3478?transport=udp",
        "turn:turn.exemplo.com.br:3478?transport=tcp",
        "turns:turn.exemplo.com.br:5349?transport=tcp",
      ],
      username,
      credential,
    },
  ],
})

Ofereça TCP e TLS na porta 5349 além do UDP: algumas redes corporativas e de hotel bloqueiam UDP e só deixam passar tráfego que parece HTTPS.

Usamos o coturn, de código aberto, num container ao lado da aplicação. No firewall, além das portas 3478 e 5349, é preciso liberar a faixa de portas que o TURN usa para retransmitir a mídia.

Credenciais temporárias, nunca fixas

Uma senha fixa de TURN no código do aplicativo vira, cedo ou tarde, um retransmissor gratuito para qualquer um. O coturn aceita credenciais temporárias derivadas de um segredo compartilhado (opção use-auth-secret): a API gera uma credencial por chamada, válida por pouco tempo, e o segredo nunca sai do servidor.

import { createHmac } from "node:crypto"
 
export function credenciaisTurn(segredo: string, usuarioId: string, validadeSegundos = 600) {
  const expiraEm = Math.floor(Date.now() / 1000) + validadeSegundos
  const username = `${expiraEm}:${usuarioId}`
  const credential = createHmac("sha1", segredo).update(username).digest("base64")
  return { username, credential }
}

O próprio TURN confere a assinatura e a validade, sem consultar a sua API.

Outros cuidados que só aparecem em produção

  • A rede muda no meio da chamada. O celular troca do Wi-Fi para o 4G e a conexão cai. RTCPeerConnection.restartIce() renegocia os caminhos sem desligar a chamada.
  • A qualidade precisa se adaptar. Com getStats() periódico dá para medir perda e atraso e reduzir resolução e taxa de quadros antes que o vídeo congele, chegando a só áudio quando a rede não aguenta.
  • O morador não está com o app aberto. A chamada precisa acordar o celular, o que no navegador significa Web Push. No iPhone, isso só funciona com o site instalado na tela de início (iOS 16.4 ou superior), e a interface precisa ensinar esse passo.
  • Teste fora do escritório. A página de teste de ICE do projeto WebRTC mostra quais candidatos o seu TURN devolve: se aparece um do tipo relay, o retransmissor está funcionando.

Quando dá para ficar sem TURN

Se as chamadas acontecem sempre dentro de uma rede controlada, como entre aparelhos da mesma empresa na mesma LAN, STUN, ou nem isso, resolve. Para qualquer produto em que um dos lados é um celular na rua, conte com o TURN desde o primeiro dia: é a diferença entre um vídeo que funciona no teste e um que funciona para o usuário.


Precisa de vídeo, voz ou tempo real no seu produto? Fale com a gente.

Fontes