IPv4 e IPv6 têm headers diferentes: um host que só fala um deles não conversa com quem só fala o outro. A (RFC) 6144 divide as pontes em três famílias: "Besides dual-stack deployment, there are two fundamental approaches one could take to interworking between IPv4 and IPv6: tunneling and translation", dual-stack, túneis e tradução (RFC 6144, seção 1.1). Só a tradução leva um cliente somente IPv6 a um servidor somente IPv4, já que o túnel exige hosts dual-stack nas pontas (seção 1.1), e toda rede com os dois protocolos usa ao menos uma família. Ao final você consegue prever qual família um host escolhe, montar os endereços de cada mecanismo, acompanhar uma sessão e conferir tudo com comandos reais.

Dual-stack e a escolha da família

Um nó dual-stack, o nó IPv6/IPv4 da RFC 4213, fala cada protocolo nativamente (RFC 4213, seção 2). As aplicações costumam tentar os endereços na ordem recebida (seção 2.2), que a RFC 6724 define numa tabela só, já que "IPv4 addresses MUST be represented as IPv4-mapped addresses", IPv4 como endereço mapeado, a forma ::ffff:0:0/96 descrita em como funciona o endereçamento IPv6 (RFC 6724, seção 3.2). A tabela padrão, em parte (seção 2.1):

Prefix          Precedence  Label
::1/128               50      0
::/0                  40      1
::ffff:0:0/96         35      4
2002::/16             30      2
2001::/32              5      5
fc00::/7               3     13

A regra 6 prefere a maior precedência (RFC 6724, seção 6): IPv6 nativo (40) vence IPv4 (35), 6to4 (30) e (5). Como a regra de escopo vem antes, um host só com endereço IPv6 link-local usa IPv4 para destinos globais (seção 10.2).

O Happy Eyeballs versão 2 torna barato um caminho IPv6 morto (RFC 8305, seção 1). A consulta sai primeiro e a A logo depois; se a A responder antes, o cliente espera 50 ms pela AAAA (seção 3). Os endereços são ordenados pela RFC 6724, com as famílias intercaladas (seção 4); as tentativas saem a cada 250 ms por padrão, entre os limites recomendados de 100 ms e 2 s, e vence a primeira conexão que se completa (seção 5). Ilustrativamente, com o IPv6 quebrado:

t =   0 ms   conecta a 2001:db8::10   IPv6, o primeiro depois da ordenação
t = 250 ms   conecta a 192.0.2.10     IPv4, o seguinte na lista intercalada
t = 280 ms   192.0.2.10 completa      a tentativa a 2001:db8::10 é cancelada

Túneis: IPv6 dentro de IPv4

Um túnel configurado, ou 6in4, põe cada pacote IPv6 atrás de um header IPv4 (RFC 4213, seção 1) com o protocolo 41 (seção 3.5), que a Internet Assigned Numbers Authority () registra como encapsulamento IPv6 (números de protocolo da IANA). Para o IPv6, o túnel é um hop só: "The tunnel is opaque to users of the network, and it is not detectable by network diagnostic tools such as traceroute", invisível até para o traceroute (RFC 4213, seção 3.3).

O 6to4 dispensa configurar túneis explicitamente (RFC 3056, resumo): o prefixo do site é 2002::/16 mais o IPv4 do site, 2002:V4ADDR::/48 (seção 2), e a outra ponta de cada túnel sai do endereço do próximo hop (seção 5.3). Relays, muitas vezes um diferente em cada sentido, ligam o 6to4 ao IPv6 nativo (RFC 7526, seção 3); a RFC 3068 pôs todos no endereço anycast 192.88.99.1 (RFC 3068, seção 2.4). Ilustrativamente:

endereço IPv4          192.0.2.33  =  c0.00.02.21
prefixo 6to4 do site   2002:c000:221::/48
relay anycast          192.88.99.1  ->  2002:c058:6301::   (RFC 3068, seção 2.5)

O Teredo, para hosts atrás de , onde túneis clássicos e 6to4 falham (RFC 4380, seção 1), é um "IPv6 access of last resort", o último recurso (seção 3.2), sobre UDP, porta 3544, em 2001::/32 (seções 2.6 e 2.7). O endereço guarda o IPv4 do servidor, flags e a porta e o endereço mapeados do cliente, com os bits invertidos (seção 4). Ilustrativamente:

2001:0000   c000:022d    3c5a    63bf             34ff:8eeb
prefixo     servidor     flags   porta            endereço do cliente
            192.0.2.45           9c40 XOR ffff    cb00:7114 XOR ffff:ffff
                                 (40000)          (203.0.113.20)
endereço    2001:0:c000:22d:3c5a:63bf:34ff:8eeb

O IPv6 Rapid Deployment (6rd) aplica a aritmética do 6to4 ao prefixo do próprio provedor: "Unlike 6to4, 6rd is for use only in an environment where a service provider closely manages the delivery of IPv6 service", só com o provedor no controle (RFC 5969, seção 1). O roteador Customer Edge (CE) acrescenta bits do seu IPv4 ao prefixo 6rd (seção 4), como no exemplo da RFC (seção 7.1.1):

endereço do CE 10.100.100.1, sem os 8 primeiros bits   100.100.1  =  64.64.01
prefixo 6rd 2001:db8::/32 + esses 24 bits              2001:db8:6464:100::/56
os 32 bits, ilustrativo                                2001:db8::/32 + 203.0.113.20 = 2001:db8:cb00:7114::/64

Tradução sem estado e endereços IPv4 convertidos

A RFC 7915 converte headers IPv4 em IPv6 e de volta, inclusive os do Internet Control Message Protocol (), no Stateless IP/ICMP Translation Algorithm (SIIT) (RFC 7915, resumo). "The stateless translator does not keep any dynamic session or binding state, thus there is no requirement that the packets in a single session or flow traverse a single translator", sem estado, sem tradutor fixo por fluxo (seção 1.3).

Hosts IPv6 enxergam hosts IPv4 como endereços IPv4 convertidos (IPv4-converted) (RFC 6052, seção 1.3), sob o Well-Known Prefix 64:ff9b::/96 (seção 2.1) ou um Network-Specific Prefix do próprio operador: "The prefixes can only have one of the following lengths: 32, 40, 48, 56, 64, or 96", só seis comprimentos (seção 2.2). A RFC 8215 acrescenta 64:ff9b:1::/48 para uso local (RFC 8215, resumo). Os bits do IPv4 seguem o prefixo, pulando os bits 64 a 71, zerados (RFC 6052, seções 2.2 e 2.3), como nos exemplos (seção 2.4):

Prefixo             IPv4         Endereço IPv4 convertido
2001:db8::/32       192.0.2.33   2001:db8:c000:221::
2001:db8:100::/40   192.0.2.33   2001:db8:1c0:2:21::        0x21 depois do octeto zerado
64:ff9b::/96        192.0.2.33   64:ff9b::192.0.2.33   =   64:ff9b::c000:221

Como 0064 mais ff9b dá ffff, zero em complemento de um, o prefixo é neutro para o checksum (RFC 6052, seção 4.2). Mas "Address translators MUST NOT translate packets in which an address is composed of the Well-Known Prefix and a non-global IPv4 address; they MUST drop these packets", com IPv4 não global, descarte obrigatório (seção 3.1), e a IANA lista 192.0.2.0/24 como não alcançável globalmente (registro IPv4 de uso especial da IANA), então estes exemplos são ilustrativos. O 64:ff9b:1::/48 escapa da regra (RFC 8215, seção 5); Faixas de IP privadas, reservadas e públicas lista os blocos não globais.

NAT64 e DNS64, passo a passo

O NAT64 com estado (stateful) leva clientes somente IPv6 a servidores IPv4 por endereços IPv4 públicos compartilhados (RFC 6146, resumo). O DNS64 o alimenta: para um nome sem registros de recurso (RRs, resource records) AAAA, o normal num servidor só IPv4, ele busca o registro A e sintetiza um AAAA (RFC 6147, seção 2), e "By default, DNS64 implementations MUST NOT synthesize AAAA RRs when real AAAA RRs exist", AAAA real dispensa síntese (seção 5.1.1). O passo a passo da RFC 6146 usa endereços de documentação que um tradutor real descartaria (RFC 6146, seção 1.2.2):

1  H1 pede ao DNS64 o AAAA de h2.example.com
2  não existe; o DNS64 busca o A 192.0.2.1
3  responde AAAA 64:ff9b::192.0.2.1
4  H1 envia de 2001:db8::1 porta 1500 para 64:ff9b::192.0.2.1
5  o NAT64 escolhe a porta 2000 em 203.0.113.1 e cria o mapeamento
   (2001:db8::1,1500) <--> (203.0.113.1,2000)
6  envia IPv4 de 203.0.113.1 porta 2000 para 192.0.2.1,
   os últimos 32 bits do destino IPv6
7  a resposta para 203.0.113.1 porta 2000 volta a 2001:db8::1 porta 1500,
   vinda de 64:ff9b::192.0.2.1

O NAT64 traduz, portanto, endereço e porta (RFC 6146, seção 1.2.1), como o NAT de NAT explicado, e sem estado prévio só nós IPv6 abrem sessões (seção 1.1). O DNS64 só compartilha com ele o prefixo e parâmetros estáticos opcionais (RFC 6147, seção 2).

Como o host descobre o prefixo

Um host que sintetiza por conta própria descobre o prefixo consultando os registros AAAA de ipv4only.arpa, cujos endereços são 192.0.0.170 e 192.0.0.171 (RFC 7050, seção 2.2), com o bit Checking Disabled (CD) zerado, senão o DNS64 não sintetiza; as respostas mostram o prefixo em volta desses endereços, e uma resposta positiva à consulta A indica um resolver que não é DNS64 (seção 3). As Router Advertisements (RAs), vistas em Descoberta de Vizinhos, podem levar o prefixo no lugar disso, na opção PREF64, tipo 38, com códigos de 0 a 5 para /96, /64, /56, /48, /40 e /32 (RFC 8781, seção 4).

464XLAT: duas traduções, nenhum túnel

O 464XLAT leva aplicações somente IPv4 através de uma rede somente IPv6 e não tunela nada: é "a simple and scalable technique to quickly deploy limited IPv4 access service to IPv6-only edge networks without encapsulation", IPv4 limitado, sem encapsulamento (RFC 6877, resumo). O tradutor do lado do cliente (CLAT, customer-side translator) traduz sem estado, 1:1, entre um IPv4 privado e um IPv6 global, como faz o SIIT; o tradutor do lado do provedor (PLAT, provider-side translator) é um NAT64 com estado, (seção 2). O CLAT só age diante de literais IPv4 ou sockets só IPv4 (seção 5.2), e seu endereço privado pode vir de 192.0.0.0/29, prefixo de sistemas que não põem IPv4 no fio (RFC 7335, seção 1). Numa rede celular, até o fim de 2018, menos de 1% do tráfego precisou do CLAT (RFC 9313, seção 4.5.2). e conexões IPv4 de entrada ficam fora de alcance (RFC 6877, seção 1).

IPv4 como serviço

O Dual-Stack Lite () tunela IPv4 em IPv6 do elemento Basic Bridging BroadBand (B4) do cliente até um Address Family Transition Router (AFTR), que reúne endpoint de túnel e NAT IPv4 num só nó (RFC 6333, seções 1 e 6.1), um NAT compartilhado; "There is no protocol family translation involved in this approach", não há tradução entre famílias (seção 4.1). O Mapping of Address and Port (MAP) compartilha um endereço dividindo suas portas (RFC 7597, seção 1): o MAP with Encapsulation (MAP-E) carrega IPv4 dentro de IPv6 (resumo), e o MAP using Translation (MAP-T) o traduz (RFC 7599, seção 1).

O que quebra

Literais IPv4. Atrás de acesso somente IPv6, literais IPv4 e APIs antigas falham sem um CLAT, o Happy Eyeballs versão 2 ou um Bump-in-the-Host com DNS64 (RFC 8683, seção 4.6), e protocolos que protegem o header IP são "essentially incompatible with NAT64", incompatíveis com o NAT64 (RFC 6146, seção 5.1).

Respostas assinadas. As Domain Name System Security Extensions () se chocam com a síntese "because DNSSEC is designed to detect changes to DNS answers, and DNS64 may alter answers coming from an authoritative server", o DNSSEC detecta o que o DNS64 altera (RFC 6147, seção 3). Um DNS64 validador (vDNS64) pode sintetizar com DNSSEC OK (DO) ligado e CD zerado, marcando o bit Authentic Data (), mas "If the CD bit is set and DO is set, then vDNS64 MAY perform validation, but MUST NOT perform synthesis", com CD e DO, nada de síntese (seção 5.5): um host validador tem então de fazer o DNS64 sozinho (seção 3). A RFC 8683 cita estudos que põem essa quebra em cerca de 1,7% dos casos (RFC 8683, seção 4.1). A RFC 8880 derrubou a exigência da RFC 7050 de assinar o nome (RFC 7050, seção 4): "the 'ipv4only.arpa' zone MUST be an insecure delegation", obrigatoriamente uma delegação insegura (RFC 8880, seção 5); veja DNSSEC de ponta a ponta.

Resolvers. Um dispositivo que usa um resolver diferente do aprendido na rede pode quebrar seriamente o DNS64 e o NAT64 (RFC 8880, seção 3.1), um custo a considerar ao escolher um resolver público.

Tamanho de pacote. A RFC 4213 limita a Maximum Transmission Unit () de um túnel 6in4: por padrão, "the MTU MUST be between 1280 and 1480 bytes (inclusive), but it SHOULD be 1280 bytes", de 1280 a 1480, idealmente 1280 (RFC 4213, seção 3.2.1). Um caminho de 1500 bytes deixa 1480 para um túnel 6rd (RFC 5969, seção 9.1), e o TCP sobre IPv6 desconta 60 octetos no Maximum Segment Size () (RFC 8200, seção 8.3), sobrando 1420. O DS-Lite pede links do B4 ao AFTR no mínimo 40 bytes maiores, pois o () não é confiável (RFC 6333, seção 5.3), e mensagens Packet Too Big descartadas não são raras (RFC 7915, seção 7). A armadilha: "a standard 'ping' from the client to the server will succeed, because it generates small packets", o ping, com pacotes pequenos, passa (RFC 6343, seção 3), e o Happy Eyeballs, que só vê o handshake, não percebe a falha (RFC 8305, seção 9.1); veja ICMP, ping e traceroute.

6to4 anycast. Um experimento viu falhar de 9% a 20% das tentativas de conexão 6to4, com uma causa provável em filtros perto dos usuários que bloqueiam o protocolo 41, e o fallback para IPv4 escondeu as falhas sob atrasos de 7 a 20 segundos (RFC 6343, seção 3). Em maio de 2015, a RFC 7526 declarou obsoletos o 6to4 anycast e o 192.88.99.1, mas manteve o 2002::/16 (RFC 7526, seção 4), e determinou: "In router implementations, 6to4 MUST be disabled by default", desligado por padrão (seção 5).

Mascaramento e spoofing. Se o IPv6 falha e o IPv4 funciona, o Happy Eyeballs pode esconder o problema do operador, e a RFC 8305 recomenda monitorar externamente cada família de endereços (RFC 8305, seção 9.3). Os decapsuladores precisam conferir o IPv4 de origem contra o endpoint configurado (RFC 4213, seção 5) ou, no 6rd, contra o IPv4 embutido (RFC 5969, seção 9.2).

Como ver na prática

Estes comandos seguem ip(8), ip-route(8), ip-tunnel(8), ip-address(8), tracepath(8), ping(8) e getent(1); um B4 do DS-Lite usa o endereço 192.0.0.2 (RFC 6333, seção 5.7):

ip -6 route get 64:ff9b::c000:221   # a rota que um destino sintetizado segue
ip tunnel show                      # sit para 6in4, 6to4 e 6rd; ipip6 para um B4 do DS-Lite
ip address show                     # um endereço de CLAT ou de B4 pode estar em 192.0.0.0/29
tracepath -6 example.com            # o MTU do caminho, hop a hop
ping -6 -M do -s 1432 example.com   # 40 + 8 + 1432 = 1480 bytes; recusado se o caminho for menor
getent ahosts example.com           # os endereços na ordem em que o getaddrinfo os devolve

O exemplo do tracepath(8) mostra um hop 6in4:

root@mops:~ # tracepath -6 3ffe:2400:0:109::2
 1?: [LOCALHOST]                              pmtu 1500
 1:  dust.inr.ac.ru                   0.411ms
 2:  dust.inr.ac.ru        asymm  1   0.390ms pmtu 1480
 2:  3ffe:2400:0:109::2               463.514ms reached
     Resume: pmtu 1480 hops 2 back 2

O /etc/gai.conf reordena os endereços, mas seu manual ainda traz a tabela da RFC 3484 (IPv4 mapeado em 10), e uma só linha precedence substitui a tabela padrão (gai.conf(5)). O curl mostra qual família venceu, e seu manual diz que a libcurl dá ao IPv6 200 ms de vantagem (página de manual do curl):

curl -s -o /dev/null -w '%{remote_ip} %{time_connect}\n' https://example.com
curl -6 https://example.com   # só IPv6; -4 para só IPv4
curl --happy-eyeballs-timeout-ms 250 https://example.com

No dig, +dns64prefix imprime os prefixos DNS64 encontrados em ipv4only.arpa, +dnssec liga o DO e +cd liga o CD (manual do dig, BIND 9); o Google Public DNS64, 2001:4860:4860::6464, só ajuda onde há um NAT64 em 64:ff9b::/96 ao alcance (Google Public DNS64):

dig @2001:4860:4860::6464 ipv4only.arpa AAAA
dig @2001:4860:4860::6464 +dns64prefix
dig @2001:4860:4860::6464 +dnssec +cd ipv4only.arpa AAAA   # DO e CD ligados: não se espera síntese

Uma resposta sintetizada ilustrativa, no formato de zona da RFC 8683, seção 4.1:

ipv4only.arpa. AAAA 64:ff9b::192.0.0.170
ipv4only.arpa. AAAA 64:ff9b::192.0.0.171

Uma captura real do Google Public DNS, que não é DNS64, feita em 2026-10-18T21:49:22Z:

curl -s 'https://dns.google/resolve?name=ipv4only.arpa&type=AAAA'
curl -s 'https://dns.google/resolve?name=ipv4only.arpa&type=A'
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"ipv4only.arpa","type":28}],"Authority":[{"name":"ipv4only.arpa","type":6,"TTL":287,"data":"sns.dns.icann.org. noc.dns.icann.org. 2026100800 7200 3600 604800 3600"}]}
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"ipv4only.arpa","type":1}],"Answer":[{"name":"ipv4only.arpa","type":1,"TTL":16109,"data":"192.0.0.170"},{"name":"ipv4only.arpa","type":1,"TTL":16109,"data":"192.0.0.171"}]}

A consulta AAAA (tipo 28) recebeu status 0, nenhum Answer e um registro em Authority, a resposta negativa da qual um DNS64 sintetizaria (RFC 8305, seção 7.2); a consulta A (tipo 1) recebeu 192.0.0.170 e 192.0.0.171, sinal de um resolver que não é DNS64 (RFC 7050, seção 3); e o AD está falso nas duas, como uma delegação insegura implica (RFC 8880, seção 5). O header DNS explica as flags, o explicador de saída do dig decodifica AD e CD, e o montador de comandos dig escreve -6, +dnssec e +cd, mas não +dns64prefix.

O ipaddress do Python decodifica 6to4 (sixtofour), Teredo (teredo) e endereços mapeados (ipv4_mapped), mas não NAT64 (documentação do ipaddress do Python). Uma sessão no CPython 3.13.16; o Playground de Python roda CPython 3.14:

>>> import ipaddress
>>> b = ipaddress.ip_address('2002:c000:221::1'); b
IPv6Address('2002:c000:221::1')
>>> b.sixtofour
IPv4Address('192.0.2.33')
>>> t = ipaddress.ip_address('2001:0:c000:22d:3c5a:63bf:34ff:8eeb'); t
IPv6Address('2001:0:c000:22d:3c5a:63bf:34ff:8eeb')
>>> t.teredo
(IPv4Address('192.0.2.45'), IPv4Address('203.0.113.20'))
>>> n = ipaddress.ip_address('64:ff9b::192.0.2.33'); n
IPv6Address('64:ff9b::c000:221')
>>> ipaddress.IPv4Address(int(n) & 0xffffffff)
IPv4Address('192.0.2.33')
>>> n.ipv4_mapped, n.sixtofour, n.teredo
(None, None, None)

O Kit de ferramentas IPv6 mostra o IPv4 dentro de um endereço IPv4 mapeado e rotula endereços de 64:ff9b::/96 e 2002::/16 sem extrair o IPv4; não reconhece endereços Teredo nem 64:ff9b:1::/48. A Calculadora de MTU / MSS dá, para um link de 1500 bytes com 6in4, MTU interno de 1480 e MSS IPv6 de 1420, e com ipip v6, como no DS-Lite, 1460 e MSS IPv4 de 1420.

Para lembrar

  • Dual-stack, túneis e tradução são as famílias da RFC 6144; só a tradução liga hosts somente IPv6 e somente IPv4.
  • A RFC 6724 põe IPv6 (40) acima de IPv4 (35), 6to4 (30) e Teredo (5); o Happy Eyeballs espaça as tentativas em 250 ms.
  • O 6to4 monta 2002:V4ADDR::/48; seus relays anycast foram declarados obsoletos em 2015, e os roteadores devem vir com ele desligado.
  • O 64:ff9b::/96 guarda um IPv4 global nos últimos 32 bits; o DNS64 sintetiza e o NAT64 traduz endereço e porta.
  • Os hosts descobrem o prefixo por ipv4only.arpa, consultado com CD zerado, ou pela PREF64 nas Router Advertisements.
  • O 464XLAT traduz duas vezes e não encapsula nada; DS-Lite e MAP-E é que carregam IPv4 dentro de IPv6.
  • Num caminho de 1500 bytes, um túnel 6in4 deixa 1480 bytes e um MSS TCP de 1420; um ping pequeno esconde a falha.

Fontes