O IP que não era meu: CGNAT e o túnel da Cloudflare
Hoje vou contar como superei os obstáculos que impediam que meu Aspire fosse acessível na hierarquia do DNS, e como uma única tecnologia gratuita da Cloudflare resolveu tudo. Mas antes de entender essa ferramenta, vamos entender o que está acontecendo na rede.
A raiz do problema: escassez de IPv4
A causa raiz dos problemas que enfrentei é a escassez de IPv4. O IPv4 é um padrão de 32 bits, o que permite um máximo aproximado de 4 bilhões de endereços possíveis. É um número pequeno para o mundo online de 2026, bem diferente de como era na década de 1980, quando o formato foi lançado. Para economizar endereços, os provedores passaram a atribuí-los a seus clientes de forma dinâmica: emprestam quando o cliente conecta, recuperam quando ele desconecta. Assim, os IPs públicos das redes domésticas passaram a mudar de forma imprevisível. Só que essa prática se tornou insuficiente com o fluxo cada vez maior de aparelhos conectados. A escassez se intensificou ao ponto de os IPv4 passarem a ser compartilhados entre vários clientes, por meio do CGNAT, deixando até de ser IPs públicos no sentido tradicional. Vamos entender essa técnica, começando pelo NAT.
NAT: tradução na sua casa
NAT (Network Address Translation) é o processo de traduzir endereços privados em públicos (e vice-versa) na fronteira entre a rede local e a internet. Ele ocorre no roteador WiFi que o próprio provedor nos fornece quando assinamos um plano. Cada assinante tem um IP atribuído pelo provedor, e esse endereço identifica o próprio roteador doméstico, na interface voltada para a rede do provedor. O roteador cria uma rede local, a LAN (Local Area Network), e cada dispositivo conectado a ela, por wireless ou cabo ethernet, se torna um nó dessa rede. Para identificar seus diferentes nós, o roteador atribui (via DHCP) um endereço IP privado único a cada dispositivo conectado. Esse IP nunca é exposto na internet, sendo conhecido apenas pelo roteador.
Agora, quando um dispositivo faz uma requisição a um servidor na internet, como esse servidor sabe para onde responder? Toda vez que uma requisição entra ou sai da LAN, o roteador faz NAT usando portas, técnica conhecida como PAT (Port Address Translation). Por exemplo: um PC na LAN, com IP privado 192.168.0.10, faz uma requisição a partir da porta 50000. O roteador anota na tabela "192.168.0.10:50000 ↔ porta 61000", troca o cabeçalho IP + TCP/UDP para sair com o IP público do provedor e a porta 61000, e manda a requisição. O servidor lá fora responde para o IP público na porta 61000. Quando essa resposta chega no roteador, ele vê que veio na porta 61000, consulta a tabela, descobre que 61000 corresponde a 192.168.0.10:50000, e reescreve o cabeçalho para entregar ao PC de origem. A porta é a chave que desambigua qual dispositivo interno deve receber a resposta.
CGNAT: tradução no provedor
Um processo similar ocorre numa camada acima, na WAN (Wide Area Network), a grande rede privada do provedor. De forma simétrica à LAN, onde os dispositivos conectados ao roteador são nós com IPs privados, na WAN são os roteadores que figuram como nós com IPs privados, numa faixa específica (100.64.0.0/10, reservada para o CGNAT pela RFC 6598). Esses IPs são atribuídos por um equipamento chamado BNG (Broadband Network Gateway), via DHCP ou, mais comum no Brasil, PPPoE, o protocolo pelo qual o roteador se autentica com usuário e senha e mantém a sessão. O CGNAT (Carrier-Grade Network Address Translation) acontece num equipamento que fica a cargo de traduzir as requisições na borda entre a WAN e a internet. Assim, um único IPv4 público é compartilhado entre vários nós.
Na prática: a requisição do PC, que saiu do roteador como 100.64.0.10:61000, chega ao equipamento de CGNAT. Ele anota na própria tabela "100.64.0.10:61000 ↔ porta 7000", troca o cabeçalho para sair com o IP público 200.150.10.5 na porta 7000, e envia à internet. O servidor responde para 200.150.10.5:7000. O CGNAT consulta sua tabela, vê que 7000 corresponde a 100.64.0.10:61000, e entrega ao roteador. O roteador consulta a dele, vê que 61000 corresponde a 192.168.0.10:50000, e entrega ao PC. Duas tabelas, duas traduções desfeitas em sequência. Esse 200.150.10.5 é compartilhado entre centenas de assinantes, e nenhum deles é o dono.
Era esse o endereço que eu via ao buscar "meu IP", e era ele que eu não podia apontar no A record, porque ele endereça um equipamento do provedor, não o meu Aspire.
Por que isso impede um servidor
Um servidor é, por definição, uma máquina que aceita conexões de entrada vindas de origens que ela não conhece de antemão. Mas o Aspire está atrás de um CGNAT. Por tudo que vimos, só chega até ele o tráfego que responde a uma conexão que ele mesmo iniciou: foi na saída que o roteador e o provedor escreveram a trilha de volta em suas tabelas. Quando um pacote chega em 200.150.10.5 sem corresponder a nada na tabela do CGNAT, o provedor não tem como saber para qual dos milhares de assinantes ele iria, e o descarta.
Nem mesmo o port forwarding, recurso clássico de quem hospeda algo em casa, resolve o problema. A regra configurada no roteador diz o que fazer com as conexões não solicitadas que chegam até ele. Mas, sob CGNAT, o pacote é descartado uma camada antes, no equipamento do provedor, onde o assinante não configura nada. O pacote nem chega ao roteador para ser encaminhado.
A solução: Cloudflare Tunnel
Vimos que, sem os registros NAT nas tabelas de LAN e WAN, conexões de fora para dentro não funcionam. Só o tráfego de saída funciona. Mas como hospedar um servidor, que precisa receber tráfego de entrada? A Cloudflare resolve isso servindo como pivô público, e a configuração é simples.
No painel da Cloudflare, eu crio um túnel e defino uma rota: o domínio jpsalviano.com.br ligado ao endereço da aplicação no servidor, no meu caso http://nginx:80. Ao criar essa rota, a Cloudflare gera automaticamente o registro de DNS que aponta o domínio para os servidores dela, então eu não preciso configurar mais nada na zona.
No Aspire, eu rodo uma aplicação chamada cloudflared, autenticada com um token gerado nesse painel. Ela faz uma conexão de dentro para fora até a Cloudflare e a mantém permanentemente aberta. Como é tráfego de saída, passa pelo NAT e pelo CGNAT normalmente.
Agora o circuito fecha. Quando um usuário acessa jpsalviano.com.br, ele não fala com o Aspire, fala com a Cloudflare, que tem IP público de verdade. Ela recebe a requisição e a empurra pela conexão que o cloudflared deixou aberta, até o nginx. O nginx responde, a resposta volta pela mesma conexão até a Cloudflare, e a Cloudflare entrega ao usuário. Esse papel de receber a requisição e repassá-la para outro servidor se chama proxy reverso. O CGNAT deixou de ser problema, porque ninguém precisa mais iniciar uma conexão de fora para dentro.
Dentro do Aspire, o nginx funciona como porta de entrada única: ele recebe tudo que chega pelo túnel e encaminha para o container certo, seja o frontend ou o backend, conforme a rota. Esses três serviços rodam em containers Docker, e cada um cumpre um papel específico que merece sua própria explicação. No próximo post, abro essa caixa-preta: como o nginx roteia, e como o frontend e o backend se encaixam na stack.