Vaig posar net.ipv6.conf.all.forwarding=1 en una porta d'enllaç Debian perquè pogués reenviar el trànsit dels clients VPN, i uns tres quarts d'hora després la màquina ja no tenia cap ruta per defecte IPv6. El router ascendent funcionava, el veí link-local encara responia i l'enllaç ascendent conservava la seva adreça global. El que s'havia aturat era la disposició del nucli a seguir acceptant router advertisements en aquella interfície. La ruta no va desaparèixer quan vaig escriure el sysctl; va desaparèixer quan va caducar la vida de la ruta per defecte apresa de l'RA i res no la va renovar.

Res no semblava espatllat a primera vista. El reenviament funcionava, els clients seguien passant mentre la ruta antiga era a la memòria cau, i la fallada va arribar més tard que el canvi que la va provocar. Aquest retard és la raó per la qual s'atribueix a l'enllaç ascendent o a una regla de tallafoc que mai no hi va intervenir.

Llegiu la taula de rutes abans de tocar cap sysctl

Comenceu amb ip -6 route show default i llegiu els atributs, no només la porta d'enllaç. Una ruta per defecte apresa de l'RA està marcada amb proto ra, porta una preferència i mostra un compte enrere expires. Una ruta afegida a mà no té cap de les dues coses, i aquesta diferència us diu quin mecanisme posseeix la ruta.

$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref medium

Després mireu l'adreça: ip -6 addr show dev eth0. Una adreça global amb vides preferida i vàlida mesurades en hores sobreviurà a una ruta per defecte la vida del router de la qual es mesura en minuts. Adreça present i ruta per defecte absent és la firma d'un problema d'anuncis. Si també falta l'adreça, primer cal perseguir l'enllaç, la informació de prefix o la detecció d'adreces duplicades.

Per què el reenviament desactiva el processament d'RA

Un RA és un paquet ICMPv6 de tipus 134, enviat des d'una font link-local amb límit de salt 255. Abans que el nucli l'usi, consulta el accept_ra de la interfície. El valor per defecte és 1, i 1 no vol dir sí. Vol dir: accepta només mentre aquest amfitrió no reenviï. Poseu forwarding=1 i aquella condició falla, així que l'anunci es descarta abans que s'hi consideri cap prefix ni cap router per defecte.

Hi ha tres valors, i només el tercer sobreviu al reenviament:

accept_raforwarding=0forwarding=1
0ignoredignored
1 (default)acceptedignored
2acceptedaccepted

Dues altres banderes decideixen què s'instal·la realment. accept_ra_defrtr controla si el router per defecte de l'anunci es converteix en ruta, i accept_ra_pinfo controla si la informació de prefix s'usa per a la configuració d'adreces. Desactivar accept_ra_defrtr és la manera habitual de mantenir adreces SLAAC en un amfitrió que reenvia sense aprendre una ruta per defecte. És una palanca diferent de accept_ra, i és la que cal fer servir quan voleu adreces però no una ruta. La referència del nucli sobre IP sysctl els llista tots tres.

Confirmeu-ho amb tres ordres

Primer, llegiu els valors en viu en lloc del fitxer que creieu carregat:

sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
       net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtr

Segon, demostreu que els anuncis encara arriben. Filtrar pel byte de tipus ICMPv6 és suficient i us estalvia llegir una paret de trànsit de descoberta de veïns:

tcpdump -ni eth0 'icmp6 and ip6[40] == 134'

Si no apareix res durant uns quants minuts, accept_ra no és el vostre problema. L'enllaç ascendent ha deixat d'anunciar, alguna cosa al camí filtra ICMPv6, o aquella interfície no és realment al segment que penseu. Tercer, sol·liciteu un anunci vosaltres mateixos i llegiu-ne els camps:

rdisc6 eth0

rdisc6 ve al paquet ndisc6 a Debian i Ubuntu. A la sortida, mireu la vida del router i la preferència abans de canviar res més. Un anunci amb una vida de router 0 és una ordre de treure el router per defecte, i cap valor d'accept_ra ho converteix en una ruta utilitzable. També així enxampeu un CPE ascendent en mode pont que reparteix prefixos però que mai no s'ofereix com a router.

Feu de l'enllaç ascendent l'única interfície permissiva

Si l'enllaç ascendent ha de ser el router per defecte, accepteu-hi anuncis malgrat el reenviament, i enlloc més:

# /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 = 1

L'abast importa perquè el reenviament IPv6 a Linux és un sol commutador global, no un per enllaç. Escriviu 1 a net.ipv6.conf.wg0.forwarding i després llegiu net.ipv6.conf.all.forwarding: el valor global es capgira i cada interfície comença a reenviar. No podeu ser router al túnel i un amfitrió normal a la LAN. El que sí que podeu limitar és l'acceptació. Manteniu accept_ra=2 a l'enllaç ascendent i deixeu les interfícies del túnel i de la LAN a 1 o 0, perquè un anunci esgarriat que arribi pel túnel no pugui instal·lar una ruta per defecte que hi apunti.

Un sysctl -w temporal no sobreviurà al proper reinici, i tant systemd-networkd com NetworkManager escriuen aquests valors des de la seva pròpia configuració. A networkd, poseu IPv6Forwarding=yes i IPv6AcceptRA=yes al fitxer .network de l'enllaç ascendent; networkd documenta IPv6Forwarding com a global pel mateix motiu del nucli. Amb NetworkManager, ipv6.method=auto a l'enllaç ascendent és el que governa el valor d'accept_ra, així que torneu a llegir el sysctl després de nmcli connection up en lloc de confiar en la primera comprovació.

L'alternativa estàtica, ip -6 route add default via fe80::1 dev eth0, sí que funciona, i és una resposta raonable quan el router ascendent té una adreça link-local estable. Tingueu clar què hi perdeu. Una ruta per defecte estàtica no es renova mai ni es retira mai, així que continua apuntant a un veí mort després que es canviï l'enllaç ascendent. La ruta per RA falla de manera segura; l'estàtica falla en silenci.

Proveu un paquet reenviat, no el de la mateixa porta d'enllaç

Els ping propis de la porta d'enllaç poden tenir èxit en una ruta que cap client pot utilitzar, i també poden tenir èxit perquè la porta d'enllaç n'és la font. Proveu des d'un client connectat i després pregunteu a la porta d'enllaç què faria per a l'adreça d'aquell client:

# 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::2

Després espereu una vida de router i torneu a mirar. L'estat estable que voleu és una ruta per defecte marcada amb proto ra la qual el valor expires es reinicia constantment, més all.forwarding=1. Si expires només fa el compte enrere, els anuncis encara es descarten en algun lloc, i el culpable habitual és un gestor de xarxa que reescriu accept_ra després que el sysctl d'arrencada ja s'hagi executat.

Abans de tancar això, confirmeu quatre coses: la ruta per defecte és proto ra i es renova, accept_ra=2 només s'aplica a l'enllaç ascendent, el reenviament continua sent 1 després d'un reinici i després de reiniciar el gestor, i és un client, no la porta d'enllaç, qui completa un ping IPv6. Si el client encara falla amb una ruta sana, el següent sospitós és el camí de tornada o un tallafoc ascendent, no l'anunci.

Articles relacionats