A rota predefinida IPv6 desapareceu após ativar o encaminhamento no Linux
Ativar o encaminhamento IPv6 faz o kernel ignorar os router advertisements no uplink, e a rota predefinida aprendida expira. Corrija com accept_ra.
Defini net.ipv6.conf.all.forwarding=1 num gateway Debian para que pudesse encaminhar o tráfego dos clientes VPN, e cerca de meia hora depois a máquina já não tinha qualquer rota predefinida IPv6. O router a montante estava ativo, o vizinho link-local ainda respondia e o uplink conservava o seu endereço global. O que tinha parado era a disposição do kernel de continuar a aceitar router advertisements nessa interface. A rota não desapareceu quando escrevi o sysctl; desapareceu quando a vida da rota predefinida aprendida do RA expirou e nada a renovou.
Nada parecia avariado à primeira vista. O encaminhamento funcionava, os clientes continuavam a passar enquanto a rota antiga estava em cache, e a falha chegou mais tarde do que a alteração que a causou. Esse atraso é a razão pela qual se culpa o uplink ou uma regra de firewall que nunca esteve envolvida.
Leia a tabela de rotas antes de tocar em qualquer sysctl
Comece com ip -6 route show default e leia os atributos, não apenas o gateway. Uma rota predefinida aprendida do RA está marcada com proto ra, transporta uma preferência e mostra uma contagem decrescente expires. Uma rota adicionada à mão não tem nem uma nem outra, e essa diferença diz-lhe que mecanismo é dono da rota.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumDepois olhe para o endereço: ip -6 addr show dev eth0. Um endereço global com vidas preferida e válida medidas em horas sobreviverá a uma rota predefinida cuja vida do router é medida em minutos. Endereço presente e rota predefinida ausente é a assinatura de um problema de anúncios. Se também faltar o endereço, primeiro há que investigar a ligação, a informação de prefixo ou a deteção de endereços duplicados.
Porque o encaminhamento desativa o processamento de RA
Um RA é um pacote ICMPv6 de tipo 134, enviado de uma origem link-local com limite de salto 255. Antes de o usar, o kernel consulta o accept_ra da interface. O valor predefinido é 1, e 1 não significa sim. Significa: aceita apenas enquanto este anfitrião não encaminhar. Defina forwarding=1 e essa condição falha, pelo que o anúncio é descartado antes de se considerar qualquer prefixo ou router predefinido nele contido.
Existem três valores, e apenas o terceiro sobrevive ao encaminhamento:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
Outros dois sinalizadores decidem o que é realmente instalado. accept_ra_defrtr controla se o router predefinido do anúncio se torna uma rota, e accept_ra_pinfo controla se a informação de prefixo é usada para a configuração de endereços. Desativar accept_ra_defrtr é a forma habitual de manter endereços SLAAC num anfitrião que encaminha sem aprender uma rota predefinida. É uma alavanca diferente de accept_ra, e é aquela a que se recorre quando se querem endereços mas não uma rota. A referência do kernel sobre IP sysctl lista as três.
Confirme com três comandos
Primeiro, leia os valores em tempo real em vez do ficheiro que julga carregado:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrSegundo, prove que os anúncios continuam a chegar. Filtrar pelo byte de tipo ICMPv6 é suficiente e poupa-lhe ler uma parede de tráfego de descoberta de vizinhos:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'Se nada aparecer durante vários minutos, accept_ra não é o seu problema. O lado a montante deixou de anunciar, algo no caminho filtra ICMPv6, ou essa interface não está realmente no segmento que pensa. Terceiro, solicite um anúncio você mesmo e leia os seus campos:
rdisc6 eth0rdisc6 vem no pacote ndisc6 no Debian e no Ubuntu. Na saída, olhe para a vida do router e para a preferência antes de alterar mais alguma coisa. Um anúncio com vida de router 0 é uma instrução para remover o router predefinido, e nenhum valor de accept_ra transforma isso numa rota utilizável. É também assim que se apanha um CPE a montante em modo bridge que distribui prefixos mas nunca se oferece como router.
Torne o uplink a única interface permissiva
Se o lado a montante deve ser o router predefinido, aceite lá anúncios apesar do encaminhamento, e em nenhum outro lugar:
# /etc/sysctl.d/60-ipv6-router.conf
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.accept_ra_defrtr = 1O âmbito importa porque o encaminhamento IPv6 no Linux é um único interruptor global, não um por ligação. Escreva 1 em net.ipv6.conf.wg0.forwarding e depois leia net.ipv6.conf.all.forwarding: o valor global inverte-se e cada interface começa a encaminhar. Não pode ser router no túnel e anfitrião comum na LAN. O que pode limitar é a aceitação. Mantenha accept_ra=2 no uplink e deixe as interfaces do túnel e da LAN em 1 ou 0, para que um anúncio extraviado que chegue pelo túnel não possa instalar uma rota predefinida que aponte para dentro dele.
Um sysctl -w temporário não sobreviverá ao próximo arranque, e tanto o systemd-networkd como o NetworkManager escrevem estes valores a partir da sua própria configuração. No networkd, defina IPv6Forwarding=yes e IPv6AcceptRA=yes no ficheiro .network do uplink; o networkd documenta o IPv6Forwarding como global pelo mesmo motivo do kernel. No NetworkManager, é ipv6.method=auto no uplink que comanda o valor de accept_ra, por isso releia o sysctl após nmcli connection up em vez de confiar na primeira verificação.
A alternativa estática, ip -6 route add default via fe80::1 dev eth0, funciona mesmo, e é uma resposta razoável quando o router a montante tem um endereço link-local estável. Seja claro quanto ao que abdica. Uma rota predefinida estática nunca é renovada nem retirada, por isso continua a apontar para um vizinho morto depois de o lado a montante ser substituído. A rota por RA falha em segurança; a estática falha em silêncio.
Teste um pacote encaminhado, não o do próprio gateway
Os pings do próprio gateway podem ter sucesso numa rota que nenhum cliente consegue usar, e também podem ter sucesso porque o gateway é a origem. Teste a partir de um cliente ligado e depois pergunte ao gateway o que faria para o endereço desse cliente:
# on the VPN client
ping -6 -c 3 2001:4860:4860::8888
# on the gateway, using a client address
ip -6 route get 2001:4860:4860::8888 from fd42:20::2Depois espere uma vida de router e volte a olhar. O estado estável que pretende é uma rota predefinida marcada com proto ra cujo valor expires se reinicia constantemente, mais all.forwarding=1. Se expires apenas faz contagem decrescente, os anúncios continuam a ser descartados em algum ponto, e o culpado habitual é um gestor de rede que reescreve accept_ra depois de o sysctl de arranque já ter sido executado.
Antes de fechar isto, confirme quatro coisas: a rota predefinida é proto ra e está a renovar-se, accept_ra=2 aplica-se apenas ao uplink, o encaminhamento continua a ser 1 após um reinício e após reiniciar o gestor, e é um cliente, não o gateway, que completa um ping IPv6. Se o cliente continuar a falhar com uma rota saudável, o próximo suspeito é o caminho de retorno ou uma firewall a montante, não o anúncio.