Murad Library
Murad LibraryREF-0315MD

Expondo serviços de streaming atrás de CGNAT

Catalogued
Reading
7 min read

Há pouco mais de dois anos saí da Vero (provedor de internet), onde eu tinha um IP público funcional, para a TIM Ultrafibra. O motivo que me levou a trocar de provedor foi simples: a TIM oferecia velocidades monstruosas e eu tinha equipamento para suportá-las.

Na Vero eu já me dava por satisfeito com meu 1 Gb, mas eu queria os 2.5 Gb da TIM. Então fui lá e troquei.

Minha triste surpresa foi ver que a TIM não oferecia IP público — e nem dava espaço para negociar. Depois de tentativas extremamente fracassadas, decidi arrumar outro jeito de expor alguns serviços de streaming.

Ainda bem que tenho uma experiência decente com redes, o que me poupou de muita dor de cabeça. Mas eu ainda precisaria de mais conhecimento se quisesse o sistema funcionando de forma plena.

Quando se usa CGNAT — o famoso IP compartilhado —, a experiência no quesito streaming (upload) costuma ser bem ruim, por dois problemas da rede:

  1. MTU mal configurado.
  2. Portas UDP reciclando em velocidades extremas.

Há outros motivos por aí, mas esses dois são os principais que tornam a experiência terrível. É por isso que muitos tentam negociar IPs públicos com seus provedores, e é a mesma razão das famosas dores de cabeça em jogos FPS.

Vamos ao que tentei e ao que funcionou.

Primeiras tentativas: Cloudflare e Tailscale

A primeira solução que me veio à cabeça foi expor os serviços pela Cloudflare, via Tunnel, ou pela Tailscale. Não cheguei a testar a Tailscale.

A Cloudflare funcionou perfeitamente bem: era rápida, robusta, e tinha um keep-alive excelente para negociar diante das mudanças bruscas do UDP. Mas tinha um problema — o mesmo compartilhado com a Tailscale (por isso nem tentei): pelas políticas dessas empresas, você não pode servir streaming. Se quisesse, teria que usar os servidores deles, ou seja, pagando. O risco é alto: podem te banir dos serviços sem maiores explicações.

Eu tenho diversos serviços rodando via Cloudflare e não podia correr esse risco. Migrar para o Tailscale Funnel era inviável pelo mesmo motivo da Cloudflare. E eu não queria manter uma rede fechada estilo WireGuard, em que só eu teria acesso: meus primos e parentes não são muito tech, e isso custaria tempo de configuração. Eu queria simplesmente mandar um domínio e eles acessarem.

O que fazer?

Pangolin: bom, mas só bom

Lembrei do Pangolin. Talvez, se eu pegasse uma VPS bem baratinha e rodasse o Pangolin nela, eu conseguisse "emular" os serviços oferecidos pelo Cloudflare Tunnel em nível semelhante.

A imagem do container do Pangolin seria perfeita: rodaria com Docker e já vinha com Traefik, Gerbil e CrowdSec. Era só subir, configurar os domínios, instalar o Newt nas máquinas locais e pronto. Eu estaria fazendo streaming daqui de casa, atrás de CGNAT e exposto. Meu problema deveria estar resolvido.

Deixei rodando por uns dois meses, mas a lentidão estava me irritando. Eu ainda não havia explorado os reais motivos, até que enfim não tive escolha. O serviço estava bom — mas só bom. E eu queria excelente.

Minha primeira ação foi fazer testes básicos: verificar rotas, DNS, MTU, etc. Interessante que, apesar de esse não ser o coração do problema, resolvi alguns outros problemas no caminho. Ou seja, tinha uma leve influência também.

Mas logs e testes mais precisos mostraram algo que eu já suspeitava: UDP e ping/keep-alive. O UDP reciclava de forma extremamente agressiva, em intervalos curtíssimos, e para streaming isso era o horror puro. Imagine tentar carregar vídeo, player, range request, WebSocket de chat... tudo isso precisa fluir bem.

Um novo problema que exigiria criatividade para resolver. A decisão foi parar de tentar fazer o túnel UDP se comportar bem em um CGNAT agressivo e trocar o miolo da arquitetura por um túnel TCP persistente. Mas como? Eu não sabia. Então deixei meio que em stand-by. Afinal, eu estava sem tempo para brincar com meus streamings, e eles já estavam de pé — mesmo que de forma inadequada.

E passaram-se algumas semanas.

O acaso: FRP

Eu estava na dashboard do Unraid e comecei a olhar os apps que tinham na loja. Então, por puro acaso, vi algo que me chamou atenção: FRP. Sinceramente, eu nunca tinha usado, e para mim não passava de mais um serviço de proxy qualquer. Dei uma olhada na imagem só por curiosidade — sabe quando você olha mas não vê (lê)? Eu nem estava pensando mais na exposição dos meus streamings, e algo me chamou atenção: o "F" no começo de FRP, que significa Fast.

Fiquei mais curioso. Por que ela seria diferente? Por que fast?

Estudando um pouco, a explicação foi simples.

O FRP (Fast Reverse Proxy) foi criado justamente para expor serviços locais que estão atrás de NAT/firewall, usando um servidor público como relay. A arquitetura é:

  • frps = servidor FRP no VPS com IP público.
  • frpc = cliente FRP na máquina local, atrás do NAT/CGNAT.

Com isso, a máquina local abre uma conexão de saída para o VPS. O VPS passa a expor portas públicas (temporárias ou internas), que depois são usadas pelo Traefik como backends HTTP.

O Pangolin (Newt/Gerbil) usa uma arquitetura mais completa: Traefik + identidade + túneis WireGuard/Gerbil/Newt. É ótimo como "plataforma", mas adiciona mais peças móveis. A própria documentação do Pangolin descreve o Gerbil como gerenciador de túneis WireGuard e o Newt como cliente de borda.

O FRP foi feito exatamente para expor serviço local atrás de NAT/firewall usando um servidor público como relay, e suporta TCP, UDP, HTTP e HTTPS.

No meu caso, a vantagem era essa. As situações eram:

  • FRP = conexão TCP persistente saindo da rede local → VPS público → Traefik.
  • Pangolin = túnel/overlay mais sofisticado → mais dependente do comportamento do túnel.

A solução era melhor não porque o FRP é "superior" ao Pangolin em tudo, mas porque ele resolve o gargalo real: parar de brigar com UDP em um CGNAT ruim.

A arquitetura final

Usuário externo
  ↓ HTTPS
Traefik no VPS (Pangolin)
  ↓ HTTP interno para a porta do FRP
frps no VPS (Pangolin)
  ↓ túnel TCP persistente
frpc na máquina local
  ↓
Serviço local de mídia

Na VPS que já tinha o Pangolin, basicamente instalei e configurei o frps (servidor) junto com um token. Cada máquina que seria cliente recebeu o frpc (cliente) com o token do servidor.

A configuração era até simples: você vincula o IP/porta, coloca o token, valida e liga.

Mas havia uma pegadinha: foi necessário fazer algo um pouco diferente no Traefik que já tínhamos no servidor. Em vez de recriar os recursos pela UI do Pangolin, usei o File Provider dinâmico. O resultado foi espantoso — o ganho prático veio na hora.

Antes, o acesso via Newt/Pangolin sofria com TTFB alto e instabilidade causada pelo CGNAT. Depois da troca para FRP, os serviços passaram a responder imediatamente e com muita estabilidade.

Por que funcionou

A mudança funcionou porque o problema não era apenas "proxy lento". Era arquitetura.

O Cloudflare Tunnel era rápido, mas inadequado como solução principal para streaming self-hosted pesado dentro das políticas corretas. O Newt/Pangolin era elegante para expor serviços privados, mas o CGNAT agressivo estava prejudicando a estabilidade do caminho UDP. O FRP resolveu o ponto exato: criou um túnel TCP persistente entre as máquinas locais e o VPS público.

O Traefik continuou fazendo o que faz bem: receber HTTPS, aplicar regras por domínio e encaminhar para os backends internos. O FRP ficou com o transporte. Cada ferramenta no seu papel certo.

Em breve farei um pequeno tutorial de como isso foi configurado e como você pode fazer na sua rede.

Até mais.

Did this resonate?

Related documents