Você sobe o túnel, faz ping de fe80::1 com o túnel como interface de origem e nada volta. Não é uma regra de firewall esquecida. Um endereço link-local só tem significado no único link onde foi formado, e uma VPN roteada não é esse link. O fe80::1 do roteador remoto fica no segmento LAN remoto; você está a um salto de distância em outro segmento, e o IPv6 não tem mecanismo algum para um roteador encaminhar pacotes link-local.

O prefixo fe80 descreve um escopo, não uma faixa

Link-local unicast é fe80::/10, e a propriedade que o define não é o número, mas o escopo. O endereço só é válido em um link, e cada interface forma um a partir do próprio identificador, por isso duas máquinas sem relação em duas redes sem relação podem ambas responder a fe80::1 sem o menor conflito. O prefixo basicamente diz “em algum link”; o link em si vem do contexto.

Em um host, esse contexto é a zona, ou scope ID, que você acrescenta depois do sinal de porcentagem: fe80::1%eth0 no Linux, fe80::1%3 ou fe80::1%12 no Windows e em ferramentas que expõem índices de interface. O kernel resolve o endereço junto com o índice da interface e então envia. Remova a zona e o destino fica ambíguo, então a pilha não tem como escolher um segmento.

Por que um túnel roteado não consegue entregá-lo

Uma VPN roteada é uma interface ponto a ponto que carrega os próprios endereços, geralmente um /64 de espaço IPv6 unique-local ou privado dentro do túnel. A LAN remota é um link separado, alcançado pelo endpoint do túnel roteando e encaminhando em seu nome. São dois segmentos distintos, então um endereço de um não é destino válido no outro.

A regra de encaminhamento é explícita no padrão, não uma esquisitice do seu cliente: roteadores não encaminham pacotes com origem ou destino link-local. É por isso que o pacote morre mesmo quando a tabela de rotas parece correta. Adicione uma rota para fe80::/64 apontando para o túnel e uma pilha conforme ou a rejeita ou a aceita e descarta todo pacote correspondente: o escopo do destino diz “apenas este link”, e a interface de saída não é esse link.

A descoberta de vizinhos reforça a mesma fronteira. Hosts resolvem próximos saltos link-local com uma solicitação de vizinho enviada ao multicast de escopo de link com limite de salto 255, então roteadores podem rejeitar tudo o que for encaminhado. Fazer isso funcionar através de um túnel significaria fazer proxy da descoberta para um segmento remoto, o que é uma ponte Layer 2 com outro chapéu.

Há uma segunda falha mais silenciosa, e ela pega quem ainda tenta forçar a rota: a zona. Qualquer zona digitada localmente nomeia a interface do túnel, enquanto o endereço que você quer está vinculado à interface da LAN remota. As duas nunca coincidem, então o pacote não pode ser direcionado para a interface correta na outra ponta.

Como a falha aparece na prática

A saída de ferramentas para um erro de escopo lê como um erro de roteamento ou de firewall, e é exatamente por isso que as pessoas passam uma tarde na camada errada.

What you runWhat you seeWhat it means
ping fe80::1 with no zoneInvalid argument on Linux, or a transmit failure on WindowsThe stack cannot pick an interface for an ambiguous destination
ping -6 -I tun0 fe80::1Destination unreachable, or a silent timeoutThe address is not on the tunnel link, so there is nothing on-link to answer
ssh user@fe80::1 after the tunnel is upHangs, then no route to hostThe SYN never left the machine in a deliverable form; the server logs nothing
ip -6 neigh show dev tun0Empty tableNo neighbor entry can exist for a link-local host that is not on this link
fe80::/64 inside AllowedIPs or route-ipv6Config accepted, traffic still droppedThe tunnel carried the packet; the receiving stack refused to forward it

A terceira linha desperdiça mais tempo, porque um cliente ssh sem saída parece um problema de serviço escutando. Se você tiver qualquer forma de entrar, verifique o lado remoto e confirme se o sshd está ligado a todos os endereços ou só a um.

Use um endereço que foi feito para ser roteado

Para tudo o que você precisa alcançar pelo túnel, use o endereço que o serviço recebeu justamente para isso: um endereço unicast global, ou um endereço unique-local de fc00::/7, a faixa reservada exatamente para este caso interno. Confirme que o ouvinte realmente o vincula, e verifique o caminho de retorno e qualquer regra de firewall do host.

Olhe o host remoto em vez de adivinhar. ip -6 addr show lista os endereços que existem, e ss -6 -ltn lista no que o daemon escuta. Um serviço ligado só a fe80:: é alcançável apenas do próprio segmento, o que costuma ser um padrão que ninguém escolheu de propósito e que pode ser mudado com o acordo do administrador.

Quando o serviço realmente não pode ser religado, suba a ponte para a camada de aplicação em vez da camada de rede. Um relay no host remoto que escuta em um endereço roteável e se conecta ao link-local resolve o problema sem estender segmento algum:

socat TCP6-LISTEN:8080,bind=[fd00:1:2::10] TCP6:[fe80::1%eth0]:80

Aqui a zona fica do lado correto, no host que realmente tem eth0 naquele link. Seu cliente fala com fd00:1:2::10, que é roteado normalmente, e o relay faz o salto link-local localmente. O mesmo truque funciona para a interface web de um appliance ou um BMC antigo que só anuncia um endereço link-local.

Quando a ponte é mesmo a resposta, e o que verificar

Algumas implantações realmente precisam de um segmento compartilhado: um dispositivo que só fala descoberta link-local, um appliance que depende de multicast, um laboratório que reproduz uma LAN plana. Isso é um problema de Layer 2 e exige uma resposta de Layer 2, como um dispositivo tap ligado por ponte à interface remota ou um produto cliente com modo de ponte explícito. Isso custa tráfego broadcast e multicast cruzando o túnel mais a descoberta de vizinhos que precisa funcionar de ponta a ponta.

Não chegue perto disso adicionando fe80::/64 a um perfil roteado. Isso produz o pior estado: a configuração parece pronta, a tabela de rotas mostra uma entrada, e todo pacote ainda é descartado em algum lugar entre duas pilhas que ambas se comportam corretamente.

Verifique com a interface em vez do ping. ip -6 addr show tun0 diz se o link do túnel formou um endereço link-local próprio, e ip -6 route get fe80::1%tun0 diz o que o kernel realmente faria com um destino com escopo. Quando o kernel diz que o destino é inalcançável naquela interface, nenhuma configuração de túnel vai mudar isso, e é hora de parar de editar o perfil.

Uma sequência curta que resolve a questão:

  • Leia o endereço no host remoto e observe se é fe80:: ou um prefixo roteável.
  • Se for fe80::, religue o serviço, faça relay naquele host ou ligue o segmento em ponte; se for roteável, corrija a rota, o firewall ou o endereço de bind.
  • Confira a zona toda vez que retestar, porque um comando copiado costuma manter a interface errada.

Fontes: RFC 4291, arquitetura de endereçamento IPv6.

Artigos relacionados