---
title: "IPv6 na prática: como testar, ativar dual-stack e parar de pagar por IPv4"
description: "IPv4 virou item de fatura na nuvem e CGNAT esconde o custo no acesso. Um roteiro com comandos para testar IPv6, configurar servidor e firewall, e corrigir os bugs de aplicação que aparecem."
date: "2026-09-29"
tags: ["ipv6", "ipv4", "cgnat", "redes", "cloud", "linux", "brasil"]
url: "https://abjr.dev/noticias/ipv6-cgnat-custo-ipv4"
---

O IPv6 foi especificado nos anos 1990 e revisado no RFC 8200 em 2017. Por muito tempo, a desculpa para não usar foi "ninguém usa". Essa desculpa acabou: as estatísticas do Google mostram algo perto de metade dos acessos chegando por IPv6, e o Brasil aparece de forma consistente entre os países com maior adoção, puxado pelas operadoras móveis e pelos provedores regionais.

Enquanto isso, o IPv4 ganhou preço. Os registros regionais esgotaram os estoques, e desde fevereiro de 2024 a AWS cobra por hora cada IPv4 público, inclusive os que estão em uso. São cerca de US$ 3,65 por endereço por mês. Parece pouco até alguém somar load balancers, NAT gateways e instâncias com IP público numa conta grande.

Este texto é o roteiro que eu seguiria para colocar um serviço em IPv6 sem surpresa: testar, ativar, filtrar direito e corrigir os bugs de aplicação que só aparecem quando o endereço tem dois-pontos.

## Primeiro, descubra se você já tem IPv6

Na sua máquina:

```bash
ip -6 addr show scope global
ip -6 route show default
curl -6 -s https://ifconfig.co
```

Se o primeiro comando mostra um endereço começando com `2` ou `3` (espaço global unicast `2000::/3`), e o `curl -6` responde, você tem IPv6 de ponta a ponta. Endereços `fe80::` são link-local e não contam. Endereços `fd..` são locais únicos (ULA), equivalentes a uma rede privada.

Para o seu domínio:

```bash
dig +short A exemplo.com.br
dig +short AAAA exemplo.com.br
curl -6 -sI https://exemplo.com.br | head -1
```

Sem registro `AAAA`, nenhum cliente vai tentar IPv6, mesmo que o servidor esteja pronto.

## Como o cliente escolhe entre IPv4 e IPv6

Clientes modernos usam **Happy Eyeballs** (RFC 8305): resolvem `A` e `AAAA`, tentam IPv6 primeiro e, se ele demora algumas centenas de milissegundos, abrem IPv4 em paralelo. Quem conectar primeiro vence.

Isso tem um efeito colateral importante: **IPv6 quebrado não aparece como erro**. Aparece como lentidão leve, porque o cliente cai no IPv4 em silêncio. Já vi `AAAA` apontando para um endereço sem firewall liberado passar meses despercebido. Por isso o teste precisa forçar o protocolo (`curl -6`, `curl -4`) em vez de confiar no navegador.

## Servidor: o mínimo para dual-stack

### Nginx

```nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name exemplo.com.br;
    # ...
}
```

O `listen [::]:443` é o que faltava na maioria das configurações antigas. Depois, confira quem está escutando:

```bash
ss -ltnp | grep ':443'
```

### Docker

O Docker não habilita IPv6 nas redes por padrão. Em `/etc/docker/daemon.json`:

```json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00:cafe::/64"
}
```

Com um prefixo ULA, os containers saem para a internet via NAT66 feito pelo Docker, espelhando o que já acontece no IPv4. Se o provedor delegou um prefixo roteável para o host, dá para usar esse prefixo e dispensar o NAT, mas aí o firewall precisa proteger cada container diretamente.

### Nuvem

Na AWS, os blocos para sair do IPv4 são: sub-redes *dual-stack* ou *IPv6-only*, **egress-only internet gateway** para saída IPv6 sem permitir entrada, e **NAT64 no NAT Gateway** junto com **DNS64 no Route 53 Resolver**, para que instâncias só IPv6 alcancem destinos que ainda são só IPv4. Load balancers em modo dual-stack aceitam clientes nos dois protocolos e falam IPv4 com o alvo, o que permite migrar a borda antes do resto.

## Firewall: não bloqueie ICMPv6

Esse é o erro mais comum e mais caro. No IPv4, muita gente bloqueia ICMP inteiro e quase nada quebra. No IPv6, isso quebra a rede:

- **Neighbor Discovery** (tipos 133 a 137) substitui o ARP. Sem ele, o host não acha nem o roteador.
- **Packet Too Big** (tipo 2) é como o IPv6 descobre o MTU do caminho. Roteadores IPv6 não fragmentam pacotes; eles descartam e avisam. Bloquear esse aviso gera conexões que abrem, trocam alguns bytes e travam quando o primeiro pacote grande passa.

O RFC 4890 lista o que filtrar e o que deixar passar. Em `nftables`, o mínimo razoável fica assim:

```text
table inet filtro {
  chain entrada {
    type filter hook input priority 0; policy drop;
    ct state established,related accept
    iif lo accept
    icmpv6 type { destination-unreachable, packet-too-big, time-exceeded,
                  parameter-problem, echo-request, nd-router-advert,
                  nd-neighbor-solicit, nd-neighbor-advert } accept
    tcp dport { 22, 80, 443 } accept
  }
}
```

A família `inet` aplica a mesma regra a IPv4 e IPv6. Evita o clássico "liberei a porta no iptables e esqueci o ip6tables".

## Os bugs que aparecem na aplicação

A rede costuma ser a parte fácil. O que quebra é código que assumiu que endereço IP tem quatro números e três pontos.

**Coluna pequena demais.** `VARCHAR(15)` corta um IPv6, que pode ter até 39 caracteres na forma textual (e mais com zona ou IPv4 embutido). No PostgreSQL, use o tipo `inet`: valida, compara, e aceita consultas de rede como `ip << '2001:db8::/32'`.

**Separar host e porta pelo `:`.** `split(":")` em `2001:db8::1:8080` não funciona. Em URL, o IPv6 vai entre colchetes: `https://[2001:db8::1]:8080/`. Use a função de parsing da linguagem, não split manual.

**Rate limit e bloqueio por IP.** No IPv4, um IP costuma ser uma casa ou um CGNAT inteiro. No IPv6, um único cliente recebe um prefixo `/64` inteiro, 18 quintilhões de endereços, e pode trocar de endereço à vontade (as extensões de privacidade do RFC 8981 fazem isso sozinhas). Rate limit por endereço individual é inútil. Agrupe por `/64`, e considere `/56` ou `/48` para bloqueios mais agressivos.

**Listas de permissão.** Allowlist de IP de parceiro, painel administrativo liberado para "o IP do escritório": se o escritório ganhou IPv6 e o cliente preferiu IPv6, o acesso cai. Toda allowlist precisa das duas famílias.

**Logs e geolocalização.** Parsers de log com regex de IPv4, bases de GeoIP antigas e dashboards que agrupam por "IP" tratam cada endereço IPv6 temporário como um visitante diferente.

## CGNAT: o custo que o usuário não vê

Do lado do acesso, o provedor sem IPv4 para todos coloca clientes atrás de **CGNAT**, no bloco `100.64.0.0/10` reservado pelo RFC 6598. Se o seu roteador recebe um IP nessa faixa, você está atrás de CGNAT. Funciona para navegar, mas:

- impede conexões de entrada: câmera, servidor caseiro, alguns jogos, acesso remoto;
- concentra muitos clientes num mesmo IPv4 público, então um bloqueio por reputação atinge todos;
- obriga o provedor a guardar porta e horário de cada sessão para identificar um usuário, como o RFC 6888 já antecipava.

Com IPv6, cada cliente volta a ter endereço global próprio. É o motivo prático pelo qual serviços de acesso remoto e jogos vêm adotando IPv6: é o único caminho direto até o usuário atrás de CGNAT.

No celular, o **464XLAT** (RFC 6877) permite que a rede interna da operadora seja só IPv6 e ainda entregue IPv4 aos apps que precisam, traduzindo nas pontas. Muitas redes móveis brasileiras já funcionam assim, e você nem percebe.

## Checklist

- [ ] Registro `AAAA` publicado para cada nome que tem `A`.
- [ ] `curl -6` e `curl -4` testados separadamente, de fora da sua rede.
- [ ] Servidor escutando em `[::]` nas mesmas portas que em `0.0.0.0`.
- [ ] Firewall em família `inet` (ou regras IPv6 equivalentes) com ICMPv6 essencial liberado.
- [ ] Colunas de IP como `inet` ou texto com 45+ caracteres; parsing de host/porta com colchetes.
- [ ] Rate limit e bloqueios agregados por prefixo `/64`.
- [ ] Allowlists, logs e alertas revisados para as duas famílias.
- [ ] Na nuvem: inventário de IPv4 públicos e plano para trocar o que for só saída por IPv6 + NAT64.

## Em resumo

IPv6 deixou de ser projeto de futuro: é o caminho padrão de boa parte do tráfego móvel e residencial, inclusive no Brasil. O IPv4 continua existindo, mas agora tem preço explícito na fatura e custo operacional no CGNAT. A migração em si é curta. O que dá trabalho é o código e o firewall que assumiram, sem dizer, que só existia IPv4.

Para quem quiser o contexto de como chegamos aqui, a [história da internet](/noticias/historia-da-internet) cobre de onde vieram o endereçamento de 32 bits e o NAT que o IPv6 tenta aposentar.

## Fontes

- [Google IPv6 Statistics](https://www.google.com/intl/en/ipv6/statistics.html)
- [RFC 8200 — IPv6 Specification](https://www.rfc-editor.org/rfc/rfc8200)
- [RFC 8305 — Happy Eyeballs v2](https://www.rfc-editor.org/rfc/rfc8305)
- [RFC 4890 — Recomendações de filtragem de ICMPv6](https://www.rfc-editor.org/rfc/rfc4890)
- [RFC 8981 — Endereços temporários (privacy extensions)](https://www.rfc-editor.org/rfc/rfc8981)
- [RFC 6598 — Shared Address Space (100.64.0.0/10)](https://www.rfc-editor.org/rfc/rfc6598)
- [RFC 6888 — Requisitos para CGN](https://www.rfc-editor.org/rfc/rfc6888)
- [RFC 6877 — 464XLAT](https://www.rfc-editor.org/rfc/rfc6877)
- [AWS — cobrança de IPv4 público](https://aws.amazon.com/blogs/aws/new-aws-public-ipv4-address-charge-public-ip-insights/)
- [Docker — IPv6 networking](https://docs.docker.com/engine/daemon/ipv6/)
- [IPv6.br (NIC.br)](https://ipv6.br/)
