Ruta implicită IPv6 a dispărut după activarea redirecționării în Linux
Când activați redirecționarea IPv6, nucleul ignoră router advertisements pe uplink, iar ruta implicită învățată expiră. Remediați cu accept_ra.
Am setat net.ipv6.conf.all.forwarding=1 pe un gateway Debian ca să poată redirecționa traficul clienților VPN, iar după aproximativ o jumătate de oră mașina nu mai avea nicio rută implicită IPv6. Routerul din amonte funcționa, vecinul link-local răspundea în continuare, iar uplink-ul își păstra adresa globală. Ce se oprise era disponibilitatea nucleului de a accepta în continuare router advertisements pe acea interfață. Ruta nu a dispărut când am scris sysctl-ul; a dispărut când durata de viață a rutei implicite învățate din RA a expirat și nimic nu a reînnoit-o.
Nimic nu părea defect la prima vedere. Redirecționarea funcționa, clienții treceau încă cât timp ruta veche era în cache, iar defecțiunea a apărut mai târziu decât modificarea care a cauzat-o. Exact această întârziere face ca problema să fie pusă pe seama laturii din amonte sau a unei reguli de firewall care nu a fost niciodată implicată.
Citiți tabela de rutare înainte de a atinge orice sysctl
Începeți cu ip -6 route show default și citiți atributele, nu doar gateway-ul. O rută implicită învățată din RA este marcată cu proto ra, poartă o preferință și arată o numărătoare inversă expires. O rută adăugată manual nu are niciuna dintre ele, iar această diferență vă spune ce mecanism deține ruta.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumApoi uitați-vă la adresă: ip -6 addr show dev eth0. O adresă globală cu durate de viață preferată și validă măsurate în ore va supraviețui unei rute implicite a cărei durată de viață a routerului se măsoară în minute. Adresă prezentă și rută implicită lipsă este semnătura unei probleme de anunțuri. Dacă lipsește și adresa, mai întâi trebuie urmărite legătura, informația de prefix sau detectarea adreselor duplicate.
De ce redirecționarea oprește procesarea RA
Un RA este un pachet ICMPv6 de tip 134, trimis dintr-o sursă link-local cu limita de salt 255. Înainte ca nucleul să îl folosească, consultă accept_ra interfeței. Valoarea implicită este 1, iar 1 nu înseamnă da. Înseamnă: acceptă doar cât timp acest gazdă nu redirecționează. Setați forwarding=1 și acea condiție nu mai este îndeplinită, așa că anunțul este aruncat înainte de a fi luat în calcul vreun prefix sau router implicit din el.
Există trei valori, iar redirecționarea este supraviețuită doar de a treia:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
Alte două fanioane decid ce se instalează de fapt. accept_ra_defrtr controlează dacă routerul implicit din anunț devine rută, iar accept_ra_pinfo controlează dacă informația de prefix este folosită pentru configurarea adresei. Dezactivarea accept_ra_defrtr este modalitatea obișnuită de a păstra adrese SLAAC pe o gazdă care redirecționează fără a învăța o rută implicită. Este o pârghie diferită de accept_ra și este cea la care apelați când doriți adrese, dar nu o rută. Referința nucleului despre IP sysctl le enumeră pe toate trei.
Confirmați cu trei comenzi
Mai întâi, citiți valorile active în locul fișierului pe care credeți că l-ați încărcat:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrÎn al doilea rând, demonstrați că anunțurile încă sosesc. Filtrarea după octetul de tip ICMPv6 este suficientă și vă scutește de citirea unui zid de trafic de descoperire a vecinilor:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'Dacă nu apare nimic timp de câteva minute, accept_ra nu este problema dumneavoastră. Partea din amonte a încetat să anunțe, ceva de pe traseu filtrează ICMPv6 sau acea interfață nu este de fapt în segmentul la care vă gândiți. În al treilea rând, solicitați singuri un anunț și citiți-i câmpurile:
rdisc6 eth0rdisc6 vine în pachetul ndisc6 pe Debian și Ubuntu. În ieșire, uitați-vă la durata de viață a routerului și la preferință înainte de a schimba orice altceva. Un anunț cu durata de viață a routerului 0 este o instrucțiune de a elimina routerul implicit, iar nicio valoare accept_ra nu transformă asta într-o rută utilizabilă. Tot așa prindeți un CPE din amonte în modul bridge care distribuie prefixe, dar nu se oferă niciodată ca router.
Faceți din uplink singura interfață permisivă
Dacă partea din amonte trebuie să fie routerul implicit, acceptați acolo anunțuri în ciuda redirecționării, și nicăieri altundeva:
# /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 = 1Limitarea contează pentru că redirecționarea IPv6 în Linux este un singur comutator global, nu unul pe legătură. Scrieți 1 în net.ipv6.conf.wg0.forwarding și apoi citiți net.ipv6.conf.all.forwarding: valoarea globală se inversează și fiecare interfață începe să redirecționeze. Nu puteți fi router pe tunel și gazdă obișnuită în LAN. Ceea ce puteți limita este acceptarea. Țineți accept_ra=2 pe uplink și lăsați interfețele tunelului și ale LAN-ului pe 1 sau 0, ca un anunț rătăcit care sosește prin tunel să nu poată instala o rută implicită care indică în el.
Un sysctl -w temporar nu va supraviețui următoarei porniri, iar atât systemd-networkd cât și NetworkManager scriu aceste valori din propria configurație. În networkd, setați IPv6Forwarding=yes și IPv6AcceptRA=yes în fișierul .network al uplink-ului; networkd documentează IPv6Forwarding ca global din același motiv legat de nucleu. Cu NetworkManager, ipv6.method=auto pe uplink este cel care comandă valoarea accept_ra, așa că recitiți sysctl-ul după nmcli connection up în loc să vă bazați pe prima verificare.
Alternativa statică, ip -6 route add default via fe80::1 dev eth0, funcționează într-adevăr și este un răspuns rezonabil când routerul din amonte are o adresă link-local stabilă. Fiți clar în privința a ceea ce cedați. O rută implicită statică nu este niciodată reînnoită și niciodată retrasă, așa că indică în continuare un vecin mort după ce partea din amonte este înlocuită. Ruta din RA eșuează în siguranță; cea statică eșuează în tăcere.
Testați un pachet redirecționat, nu pe cel al gateway-ului însuși
Ping-urile proprii ale gateway-ului pot reuși pe o rută pe care niciun client nu o poate folosi și pot reuși și pentru că gateway-ul este sursa. Testați de la un client conectat, apoi întrebați gateway-ul ce ar face pentru adresa acelui 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::2Apoi așteptați o durată de viață a routerului și priviți din nou. Starea stabilă dorită este o rută implicită marcată cu proto ra a cărei valoare expires se resetează continuu, plus all.forwarding=1. Dacă expires doar numără invers, anunțurile sunt încă aruncate undeva, iar vinovatul obișnuit este un manager de rețea care rescrie accept_ra după ce sysctl-ul de la pornire a rulat deja.
Înainte de a încheia, confirmați patru lucruri: ruta implicită este proto ra și se reînnoiește, accept_ra=2 se aplică doar uplink-ului, redirecționarea este încă 1 după o repornire și după repornirea managerului, iar un client, nu gateway-ul, finalizează un ping IPv6. Dacă clientul tot eșuează cu o rută sănătoasă, următorul suspect este calea de întoarcere sau un firewall din amonte, nu anunțul.