IPv6-Link-Local funktioniert nicht über VPN: Warum fe80 am Link endet
Eine fe80::-Adresse bedeutet nur auf einem Link etwas. Lesen Sie, warum ein geroutetes VPN sie nicht transportieren kann, wie der Fehler aussieht und welche Adresse Sie stattdessen verwenden.
Sie bringen den Tunnel hoch, pingen fe80::1 mit dem Tunnel als Quellinterface und bekommen nichts zurück. Es ist keine Firewall-Regel, die Sie vergessen haben. Eine Link-Local-Adresse bedeutet nur auf dem einen Link etwas, auf dem sie gebildet wurde, und ein geroutetes VPN ist nicht dieser Link. Die fe80::1 des entfernten Routers lebt im entfernten LAN-Segment; Sie sitzen einen Hop entfernt in einem anderen Segment, und IPv6 hat keinerlei Mechanismus, mit dem ein Router Link-Local-Pakete überhaupt weiterleiten könnte.
Das Präfix fe80 beschreibt einen Gültigkeitsbereich, keinen Adressbereich
Link-Local-Unicast ist fe80::/10, und die entscheidende Eigenschaft ist nicht die Zahl, sondern der Gültigkeitsbereich. Die Adresse gilt nur auf einem Link, und jedes Interface bildet eine aus seiner eigenen Kennung; deshalb können zwei unabhängige Maschinen in zwei unabhängigen Netzen beide auf fe80::1 antworten, ohne den geringsten Konflikt. Das Präfix sagt im Grunde „auf irgendeinem Link“; der Link selbst kommt aus dem Kontext.
Auf einem Host ist dieser Kontext die Zone, also die Scope-ID, die Sie nach einem Prozentzeichen anhängen: fe80::1%eth0 unter Linux, fe80::1%3 oder fe80::1%12 unter Windows und in Werkzeugen, die Interface-Indizes offenlegen. Der Kernel löst die Adresse zusammen mit dem Interface-Index auf und sendet dann. Lassen Sie die Zone weg, ist das Ziel mehrdeutig, und der Stack kann kein Segment auswählen.
Warum ein gerouteter Tunnel sie nicht zustellen kann
Ein geroutetes VPN ist ein Punkt-zu-Punkt-Interface mit eigenen Adressen, üblicherweise ein /64 aus Unique-Local- oder privatem IPv6-Raum innerhalb des Tunnels. Das entfernte LAN ist ein separater Link, erreicht durch Routing und Weiterleitung des Tunnelendpunkts in Ihrem Namen. Das sind zwei verschiedene Segmente, also ist eine Adresse aus dem einen kein gültiges Ziel im anderen.
Die Weiterleitungsregel steht ausdrücklich in der Norm und ist keine Eigenheit Ihres Clients: Router leiten keine Pakete mit Link-Local-Quelle oder -Ziel weiter. Deshalb stirbt das Paket, selbst wenn die Routingtabelle korrekt aussieht. Fügen Sie eine Route für fe80::/64 auf den Tunnel hinzu, und ein normkonformer Stack lehnt sie entweder ab oder akzeptiert sie und verwirft jedes passende Paket: Der Zielbereich sagt „nur dieser Link“, und das ausgehende Interface ist nicht dieser Link.
Die Nachbarsuche verstärkt dieselbe Grenze. Hosts lösen Link-Local-Nexthops mit einer Nachbaranfrage auf, die an Multicast im Linkbereich mit einem Hop-Limit von 255 gesendet wird, sodass Router alles Weitergeleitete ablehnen können. Das über einen Tunnel zum Laufen zu bringen, hieße, die Erkennung für ein entferntes Segment zu proxen, was Layer-2-Bridging mit einem anderen Hut ist.
Es gibt einen leiseren zweiten Fehler, und er bringt Leute ins Stolpern, die die Route trotzdem erzwingen wollen: die Zone. Welche Zone Sie lokal eintippen, sie benennt das Tunnel-Interface, während die gewünschte Adresse an das Interface des entfernten LANs gebunden ist. Die beiden passen nie zusammen, also lässt sich das Paket am fernen Ende nicht auf das richtige Interface lenken.
Wie der Fehler in der Praxis aussieht
Tool-Ausgaben bei einem Bereichsfehler lesen sich wie ein Routing- oder Firewall-Fehler, und genau deshalb verbringen Leute einen Nachmittag in der falschen Schicht.
| 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 |
Die dritte Zeile kostet die meiste Zeit, denn ein ssh-Client ohne Ausgabe sieht wie ein Problem eines lauschenden Dienstes aus. Wenn Sie irgendwie hineinkommen, schauen Sie auf die Gegenseite und prüfen Sie, ob sshd an alle Adressen oder nur an eine gebunden ist.
Verwenden Sie eine Adresse, die zum Routen gedacht war
Für alles, was Sie durch den Tunnel erreichen müssen, verwenden Sie die Adresse, die der Dienst genau dafür bekommen hat: eine globale Unicast-Adresse oder eine Unique-Local-Adresse aus fc00::/7, den Bereich, der genau für diesen internen Fall reserviert ist. Prüfen Sie, ob der Listener sie tatsächlich bindet, und prüfen Sie den Rückweg und jede Firewall-Regel des Hosts.
Sehen Sie auf den entfernten Host, statt zu raten. ip -6 addr show listet die vorhandenen Adressen, und ss -6 -ltn listet, worauf der Daemon lauscht. Ein Dienst, der nur an fe80:: gebunden ist, ist nur aus seinem eigenen Segment erreichbar, was meist eine Voreinstellung ist, die niemand absichtlich gewählt hat und die mit Zustimmung des Administrators geändert werden kann.
Wenn der Dienst wirklich nicht neu gebunden werden kann, heben Sie die Brücke auf die Anwendungsschicht statt auf die Netzwerkschicht. Ein Relay auf dem entfernten Host, das auf einer routbaren Adresse lauscht und sich mit der Link-Local-Adresse verbindet, löst das Problem, ohne irgendein Segment auszudehnen:
socat TCP6-LISTEN:8080,bind=[fd00:1:2::10] TCP6:[fe80::1%eth0]:80Hier sitzt die Zone auf der richtigen Seite, auf dem Host, der tatsächlich eth0 an diesem Link hat. Ihr Client spricht mit fd00:1:2::10, das normal geroutet wird, und das Relay macht den Link-Local-Hop lokal. Derselbe Trick funktioniert für die Weboberfläche eines Geräts oder ein altes BMC, das nur eine Link-Local-Adresse ankündigt.
Wann Bridging wirklich die Antwort ist und was zu prüfen ist
Manche Umgebungen brauchen wirklich ein gemeinsames Segment: ein Gerät, das nur Link-Local-Erkennung spricht, ein Gerät, das von Multicast abhängt, ein Labor, das ein flaches LAN nachbildet. Das ist ein Layer-2-Problem und braucht eine Layer-2-Antwort, etwa ein Tap-Gerät, das auf das entfernte Interface gebrückt ist, oder ein Client-Produkt mit ausdrücklichem Bridge-Modus. Es kostet Sie Broadcast- und Multicast-Verkehr über den Tunnel plus Nachbarsuche, die Ende zu Ende funktionieren muss.
Nähern Sie das nicht an, indem Sie fe80::/64 zu einem gerouteten Profil hinzufügen. Das erzeugt den schlechtesten Zustand von allen: Die Konfiguration sieht fertig aus, die Routingtabelle zeigt einen Eintrag, und jedes Paket wird trotzdem irgendwo zwischen zwei Stacks verworfen, die sich beide korrekt verhalten.
Prüfen Sie mit dem Interface statt mit dem Ping. ip -6 addr show tun0 sagt Ihnen, ob der Tunnel-Link eine eigene Link-Local-Adresse gebildet hat, und ip -6 route get fe80::1%tun0 sagt, was der Kernel mit einem Ziel im Bereich tatsächlich tun würde. Wenn der Kernel sagt, das Ziel sei auf diesem Interface nicht erreichbar, ändert keine Tunnel-Einstellung das, und es ist Zeit, das Profil nicht mehr zu bearbeiten.
Eine kurze Reihenfolge, die die Frage klärt:
- Lesen Sie die Adresse auf dem entfernten Host und notieren Sie, ob es fe80:: oder ein routbares Präfix ist.
- Ist es fe80::, binden Sie den Dienst neu, relayen Sie auf diesem Host oder brücken Sie das Segment; ist es routbar, korrigieren Sie die Route, die Firewall oder die Bind-Adresse.
- Prüfen Sie die Zone bei jedem erneuten Test, denn ein kopierter Befehl behält meist das falsche Interface.
Quellen: RFC 4291, IPv6-Adressarchitektur.