IPv6 link-local fungerer ikkje over VPN: kvifor fe80 stoppar ved lenkja
Ei fe80:: adresse har berre tyding på éi lenkje. Sjå kvifor eit ruta VPN ikkje kan bera henne, korleis feilen ser ut, og kva adresse du bør bruke i staden.
Du får opp tunnelen, pingar fe80::1 med tunnelen som kjeldegrensesnitt, og får ingenting tilbake. Det er ikkje ei brannmurregel du gløymde. Ei link-local-adresse har berre tyding på den eine lenkja der ho vart danna, og eit ruta VPN er ikkje den lenkja. fe80::1 til den eksterne rutaren ligg på det eksterne LAN-segmentet; du sit eitt hopp unna på eit anna segment, og IPv6 har ingen mekanisme for at ein rutar vidaresender link-local-pakkar i det heile teke.
fe80-prefikset skildrar eit omfang, ikkje eit område
Link-local unicast er fe80::/10, og den definerande eigenskapen er ikkje talet, men omfanget. Adressa er gyldig berre på éi lenkje, og kvart grensesnitt dannar éi frå sin eigen identifikator, og difor kan to uslekta maskinar på to uslekta nettverk båe svare på fe80::1 utan den minste konflikt. Prefikset seier i praksis «på ei eller anna lenkje»; sjølve lenkja kjem frå konteksten.
På ein vert er den konteksten sona, eller scope ID, som du legg til etter eit prosentteikn: fe80::1%eth0 på Linux, fe80::1%3 eller fe80::1%12 på Windows og i verktøy som viser grensesnittindeksar. Kjernen løyser adressa saman med grensesnittindeksen og sender deretter. Fjernar du sona, blir målet tvitydig, så stakken har ingen måte å velje eit segment på.
Kvifor ein ruta tunnel ikkje kan levere henne
Eit ruta VPN er eit punkt-til-punkt-grensesnitt som ber sine eigne adresser, vanlegvis eit /64 av unique-local eller privat IPv6-rom inne i tunnelen. Det eksterne LAN-et er ei separat lenkje, nådd av tunnelendepunktet som rutar og vidaresender på dine vegner. Det er to ulike segment, så ei adresse frå det eine er ikkje eit gyldig mål på det andre.
Vidaresendingsregelen står eksplisitt i standarden og er ikkje ein særheit ved klienten din: rutarar vidaresender ikkje pakkar med link-local kjelde eller mål. Difor døyr pakken sjølv når rutetabellen ser riktig ut. Legg du til ei rute for fe80::/64 mot tunnelen, vil ein standardkonform stakk anten avvise henne eller godta henne og droppe kvar samsvarande pakke: omfanget til målet seier «berre denne lenkja», og det utgåande grensesnittet er ikkje den lenkja.
Nabo-oppdaging forsterkar same grensa. Vertar løyser link-local neste hopp med ein nabo-førespurnad send til multicast med lenkjeomfang og hoppgrens 255, så rutarar kan avvise alt som blir vidaresendt. Å få det til å verke over ein tunnel ville bety å proxy oppdaginga for eit eksternt segment, som er Layer 2-bruing i ein annan hatt.
Det finst ein stillare andre feil, og han fangar folk som likevel prøver å tvinge ruta: sona. Kva sone du enn skriv lokalt, namngjev ho tunnelgrensesnittet, medan adressa du vil ha er bunden til det eksterne LAN-grensesnittet. Dei to stemmer aldri overeins, så pakken kan ikkje styrast til rett grensesnitt i den andre enden.
Korleis feilen ser ut i praksis
Verktøyutdata for ein omfangfeil blir lese som ein ruting- eller brannmurfeil, og det er nettopp difor folk brukar ein ettermiddag i feil lag.
| What you run | What you see | What it means |
|---|---|---|
| ping fe80::1 with no zone | Invalid argument on Linux, or a transmit failure on Windows | The stack cannot pick an interface for an ambiguous destination |
| ping -6 -I tun0 fe80::1 | Destination unreachable, or a silent timeout | The address is not on the tunnel link, so there is nothing on-link to answer |
| ssh user@fe80::1 after the tunnel is up | Hangs, then no route to host | The SYN never left the machine in a deliverable form; the server logs nothing |
| ip -6 neigh show dev tun0 | Empty table | No neighbor entry can exist for a link-local host that is not on this link |
| fe80::/64 inside AllowedIPs or route-ipv6 | Config accepted, traffic still dropped | The tunnel carried the packet; the receiving stack refused to forward it |
Den tredje rada kastar bort mest tid, fordi ein ssh-klient utan utdata ser ut som eit problem med ein lyttande teneste. Har du nokon måte å kome inn på, sjekk den eksterne sida og stadfest om sshd er bunden til alle adresser eller berre éi.
Bruk ei adresse som var meint for ruting
For alt du må nå gjennom tunnelen, bruk adressa tenesta fekk til nettopp dette føremålet: ei global unicast-adresse, eller ei unique-local-adresse frå fc00::/7, området som er reservert nettopp for dette interne tilfellet. Stadfest at lyttaren faktisk bind henne, og kontroller returvegen og kvar brannmurregel på verten.
Sjå på den eksterne verten i staden for å gjette. ip -6 addr show listar adressene som finst, og ss -6 -ltn listar kva daemonen lyttar på. Ei teneste som berre er bunden til fe80::, er berre tilgjengeleg frå sitt eige segment, noko som vanlegvis er ein standard ingen valde med vilje, og som kan endrast med samtykket til administratoren.
Når tenesta verkeleg ikkje kan bindast på nytt, flytt brua opp til applikasjonslaget i staden for nettverkslaget. Ein relay på den eksterne verten som lyttar på ei rutbar adresse og koplar til den link-local adressa, løyser problemet utan å utvide noko segment:
socat TCP6-LISTEN:8080,bind=[fd00:1:2::10] TCP6:[fe80::1%eth0]:80Her sit sona på rett side, på verten som faktisk har eth0 på den lenkja. Klienten din snakkar med fd00:1:2::10, som blir ruta normalt, og relayen gjer link-local-hoppet lokalt. Same triks fungerer for eit webgrensesnitt på eit apparat eller ein gammal BMC som berre annonserer ei link-local-adresse.
Når bruing verkeleg er svaret, og kva du bør sjekke
Nokre utplasseringar treng verkeleg eitt delt segment: ein eining som berre snakkar link-local-oppdaging, eit apparat som er avhengig av multicast, eit laboratorium som reproduserer eit flatt LAN. Det er eit Layer 2-problem, og det treng eit Layer 2-svar, som ein tap-eining brua til det eksterne grensesnittet eller eit klientprodukt med ein eksplisitt bru-modus. Det kostar deg broadcast- og multicast-trafikk som kryssar tunnelen, pluss nabooppdaging som må verke ende til ende.
Ikkje nærm deg dette ved å leggje fe80::/64 til ein ruta profil. Det gir den verste tilstanden: konfigurasjonen ser ferdig ut, rutetabellen viser ei oppføring, og kvar pakke blir framleis forkasta ein stad mellom to stakkar som båe oppfører seg riktig.
Verifiser med grensesnittet i staden for med ping. ip -6 addr show tun0 fortel om tunnellenkja danna si eiga link-local-adresse, og ip -6 route get fe80::1%tun0 fortel kva kjernen faktisk ville gjere med eit mål med omfang. Når kjernen seier at målet er uoppnåeleg på det grensesnittet, vil inga tunnelinnstilling endre det, og det er på tide å slutte å redigere profilen.
Ein kort sekvens som avgjer spørsmålet:
- Les adressa på den eksterne verten og legg merke til om ho er fe80:: eller eit rutbart prefiks.
- Er ho fe80::, bind tenesta på nytt, relay på den verten, eller bru segmentet; er ho rutbar, rett opp ruta, brannmuren eller bind-adressa.
- Sjekk sona på nytt kvar gong du testar på nytt, fordi ein kopiert kommando vanlegvis held på feil grensesnitt.
Kjelder: RFC 4291, IPv6-adresseringsarkitektur.