Pular para o conteúdo

Relay de mídia (TURN) ​

Por padrão, a voz e o vídeo do Monky trafegam direto entre os participantes (P2P). O servidor só intermedeia a apresentação inicial. Isso é ótimo: menos latência e banda quase zero para quem hospeda.

O problema pode aparecer quando membros estão atrás de CGNAT — comum em internet móvel e em boa parte dos provedores residenciais no Brasil. Nesse cenário, dependendo do NAT e do firewall, os dois lados não conseguem uma rota direta, mesmo que cada um conecte normalmente com os demais.

O TURN oferece um caminho alternativo: o servidor repassa a mídia desse par. O WebRTC tenta usar a conectividade direta quando possível; o relay também precisa estar alcançável e com portas e credenciais corretas.

Esta página vale para o modo P2P Mesh

No modo SFU cada participante envia mídia ao servidor, em vez de diretamente aos outros. O TURN integrado do Monky é oferecido somente para P2P: o app e o CLI recusam habilitá-lo junto com SFU. Isso não dispensa uma rota acessível até o servidor. Se a mídia SFU não flui, confira IP anunciado, processo e portas do SFU, em vez de tentar habilitar uma combinação não suportada.

Requisitos ​

  • Host Linux com IP público (uma VPS típica). O Monky só gerencia a instalação e execução desse relay no Linux; não oferece esse controle no Windows ou macOS.
  • Portas abertas no firewall (veja abaixo).
  • Banda no host: cada par relayado consome upload e download do servidor.

Portas necessárias ​

PortaProtocoloFunção
3478TCPPorta de escuta do TURN (sinalização e allocate)
3478UDPPorta de escuta do TURN (sinalização e allocate)
49152-65535UDPRange de portas para relay de mídia

O processo online não comprova o caminho de mídia

Libere os transportes da configuração acima para atender redes com restrições diferentes. Alocação e tráfego são etapas distintas: a porta 3478 pode responder enquanto a faixa de relay continua bloqueada. Confira a reprodução de mídia, não apenas se o processo está rodando.

Abrindo portas no Linux ​

1. Firewall do provedor (painel web) ​

A maioria dos provedores de VPS (Oracle Cloud, AWS, Azure, GCP, Hetzner) tem um firewall fora da máquina, no nível da rede. Esse firewall precisa ser configurado no painel web do provedor — não basta mexer no iptables.

Oracle Cloud (OCI) ​

  1. Acesse o console da Oracle Cloud
  2. Vá em Networking → Virtual Cloud Networks
  3. Clique na VCN da sua instância
  4. No menu lateral, clique em Security (ou Subnets → sua subnet → Security List)
  5. Clique na Security List associada
  6. Clique em Add Ingress Rules e adicione 3 regras:
Source CIDRIP ProtocolDestination Port Range
0.0.0.0/0UDP3478
0.0.0.0/0TCP3478
0.0.0.0/0UDP49152-65535
  1. Salve

AWS (EC2) ​

  1. Acesse o console da AWS → EC2 → Security Groups
  2. Selecione o Security Group da sua instância
  3. Aba Inbound rules → Edit inbound rules
  4. Adicione as mesmas 3 regras (Custom UDP/TCP, source 0.0.0.0/0)

Outros provedores ​

Procure por "Security Groups", "Firewall Rules" ou "Network ACL" no painel do seu provedor. A lógica é a mesma: abrir as portas 3478 TCP/UDP e o range 49152-65535 UDP para qualquer origem.

2. Firewall do Linux (iptables) ​

Mesmo com o firewall do provedor aberto, o Linux pode ter regras próprias. Execute:

bash
# Abrir as portas
sudo iptables -I INPUT -p udp --dport 3478 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 3478 -j ACCEPT
sudo iptables -I INPUT -p udp --dport 49152:65535 -j ACCEPT

# Persistir (sobrevive a reboot)
sudo netfilter-persistent save

Esse comando pressupõe netfilter-persistent instalado e configurado. Em outras distribuições, use o mecanismo de persistência do firewall local.

Se usar ufw em vez de iptables

bash
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udp
sudo ufw allow 49152:65535/udp

Se usar firewalld (CentOS/RHEL)

bash
sudo firewall-cmd --permanent --add-port=3478/tcp
sudo firewall-cmd --permanent --add-port=3478/udp
sudo firewall-cmd --permanent --add-port=49152-65535/udp
sudo firewall-cmd --reload

Ativando o relay ​

Não reutilize o coturn de outro serviço

O Monky inicia sua própria instância. A instalação automática e o helper do repositório tentam desativar o serviço coturn da distribuição para liberar a porta 3478. Se outra aplicação depende desse serviço, planeje um host separado antes de continuar; não pare um relay compartilhado.

bash
monky stop
monky config set turn true
monky start

O Monky tenta instalar coturn pelo gerenciador de pacotes da distribuição quando necessário. Isso exige root ou sudo não interativo já autorizado; o processo não abre um prompt de senha. Também é possível ativar em Configurações do Servidor → Recursos de Voz e Vídeo no app.

Instalação manual do coturn ​

Sem esses privilégios, prepare o host antes. Em Debian/Ubuntu com systemd, num host dedicado ao relay do Monky:

bash
sudo apt-get update
sudo apt-get install -y coturn
sudo systemctl disable --now coturn
command -v turnserver

Em outras distribuições, use o pacote coturn e o gerenciador de serviços correspondentes. Depois volte a monky stop, monky config set turn true e monky start com o mesmo usuário que administra o servidor, sem executar o Monky inteiro como root.

Se você clonou o repositório, há também um helper. Execute a partir da raiz do checkout:

bash
sudo bash scripts/install-turn.sh

Esse arquivo não acompanha a instalação global do CLI. O caminho acima não funciona em uma pasta arbitrária após npm install -g.

Verificando se está funcionando ​

Via CLI ​

bash
monky status

Na seção Relay TURN, deve aparecer:

turn: sim
coturn: instalado
porta: 3478
status: ✔ acessível

Se aparecer ⚠ porta bloqueada, revise os firewalls acima.

Via rede (de outra máquina) ​

bash
# Verifica se a porta está respondendo
nc -zv SEU_IP 3478

Isso testa somente a conexão TCP. Não confirma o transporte UDP, a faixa de relay nem uma chamada completa entre duas redes.

No próprio servidor ​

bash
# Verifica se o coturn está escutando
sudo ss -tlnup | grep 3478

No app ​

Um participante conectado via relay ganha um ícone âmbar swap_horiz ao lado do nome, tanto no palco quanto na lista do canal de voz. Se ninguém mostrar o ícone, ou todos estão conectando direto (cenário ideal) ou o relay não subiu — confira com monky logs.

Troubleshooting ​

SintomaCausa provávelSolução
monky status mostra ⚠ porta bloqueadaPorta 3478 fechada no firewall do provedor ou do LinuxSiga os passos de abertura de porta acima
coturn sobe mas ninguém conecta via relayFalta external-ip no config (VPS com NAT)Atualize para v4.13.2+ — a detecção é automática
monky status mostra coturn: indisponívelcoturn não está instaladoSiga a instalação manual
O botão TURN está esmaecido no appServidor não é Linux, ou versão antigaAtualize o servidor; TURN só funciona em Linux
Chamada conecta mas com muita latênciaNormal para relay — a mídia passa pelo servidorConsidere uma VPS mais próxima dos membros

Desligando ​

bash
monky stop
monky config set turn false
monky start

O coturn permanece instalado mas não é iniciado. Nenhuma porta extra precisa ficar aberta.

Como funciona por baixo ​

O Monky usa o coturn, o servidor TURN de referência. Ao ligar o relay:

  1. O Monky gera um shared secret aleatório e persiste no banco
  2. No boot, detecta o IP público da VPS (via ipify.org) e o IP local da interface usada pela rota padrão (bridges do Docker e túneis de VPN não contam)
  3. Gera o turnserver.conf com a diretiva external-ip=PÚBLICO/PRIVADO — sem isso, em VPS com NAT (Oracle, AWS, etc.), o coturn anuncia o IP privado e os relay candidates ficam inalcançáveis
  4. Spawna o coturn como processo filho
  5. Verifica se a porta 3478 está escutando e, se possível, se está acessível externamente
  6. No login de cada cliente, gera credenciais efêmeras (TURN REST API) com validade de 12 horas
  7. O WebRTC do cliente tenta a rota direta e só usa o relay se necessário

O que o relay recusa ​

O relay só repassa UDP (no-tcp-relay) e só em direção à internet pública: loopback, redes privadas (10/8, 172.16/12, 192.168/16), CGNAT (100.64/10, a faixa do Tailscale) e as demais faixas reservadas ficam negadas. Assim, quem tem credenciais não usa o relay para alcançar serviços da sua rede interna.

Exceção atrás de NAT. Quando o servidor está atrás de NAT (o mapeamento external-ip=PÚBLICO/PRIVADO acima), o Monky também grava allowed-peer-ip=PRIVADO. Quando os dois membros de uma chamada precisam do relay, a mídia faz cliente → TURN → TURN → cliente, e o coturn enxerga essa segunda perna no IP privado do host; sem a exceção, essas chamadas não conectam. O efeito colateral: o relay passa a entregar UDP a qualquer serviço do próprio host que escute nesse IP privado (ou em todos os endereços, 0.0.0.0). TCP continua fechado, e o resto da rede interna continua negado. Se o host roda um serviço UDP que não deve ficar ao alcance dos membros, faça-o escutar em 127.0.0.1 ou bloqueie-o no firewall. Um host com o IP público na própria interface não ganha mapeamento nem exceção.