Ridici tunelul, dai ping la fe80::1 cu tunelul ca interfață sursă și nu se întoarce nimic. Nu este o regulă de firewall uitată. O adresă link-local are sens doar pe acea singură legătură pe care a fost formată, iar un VPN rutat nu este acea legătură. fe80::1 al routerului îndepărtat se află în segmentul LAN îndepărtat; tu stai la un hop distanță într-un alt segment, iar IPv6 nu are niciun mecanism prin care un router să transmită mai departe pachete link-local.

Prefixul fe80 descrie un domeniu, nu un interval

Link-local unicast este fe80::/10, iar proprietatea definitorie nu este numărul, ci domeniul. Adresa este validă doar pe o legătură, iar fiecare interfață formează una din propriul identificator, de aceea două mașini fără legătură din două rețele fără legătură pot răspunde amândouă la fe80::1 fără cel mai mic conflict. Prefixul spune practic „pe o anumită legătură”; legătura în sine vine din context.

Pe un host, acel context este zona, sau scope ID, pe care o adaugi după semnul de procent: fe80::1%eth0 pe Linux, fe80::1%3 sau fe80::1%12 pe Windows și în instrumentele care expun indecși de interfață. Nucleul rezolvă adresa împreună cu indexul interfeței și abia apoi trimite. Dacă elimini zona, destinația devine ambiguă, așa că stiva nu are cum să aleagă un segment.

De ce un tunel rutat nu o poate livra

Un VPN rutat este o interfață punct-la-punct care poartă propriile adrese, de obicei un /64 de spațiu IPv6 unique-local sau privat în interiorul tunelului. LAN-ul îndepărtat este o legătură separată, atinsă de capătul tunelului care rutează și transmite în numele tău. Sunt două segmente distincte, așa că o adresă dintr-unul nu este o destinație validă în celălalt.

Regula de transmitere este explicită în standard, nu o ciudățenie a clientului tău: routerele nu transmit pachete cu sursă sau destinație link-local. De aceea pachetul moare chiar și când tabela de rutare pare corectă. Adaugă o rută pentru fe80::/64 spre tunel și o stivă conformă fie o respinge, fie o acceptă și aruncă fiecare pachet potrivit: domeniul destinației spune „doar această legătură”, iar interfața de ieșire nu este acea legătură.

Descoperirea vecinilor întărește aceeași graniță. Hosturile rezolvă următorii pași link-local printr-o cerere de vecin trimisă către multicast cu domeniu de legătură și limită de hop 255, așa că routerele pot respinge orice este transmis mai departe. A face asta să funcționeze prin tunel ar însemna să proxy-ezi descoperirea pentru un segment îndepărtat, ceea ce este punte Layer 2 într-o altă pălărie.

Există o a doua defecțiune mai tăcută și ea prinde oamenii care încearcă totuși să forțeze ruta: zona. Orice zonă tastezi local numește interfața tunelului, în timp ce adresa pe care o vrei este legată de interfața LAN-ului îndepărtat. Cele două nu se potrivesc niciodată, așa că pachetul nu poate fi direcționat către interfața corectă la capătul îndepărtat.

Cum arată defecțiunea în practică

Ieșirea instrumentului pentru o eroare de domeniu se citește ca o eroare de rutare sau de firewall și exact de aceea oamenii petrec o după-amiază în stratul greșit.

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

A treia linie pierde cel mai mult timp, pentru că un client ssh fără ieșire pare o problemă a serviciului care ascultă. Dacă ai vreo cale de intrare, verifică partea îndepărtată și confirmă dacă sshd este legat de toate adresele sau doar de una.

Folosește o adresă care a fost menită pentru rutare

Pentru tot ce trebuie să atingi prin tunel, folosește adresa care i-a fost dată serviciului exact în acest scop: o adresă unicast globală sau o adresă unique-local din fc00::/7, intervalul rezervat exact pentru acest caz intern. Confirmă că ascultătorul chiar o leagă și verifică calea de întoarcere și orice regulă de firewall a hostului.

Uită-te la hostul îndepărtat în loc să ghicești. ip -6 addr show listează adresele care există, iar ss -6 -ltn listează pe ce ascultă demonul. Un serviciu legat doar de fe80:: este accesibil doar din propriul segment, ceea ce de obicei este o valoare implicită pe care nimeni nu a ales-o intenționat și care poate fi schimbată cu acordul administratorului.

Când serviciul chiar nu poate fi relegat, mută puntea mai sus, la nivelul aplicației în loc de nivelul rețelei. Un relay pe hostul îndepărtat care ascultă pe o adresă rutabilă și se conectează la cea link-local rezolvă problema fără a extinde vreun segment:

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

Aici zona stă de partea corectă, pe hostul care chiar are eth0 pe acea legătură. Clientul tău vorbește cu fd00:1:2::10, care este rutat normal, iar relay-ul face saltul link-local local. Același truc funcționează pentru interfața web a unui aparat sau un BMC vechi care anunță doar o adresă link-local.

Când puntea este într-adevăr răspunsul, și ce trebuie verificat

Unele implementări au într-adevăr nevoie de un segment comun: un dispozitiv care vorbește doar descoperire link-local, un aparat care depinde de multicast, un laborator care reproduce un LAN plat. Este o problemă de Layer 2 și are nevoie de un răspuns de Layer 2, cum ar fi un dispozitiv tap punte către interfața îndepărtată sau un produs client cu mod punte explicit. Te costă trafic broadcast și multicast care traversează tunelul plus descoperirea vecinilor care trebuie să funcționeze cap la cap.

Nu te apropia de asta adăugând fe80::/64 la un profil rutat. Asta produce cea mai rea stare: configurația pare terminată, tabela de rutare arată o intrare, iar fiecare pachet este tot aruncat undeva între două stive care ambele se comportă corect.

Verifică cu interfața, nu cu ping. ip -6 addr show tun0 îți spune dacă legătura tunelului a format o adresă link-local proprie, iar ip -6 route get fe80::1%tun0 îți spune ce ar face nucleul de fapt cu o destinație cu domeniu. Când nucleul spune că destinația este inaccesibilă pe acea interfață, nicio setare de tunel nu va schimba asta, și este timpul să nu mai editezi profilul.

O secvență scurtă care lămurește întrebarea:

  • Citește adresa de pe hostul îndepărtat și notează dacă este fe80:: sau un prefix rutabil.
  • Dacă este fe80::, relegă serviciul, fă relay pe acel host sau punte segmentul; dacă este rutabil, repară ruta, firewall-ul sau adresa de bind.
  • Verifică zona de fiecare dată când retestezi, pentru că o comandă copiată păstrează de obicei interfața greșită.

Surse: RFC 4291, arhitectura de adresare IPv6.

Articole similare