Todos os artigos
176 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

IPv4 vs IPv6: diferenças, NAT e o que muda no seu código

IPv4 tem 32 bits e esgotou; IPv6 tem 128 e dispensa NAT. Veja as diferenças em uma tabela e o que muda no bind, no banco e nos logs da sua aplicação.

IPv4 vs IPv6: diferenças, NAT e o que muda no seu código
COVER · Tutoriais

Já perdi uma tarde com um bug que só acontecia para parte dos usuários: o rate limit por IP bloqueava gente que nunca tinha batido no limite. A causa era banal. O servidor escutava em ::, os clientes IPv4 chegavam como ::ffff:189.6.x.x, os clientes IPv6 chegavam como 2804:..., e o código que normalizava o IP só conhecia o formato com pontos. Metade da chave do rate limit era lixo. Ninguém no time tinha pensado em IPv6 porque "isso é coisa de infra".

Não é. Este post compara IPv4 e IPv6 do jeito que importa para quem escreve código: a tabela de diferenças, por que o IPv4 acabou, onde o NAT entra e o que muda no bind, no banco e nos logs. A parte de IP público, privado, fixo e dinâmico (e o CGNAT do ponto de vista do usuário) está no post irmão IP público, privado, fixo e dinâmico.

IPv4 vs IPv6: a tabela de diferenças

IPv4 IPv6
Tamanho do endereço 32 bits 128 bits
Notação 4 octetos decimais: 192.0.2.10 8 grupos hexadecimais: 2001:db8::10
Total de endereços 2³² ≈ 4,3 bilhões 2¹²⁸ ≈ 3,4 × 10³⁸
NAT Onipresente (casa, operadora, cloud) Desnecessário: cada dispositivo pode ter IP global
Broadcast Existe (255.255.255.255) Não existe; usa multicast (ff02::1)
Cabeçalho 20 a 60 bytes, com checksum Fixo em 40 bytes, sem checksum, com extension headers
Configuração Manual ou DHCP SLAAC (autoconfiguração), DHCPv6 opcional
IPsec Opcional Recomendado (SHOULD), não obrigatório
Registro DNS A AAAA
Loopback 127.0.0.1 ::1
Rede privada RFC 1918 (10/8, 172.16/12, 192.168/16) ULA (fc00::/7)

Os dois protocolos não conversam entre si. Um host só-IPv4 não fala com um host só-IPv6 sem um mecanismo de tradução no meio, e é por isso que a internet roda em dual-stack: os dois protocolos lado a lado, possivelmente por mais algumas décadas.

IPv4: 32 bits que acabaram

O endereço IPv4 tem 32 bits, escritos como quatro números de 0 a 255. São 4.294.967.296 combinações, um número que parecia generoso quando a RFC 791 saiu, em 1981, e que deixou de ser há muito tempo. Parte do espaço nem é utilizável publicamente: loopback (127.0.0.0/8), link-local (169.254.0.0/16), multicast (224.0.0.0/4) e as faixas privadas da RFC 1918.

O estoque central da IANA acabou em fevereiro de 2011, quando os últimos blocos foram distribuídos aos cinco registros regionais. A LACNIC, que atende a América Latina e o Caribe, esgotou o seu em agosto de 2020. Desde então, quem precisa de IPv4 novo compra no mercado secundário ou divide os que já tem.

Dividir é o trabalho do NAT. O roteador da sua casa troca o IP privado de cada dispositivo pelo IP público dele na saída e desfaz a troca na volta. Quando nem a operadora tem IPv4 público para cada cliente, ela empilha mais um NAT na própria rede: o CGNAT. Funciona para navegar, mas quebra o modelo de ponta a ponta da internet: conexões que vêm de fora não sabem para qual dispositivo ir, e hospedar qualquer coisa exige port forwarding, túnel ou um IP contratado. Os detalhes de porta e encaminhamento estão em portas de rede.

IPv6: notação e o que muda

O endereço IPv6 tem 128 bits, escritos como oito grupos de quatro dígitos hexadecimais:

2001:0db8:85a3:0000:0000:8a2e:0370:7334
2001:db8:85a3::8a2e:370:7334      # mesma coisa, abreviado

Duas regras de abreviação: zeros à esquerda de cada grupo podem sumir, e uma única sequência de grupos zerados pode virar ::. O formato canônico que os sistemas devem gerar (minúsculo, sempre a forma mais curta) está na RFC 5952. Isso importa para comparação de strings: 2001:DB8::1 e 2001:0db8:0:0:0:0:0:1 são o mesmo endereço.

São 2¹²⁸ endereços, cerca de 3,4 × 10³⁸. Dividindo pela superfície da Terra (uns 510 milhões de km²), dá algo como 6,7 × 10²³ endereços por metro quadrado. Com essa folga, cada rede local recebe um prefixo /64 inteiro e cada dispositivo pode ter um endereço global, sem NAT.

Os tipos de endereço que você vai ver no ip addr:

Prefixo Tipo Equivalente IPv4
::1/128 Loopback 127.0.0.1
fe80::/10 Link-local, configurado sozinho em toda interface 169.254.0.0/16
fc00::/7 Unique Local (ULA), rede privada RFC 1918
2000::/3 Global unicast (público) IPs públicos

Algumas diferenças de protocolo também aparecem no dia a dia. O cabeçalho IPv6 tem tamanho fixo de 40 bytes e não tem checksum (a verificação fica para as camadas de cima). Não existe broadcast: o que era broadcast vira multicast. Um dispositivo consegue montar o próprio endereço global com SLAAC, a partir do prefixo que o roteador anuncia, sem DHCP.

E um mito comum: "IPv6 tem IPsec obrigatório". Teve, na especificação original. A RFC 6434, de 2011, rebaixou o suporte a IPsec de MUST para SHOULD, e a RFC 8504 (2019), que a substituiu, manteve o SHOULD. IPv6 não é mais seguro que IPv4 por definição; a criptografia continua sendo TLS, WireGuard ou o que você configurar.

Por que a adoção do IPv6 demorou

A primeira especificação do IPv6 é a RFC 1883, de dezembro de 1995. Ela foi revisada pela RFC 2460 (1998) e a versão atual é a RFC 8200, de 2017. São três décadas, e a migração ainda está no meio.

Pelos dados do Google, que mede a fração de usuários que chega aos seus serviços por IPv6, a adoção global oscilava entre 47% e 51% no começo de novembro de 2026, com picos nos fins de semana (mais acesso de casa e do celular, menos de rede corporativa). No mesmo levantamento, o Brasil aparecia com 57,5% em 7 de novembro de 2026. Esses números mudam toda semana; consulte a página para o valor atual.

Os motivos da demora são conhecidos. Ligar IPv6 não desliga o IPv4, então quem migra passa a operar dois stacks. O NAT e o mercado secundário tiraram a urgência. E muito equipamento antigo (roteadores, firewalls, sistemas embarcados) não suportava IPv6 sem troca de hardware. Quem puxou a adoção foram as operadoras móveis, que nunca tiveram IPv4 para todos os celulares, e os grandes provedores de conteúdo.

O que muda no seu código

Esta é a parte que eu gostaria de ter lido antes do bug do rate limit.

Bind em 0.0.0.0 vs ::. 0.0.0.0 escuta em todas as interfaces IPv4. :: escuta em todas as interfaces IPv6, e se ele também aceita IPv4 depende do sistema operacional. No Linux, o padrão é aceitar: net.ipv6.bindv6only vale 0, e um socket em :: recebe conexões IPv4 como endereços ::ffff:a.b.c.d. No Windows, a documentação da Microsoft diz o contrário: o socket IPv6 é só-IPv6 por padrão, e você precisa zerar IPV6_V6ONLY antes do bind. Rodei isto num container Linux:

// Node 22: sem host, o listen tenta "::" (e no Linux aceita IPv4 também)
const net = require('net');
const srv = net.createServer(s => console.log(s.remoteAddress, s.remoteFamily));
srv.listen(3000, () => net.connect(3000, '127.0.0.1'));
// saída: ::ffff:127.0.0.1 IPv6
# Python 3.8+: dual-stack explícito, sem depender do padrão do SO
import socket
srv = socket.create_server(("", 8000), family=socket.AF_INET6, dualstack_ipv6=True)
# cliente 127.0.0.1 aparece como ::ffff:127.0.0.1; cliente ::1 aparece como ::1

A consequência prática é a do meu bug: o mesmo cliente IPv4 pode aparecer como 189.6.10.20 num servidor e como ::ffff:189.6.10.20 em outro. Normalize antes de usar o IP como chave (rate limit, allowlist, auditoria). Em Python, ipaddress.ip_address(x).ipv4_mapped devolve o IPv4 embutido; em outras linguagens há equivalente.

Armazenamento. No PostgreSQL, use o tipo inet (ou cidr para redes): aceita os dois protocolos e compara corretamente. No MySQL, VARBINARY(16) com INET6_ATON() e INET6_NTOA(). Se insistir em texto, VARCHAR(39) cabe o maior endereço IPv6 em hexadecimal puro (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff), mas não a forma com IPv4 embutido sem abreviação, 0000:0000:0000:0000:0000:ffff:255.255.255.255, que tem 45 caracteres. É por isso que a constante INET6_ADDRSTRLEN do C vale 46 (45 mais o terminador). Use 45 e não pense mais nisso.

Parsing e logs. Regex de IPv4 não pega IPv6, e regex de IPv6 escrita à mão quase sempre esquece um caso. Use a biblioteca da linguagem (ipaddress no Python, net.ParseIP no Go, inet_pton no C). Cuidado também com host:porta: em IPv6 os dois pontos são parte do endereço, então a forma correta em URL e em log é [2001:db8::1]:443, com colchetes.

Rate limit por IP. Em IPv4, um IP costuma ser um cliente (ou um CGNAT cheio deles). Em IPv6, um único cliente tem um /64 inteiro e pode trocar de endereço à vontade dentro dele, de propósito, por privacidade. Limitar por endereço IPv6 completo é inútil; o costume é agrupar por prefixo /64.

DNS e Happy Eyeballs. Para receber tráfego IPv6, o domínio precisa de um registro AAAA, além do A (veja tipos de registro DNS). Quando os dois existem, o cliente usa Happy Eyeballs, hoje especificado na RFC 8305 (2017, substituiu a RFC 6555): tenta IPv6 primeiro e, se a conexão não sair em cerca de 250 ms, dispara IPv4 em paralelo e fica com o que responder antes. Se o domínio não tem AAAA, o cliente vai direto para IPv4, sem atraso nenhum.

Para saber se a sua conexão sai por IPv4 ou IPv6, abro o Qual é meu IP: ele mostra o IP público da sua conexão, a família e o provedor (ASN). A mesma página tem uma calculadora CIDR para as faixas IPv4 e um conversor que gera o endereço IPv4-mapeado (::ffff:...) de um IPv4, útil para entender o que vai aparecer no log de um servidor dual-stack.

Perguntas frequentes

Qual a principal diferença entre IPv4 e IPv6?

O tamanho do endereço: 32 bits no IPv4 (cerca de 4,3 bilhões de endereços) contra 128 bits no IPv6 (cerca de 3,4 × 10³⁸). Disso decorrem as outras diferenças: o IPv6 dispensa NAT, troca broadcast por multicast, tem cabeçalho fixo de 40 bytes e permite autoconfiguração com SLAAC.

IPv6 é mais rápido que IPv4?

Não por natureza. A velocidade depende do caminho entre as duas pontas. Sem NAT no caminho, o IPv6 às vezes tem latência um pouco menor, e às vezes a rota IPv6 é pior que a IPv4. Na média, a diferença é pequena.

Meu site precisa ter IPv6?

Não é obrigatório: se o domínio não publica registro AAAA, todo cliente usa IPv4 sem atraso. Mas com mais da metade dos usuários brasileiros já chegando ao Google por IPv6, vale ativar. Na maioria das clouds é configuração de rede mais um registro AAAA. Só publique o AAAA depois de testar, porque um AAAA apontando para um servidor que não responde força o cliente a esperar o fallback.

Por que meu IP começa com 192.168 ou 10?

São endereços privados da RFC 1918, válidos só dentro da sua rede local. O IP que os sites enxergam é o público, que o roteador (ou o CGNAT da operadora) usa na saída. A diferença entre os dois está em IP público e privado.

Trate os dois formatos desde o primeiro commit

O IPv4 esgotou e sobreviveu graças ao NAT; o IPv6 resolve a falta de endereços, mas convive com o IPv4 em dual-stack, e o seu servidor recebe os dois. Para quem escreve código, o mínimo é: saber o que o seu bind aceita em cada sistema operacional, guardar IP em tipo nativo (inet, VARBINARY(16)) ou em texto de 45 caracteres, normalizar ::ffff: antes de usar o IP como chave e agrupar IPv6 por /64 em rate limit. Se quiser entender o caminho completo de uma requisição, do DNS ao primeiro byte, o próximo passo é como a internet funciona do DNS ao HTTP.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil