Resumo

  • RFC 3493 permitia que um socket AF_INET6 falasse com nós IPv4 por endereços IPv4 mapeados em IPv6. IPV6_V6ONLY restringia o socket a IPv6, mas o RFC definia a opção desligada por padrão.
  • Assim, família declarada, processo em execução e bind bem-sucedido não provavam quais pares chegavam nem se outro listener possuía a mesma porta. Estado efetivo e tráfego observado eram recibos separados.

Uma linha do tempo de incidente revela o contrato oculto. O serviço IPv6 sobe primeiro e faz bind em endereço curinga. O serviço IPv4 sobe depois e recebe conflito. O supervisor mantém o conjunto verde porque o primeiro processo continua atendendo. Só que a separação planejada entre famílias desapareceu antes da primeira requisição.

RFC 3493 criou compatibilidade usando endereços IPv4 mapeados em IPv6. O endereço IPv4 ocupa os 32 bits inferiores de uma estrutura de 128 bits sob o prefixo ::ffff:. Um aplicativo pode usar um socket AF_INET6 para alcançar um nó IPv4; ao receber, o kernel pode devolver o par em sockaddr_in6. O macro IN6_IS_ADDR_V4MAPPED() existe para quem precisa reconhecer a forma.

Essa forma é um contrato de representação. Não demonstra IPv6 nativo no host remoto, não descreve o caminho e não certifica política ou identidade. O fato de o programa receber uma estrutura IPv6 não transforma o tráfego em uma prova de família.

A seção 5.3 define IPV6_V6ONLY. Ligada, a opção booleana limita o socket AF_INET6 a comunicação IPv6. O RFC dizia que ela ficava desligada por padrão. Naquele modelo, um listener curinga podia receber IPv6 nativo e IPv4 apresentado como endereço mapeado.

O exemplo do documento trata diretamente de propriedade de porta. Ligar a opção permite executar duas versões do mesmo servidor no mesmo número, uma em IPv6 e outra em IPv4. Logo, a opção decide se um bind ocupa uma ou duas famílias e se há espaço para um segundo listener. Ordem de inicialização e código de retorno deixam de ser detalhes administrativos.

Por isso, inventário de processos não basta. Um processo pode existir sem ter adquirido seu socket. Inventário de sockets também falha se traduzir AF_INET6 como IPv6-only. A evidência deve reunir família, valor lido de IPV6_V6ONLY, endereço de bind, namespace, porta, resultado da chamada e classes de pares efetivamente aceitas.

Há uma ressalva que impede simplificações. RFC 3493 diz que a opção não afeta endereços mapeados que entram como IPv6 válido por SIIT. RFC 6052 e RFC 6145 tratam de endereços incorporados e tradução de pacotes, não da mesma coisa que o mapeamento local do socket. Ver ::ffff: não revela sozinho onde ocorreu a transformação.

Resolução é outro degrau. getaddrinfo() produz candidatos conforme família e flags. RFC 6724 organiza seleção; RFC 8305 trata candidatos IPv6 e IPv4 como caminhos concorrentes. Obter um endereço não prova listener, conectividade, autorização ou entrega do serviço.

O padrão desligado é um fato histórico, não um valor universal atual. RFC 3493 é Informational, substituiu RFC 2553 e apontou outra especificação como padrão formal. Sistemas, runtimes e plataformas modernas podem divergir. A verificação contemporânea precisa ler estado e testar comportamento.

A lição durável é manter os recibos em ordem: família declarada, opção efetiva, bind, propriedade da porta, forma do par, autorização e resultado. Sem isso, o nome “listener IPv6” pode esconder uma entrada IPv4 ou um servidor IPv4 que nunca escutou.

Fontes