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
| Porta | Protocolo | Função |
|---|---|---|
3478 | TCP | Porta de escuta do TURN (sinalização e allocate) |
3478 | UDP | Porta de escuta do TURN (sinalização e allocate) |
49152-65535 | UDP | Range 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)
- Acesse o console da Oracle Cloud
- Vá em Networking → Virtual Cloud Networks
- Clique na VCN da sua instância
- No menu lateral, clique em Security (ou Subnets → sua subnet → Security List)
- Clique na Security List associada
- Clique em Add Ingress Rules e adicione 3 regras:
| Source CIDR | IP Protocol | Destination Port Range |
|---|---|---|
0.0.0.0/0 | UDP | 3478 |
0.0.0.0/0 | TCP | 3478 |
0.0.0.0/0 | UDP | 49152-65535 |
- Salve
AWS (EC2)
- Acesse o console da AWS → EC2 → Security Groups
- Selecione o Security Group da sua instância
- Aba Inbound rules → Edit inbound rules
- 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:
# 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 saveEsse 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
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udp
sudo ufw allow 49152:65535/udpSe usar firewalld (CentOS/RHEL)
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 --reloadAtivando 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.
monky stop
monky config set turn true
monky startO 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:
sudo apt-get update
sudo apt-get install -y coturn
sudo systemctl disable --now coturn
command -v turnserverEm 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:
sudo bash scripts/install-turn.shEsse 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
monky statusNa seção Relay TURN, deve aparecer:
turn: sim
coturn: instalado
porta: 3478
status: ✔ acessívelSe aparecer ⚠ porta bloqueada, revise os firewalls acima.
Via rede (de outra máquina)
# Verifica se a porta está respondendo
nc -zv SEU_IP 3478Isso 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
# Verifica se o coturn está escutando
sudo ss -tlnup | grep 3478No 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
| Sintoma | Causa provável | Solução |
|---|---|---|
monky status mostra ⚠ porta bloqueada | Porta 3478 fechada no firewall do provedor ou do Linux | Siga os passos de abertura de porta acima |
| coturn sobe mas ninguém conecta via relay | Falta external-ip no config (VPS com NAT) | Atualize para v4.13.2+ — a detecção é automática |
monky status mostra coturn: indisponível | coturn não está instalado | Siga a instalação manual |
| O botão TURN está esmaecido no app | Servidor não é Linux, ou versão antiga | Atualize o servidor; TURN só funciona em Linux |
| Chamada conecta mas com muita latência | Normal para relay — a mídia passa pelo servidor | Considere uma VPS mais próxima dos membros |
Desligando
monky stop
monky config set turn false
monky startO 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:
- O Monky gera um shared secret aleatório e persiste no banco
- 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)
- Gera o
turnserver.confcom a diretivaexternal-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 - Spawna o coturn como processo filho
- Verifica se a porta 3478 está escutando e, se possível, se está acessível externamente
- No login de cada cliente, gera credenciais efêmeras (TURN REST API) com validade de 12 horas
- 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.
