IPv6-standardrute forsvandt efter aktiveret videresendelse på Linux
Når du aktiverer IPv6-videresendelse, ignorerer kernen routerannoncer på uplink, og den lærte standardrute udløber. Ret det med accept_ra.
Jeg satte net.ipv6.conf.all.forwarding=1 på en Debian-gateway, så den kunne videresende VPN-klienttrafik, og omkring en halv time senere havde boksen ingen IPv6-standardrute tilbage. Den opstrøms router var oppe, den linklokale nabo svarede stadig, og uplink havde stadig sin globale adresse. Det, der var stoppet, var kernens vilje til fortsat at tage imod routerannoncer på det interface. Ruten forsvandt ikke, da jeg skrev sysctl-kommandoen; den forsvandt, da levetiden på den RA-lærte standard løb ud, og intet fornyede den.
Intet så ødelagt ud ved første øjekast. Videresendelsen virkede, klienterne kom igennem, mens den gamle rute stadig var cachet, og fejlen kom senere end den ændring, der forårsagede den. Den forsinkelse er grunden til, at dette bliver skudt på uplink eller på en firewallregel, der aldrig var involveret.
Læs rutetabellen, før du rører ved nogen sysctl
Start med ip -6 route show default og læs attributterne, ikke bare gatewayen. En RA-lært standard er markeret proto ra, bærer en præference og viser en expires-nedtælling. En rute, du har tilføjet manuelt, har ingen af delene, og den forskel fortæller dig, hvilken mekanisme der ejer ruten.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumSe derefter på adressen: ip -6 addr show dev eth0. En global adresse med foretrukne og gyldige levetider målt i timer overlever en standardrute, hvis routerlevetid måles i minutter. Adresse til stede plus standard mangler er signaturen på et annonceringsproblem. Mangler adressen også, er det linket, præfiksoplysningerne eller dobbelt adressedetektion, du skal jagte først.
Hvorfor videresendelse slår RA-behandling fra
En RA er en ICMPv6-pakke af type 134, sendt fra en linklokal kilde med hopgrænse 255. Før kernen bruger den, konsulterer den interfacets accept_ra. Standardværdien er 1, og 1 betyder ikke ja. Det betyder accepter kun, mens denne vært ikke videresender. Sæt forwarding=1, og den betingelse fejler, så annoncen kasseres, før noget præfiks eller standardrouter i den overvejes.
Der findes tre værdier, og kun den tredje overlever videresendelse:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
To andre flag afgør, hvad der faktisk bliver installeret. accept_ra_defrtr styrer, om standardrouteren i annoncen bliver en rute, og accept_ra_pinfo styrer, om præfiksoplysninger bruges til adressekonfiguration. At slå accept_ra_defrtr fra er den sædvanlige måde at beholde SLAAC-adresser på en videresendende vært uden at lære en standard. Det er et andet håndtag end accept_ra, og det er det, du skal gribe efter, når du vil have adresser men ikke en rute. Kernens IP-sysctl-reference lister alle tre.
Bekræft det med tre kommandoer
Læs først de levende værdier i stedet for den fil, du tror er indlæst:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrBevis for det andet, at annoncerne stadig kommer. Filtrering på ICMPv6-typebyten er nok, og det undgår at læse en mur af nabo-opdagelsestrafik:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'Hvis der ikke dukker noget op i løbet af flere minutter, er accept_ra ikke dit problem. Uplink holdt op med at annoncere, noget på vejen filtrerer ICMPv6, eller også er det interface ikke rigtigt på det segment, du tror. Bed for det tredje selv om en annonce og læs dens felter:
rdisc6 eth0rdisc6 leveres i ndisc6-pakken på Debian og Ubuntu. I outputtet skal du se på routerlevetiden og præferencen, før du ændrer noget andet. En annonce med routerlevetid 0 er en instruks om at fjerne standardrouteren, og ingen accept_ra-værdi gør det til en brugbar rute. Det er også sådan, du fanger en opstrøms CPE i bridge-tilstand, der uddeler præfikser, men aldrig tilbyder sig selv som router.
Gør uplink til det eneste tilladende interface
Hvis uplink skal være standardrouteren, så accepter annoncer der trods videresendelse, og ingen andre steder:
# /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 = 1Afgrænsningen betyder noget, fordi IPv6-videresendelse er én global kontakt i Linux, ikke én pr. link. Skriv 1 til net.ipv6.conf.wg0.forwarding og læs derefter net.ipv6.conf.all.forwarding: den globale værdi vender, og hvert interface begynder at videresende. Du kan ikke være router på tunnelen og almindelig vært på LAN'et. Det, du kan afgrænse, er accepten. Behold accept_ra=2 på uplink og lad tunne- og LAN-interfaces stå på 1 eller 0, så en vildfaren annonce, der ankommer over tunnelen, ikke kan installere en standard, der peger ind i den.
En midlertidig sysctl -w overlever ikke næste genstart, og både systemd-networkd og NetworkManager skriver disse værdier fra deres egen konfiguration. I networkd skal du sætte IPv6Forwarding=yes og IPv6AcceptRA=yes i uplinkets .network-fil; networkd beskriver IPv6Forwarding som global af samme kernel-grund. Med NetworkManager er ipv6.method=auto på uplink det, der driver accept_ra-værdien, så læs sysctl igen efter nmcli connection up i stedet for at stole på den første kontrol.
Det statiske alternativ, ip -6 route add default via fe80::1 dev eth0, virker faktisk, og det er et rimeligt svar, når den opstrøms router har en stabil linklokal adresse. Vær klar over, hvad du giver afkald på. En statisk standard bliver aldrig fornyet og aldrig tilbagetrukket, så den bliver ved med at pege på en død nabo, efter at uplink er udskiftet. RA-ruten fejler sikkert; den statiske fejler stille.
Test en videresendt pakke, ikke gatewayens egen
Gatewayens egne ping kan lykkes på en rute, ingen klient kan bruge, og de kan også lykkes, fordi gatewayen er kilden. Test fra en tilsluttet klient, og spørg derefter gatewayen, hvad den ville gøre for den klients adresse:
# 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::2Vent derefter en routerlevetid og se igen. Den stabile tilstand, du vil have, er en standard markeret proto ra, hvis expires-værdi bliver ved med at nulstille, plus all.forwarding=1. Hvis expires kun tæller ned, bliver annoncer stadig kasseret et sted, og den sædvanlige skyldige er en netværksmanager, der overskriver accept_ra, efter boot-tidens sysctl allerede har kørt.
Før du lukker dette, skal du bekræfte fire ting: standardruten er proto ra og fornyes, accept_ra=2 gælder kun for uplink, videresendelse er stadig 1 efter en genstart og efter en manager-genstart, og en klient snarere end gatewayen gennemfører et IPv6-ping. Hvis klienten stadig fejler med en sund rute, er den næste mistænkte returvejen eller en opstrøms firewall, ikke annoncen.