Du får upp tunneln, pingar fe80::1 med tunneln som källgränssnitt och får ingenting tillbaka. Det är inte en brandväggsregel du glömt. En link-local-adress har bara betydelse på den enda länk där den bildades, och en routad VPN är inte den länken. fe80::1 hos fjärrroutern ligger på fjärr-LAN-segmentet; du sitter ett hopp bort på ett annat segment, och IPv6 har ingen mekanism för att en router vidarebefordrar link-local-paket över huvud taget.

fe80-prefixet beskriver en omfattning, inte ett intervall

Link-local unicast är fe80::/10, och den avgörande egenskapen är inte talet utan omfattningen. Adressen är giltig bara på en länk, och varje gränssnitt bildar en från sin egen identifierare, därför kan två orelaterade maskiner på två orelaterade nätverk båda svara på fe80::1 utan minsta konflikt. Prefixet säger i praktiken ”på någon länk”; själva länken kommer från sammanhanget.

På en värd är det sammanhanget zonen, eller scope ID, som du lägger till efter ett procenttecken: fe80::1%eth0 på Linux, fe80::1%3 eller fe80::1%12 på Windows och i verktyg som visar gränssnittsindex. Kärnan löser adressen tillsammans med gränssnittsindexet och skickar sedan. Tar du bort zonen blir målet tvetydigt, så stacken har inget sätt att välja ett segment.

Varför en routad tunnel inte kan leverera den

En routad VPN är ett punkt-till-punkt-gränssnitt som bär sina egna adresser, vanligen ett /64 av unique-local eller privat IPv6-rymd inne i tunneln. Fjärr-LAN:et är en separat länk, nådd av tunnelns ändpunkt som routar och vidarebefordrar å dina vägnar. Det är två olika segment, så en adress från det ena är inte ett giltigt mål på det andra.

Vidarebefordringsregeln står uttryckligen i standarden och är ingen egenhet hos din klient: routrar vidarebefordrar inte paket med link-local källa eller mål. Därför dör paketet även när routingtabellen ser korrekt ut. Lägg till en rutt för fe80::/64 mot tunneln och en standardenlig stack antingen avvisar den eller accepterar den och släpper varje matchande paket: målets omfattning säger ”bara den här länken”, och det utgående gränssnittet är inte den länken.

Grannupptäckt förstärker samma gräns. Värdar löser link-local nästa hopp med en granneförfrågan som skickas till multicast med länkomfattning och hoppgräns 255, så routrar kan avvisa allt som vidarebefordras. Att få det att fungera över en tunnel skulle innebära att proxy:a upptäckten för ett fjärrsegment, vilket är Layer 2-bryggning i en annan hatt.

Det finns ett tystare andra fel, och det fångar människor som ändå försöker tvinga fram rutten: zonen. Vilken zon du än skriver lokalt namnger den tunnelgränssnittet, medan adressen du vill ha är bunden till fjärr-LAN-gränssnittet. De två matchar aldrig, så paketet kan inte styras till rätt gränssnitt i andra änden.

Hur felet ser ut i praktiken

Verktygsutdata för ett omfattningsfel läses som ett routing- eller brandväggsfel, och det är precis därför människor tillbringar en eftermiddag i fel lager.

What you runWhat you seeWhat it means
ping fe80::1 with no zoneInvalid argument on Linux, or a transmit failure on WindowsThe stack cannot pick an interface for an ambiguous destination
ping -6 -I tun0 fe80::1Destination unreachable, or a silent timeoutThe address is not on the tunnel link, so there is nothing on-link to answer
ssh user@fe80::1 after the tunnel is upHangs, then no route to hostThe SYN never left the machine in a deliverable form; the server logs nothing
ip -6 neigh show dev tun0Empty tableNo neighbor entry can exist for a link-local host that is not on this link
fe80::/64 inside AllowedIPs or route-ipv6Config accepted, traffic still droppedThe tunnel carried the packet; the receiving stack refused to forward it

Den tredje raden slösar mest tid, eftersom en ssh-klient utan utdata ser ut som ett problem med en lyssnande tjänst. Om du har något sätt in, kontrollera fjärrsidan och bekräfta om sshd är bunden till alla adresser eller bara en.

Använd en adress som var avsedd att routas

För allt du måste nå genom tunneln, använd adressen tjänsten fick just för detta ändamål: en global unicast-adress, eller en unique-local-adress från fc00::/7, intervallet som är reserverat just för detta interna fall. Bekräfta att lyssnaren verkligen binder den, och kontrollera returvägen och varje brandväggsregel på värden.

Titta på fjärrvärden i stället för att gissa. ip -6 addr show listar adresserna som finns, och ss -6 -ltn listar vad daemonen lyssnar på. En tjänst som bara är bunden till fe80:: går bara att nå från sitt eget segment, vilket vanligen är en standard som ingen valde medvetet och som kan ändras med administratörens samtycke.

När tjänsten verkligen inte kan bindas om, flytta upp bryggan till applikationslagret i stället för nätverkslagret. En relay på fjärrvärden som lyssnar på en routbar adress och ansluter till den link-local adressen löser problemet utan att utöka något segment:

socat TCP6-LISTEN:8080,bind=[fd00:1:2::10] TCP6:[fe80::1%eth0]:80

Här sitter zonen på rätt sida, på värden som verkligen har eth0 på den länken. Din klient talar med fd00:1:2::10, som routas normalt, och relayen gör link-local-hoppet lokalt. Samma knep fungerar för ett web-gränssnitt på en apparat eller en gammal BMC som bara annonserar en link-local-adress.

När bryggning verkligen är svaret, och vad du bör kontrollera

Vissa installationer behöver verkligen ett delat segment: en enhet som bara talar link-local-upptäckt, en apparat som är beroende av multicast, ett labb som återskapar ett platt LAN. Det är ett Layer 2-problem och det kräver ett Layer 2-svar, som en tap-enhet bryggad till fjärrgränssnittet eller en klientprodukt med ett uttryckligt bryggläge. Det kostar dig broadcast- och multicasttrafik som korsar tunneln plus grannupptäckt som måste fungera från ände till ände.

Närma dig inte detta genom att lägga till fe80::/64 i en routad profil. Det ger det sämsta tillståndet: konfigurationen ser färdig ut, routingtabellen visar en post, och varje paket släpps fortfarande någonstans mellan två stackar som båda beter sig korrekt.

Verifiera med gränssnittet i stället för med ping. ip -6 addr show tun0 berättar om tunnellänken bildade en egen link-local-adress, och ip -6 route get fe80::1%tun0 berättar vad kärnan faktiskt skulle göra med ett mål med omfattning. När kärnan säger att målet är onåbart på det gränssnittet ändrar ingen tunnelinställning det, och det är dags att sluta redigera profilen.

En kort sekvens som avgör frågan:

  • Läs adressen på fjärrvärden och notera om den är fe80:: eller ett routbart prefix.
  • Om den är fe80::, bind om tjänsten, relay på den värden eller brygga segmentet; om den är routbar, rätta rutten, brandväggen eller bind-adressen.
  • Kontrollera zonen varje gång du testar om, eftersom ett kopierat kommando vanligen behåller fel gränssnitt.

Källor: RFC 4291, IPv6-adressarkitektur.

Relaterade artiklar