Ви піднімаєте тунель, пінгуєте fe80::1, вказавши тунель вихідним інтерфейсом, і нічого не повертається. Це не забуте правило брандмауера. Link-local адреса має сенс лише на тому єдиному каналі, де вона сформована, а маршрутизований VPN — не цей канал. fe80::1 віддаленого маршрутизатора живе у віддаленому сегменті LAN; ви перебуваєте на один перехід далі в іншому сегменті, і в IPv6 взагалі немає механізму, який дозволяв би маршрутизатору пересилати link-local пакети.

Префікс fe80 описує область дії, а не діапазон

Link-local unicast — це fe80::/10, і визначальною властивістю є не число, а область дії. Адреса дійсна лише в одному каналі, і кожен інтерфейс формує свою з власного ідентифікатора, тому дві незв'язані машини в двох незв'язаних мережах можуть обидві відповідати на fe80::1 без найменшого конфлікту. Префікс, по суті, каже «у якомусь каналі»; сам канал береться з контексту.

На хості цей контекст — зона, або scope ID, яку ви додаєте після знака відсотка: fe80::1%eth0 у Linux, fe80::1%3 або fe80::1%12 у Windows і в інструментах, що показують індекси інтерфейсів. Ядро розв'язує адресу разом з індексом інтерфейсу і потім надсилає. Приберіть зону, і призначення стане неоднозначним, тому стек не має способу вибрати сегмент.

Чому маршрутизований тунель не може її доставити

Маршрутизований VPN — це інтерфейс «точка-точка», що несе власні адреси, зазвичай /64 із unique-local або приватного простору IPv6 усередині тунелю. Віддалений LAN — окремий канал, до якого кінцева точка тунелю доходить, маршрутизуючи й пересилаючи від вашого імені. Це два різні сегменти, тому адреса з одного не є допустимим призначенням в іншому.

Правило пересилання прямо записане в стандарті, а не є примхою вашого клієнта: маршрутизатори не пересилають пакети з link-local джерелом або призначенням. Саме тому пакет гине навіть тоді, коли таблиця маршрутизації виглядає правильно. Додайте маршрут для fe80::/64 у бік тунелю, і стек, що відповідає стандарту, або відхилить його, або прийме й відкине кожен відповідний пакет: область призначення каже «лише цей канал», а вихідний інтерфейс — не цей канал.

Виявлення сусідів зміцнює ту саму межу. Хости розв'язують link-local наступні переходи запитом сусіда, що надсилається в multicast з областю каналу й обмеженням переходів 255, тому маршрутизатори можуть відхиляти все переслане. Змусити це працювати через тунель означало б проксіювати виявлення для віддаленого сегмента, а це міст Layer 2 в іншому капелюсі.

Є й другий, тихіший збій, і він ловить тих, хто все ж намагається форсувати маршрут: зона. Яку б зону ви не ввели локально, вона називає інтерфейс тунелю, тоді як потрібна вам адреса прив'язана до інтерфейсу віддаленого LAN. Ці двоє ніколи не збігаються, тому пакет не можна спрямувати на правильний інтерфейс на далекому кінці.

Як збій виглядає на практиці

Вивід інструмента при помилці області читається як помилка маршрутизації або брандмауера, і саме тому люди проводять півдня не в тому шарі.

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

Третій рядок витрачає найбільше часу, бо ssh-клієнт без виводу схожий на проблему зі службою, що слухає. Якщо у вас є будь-який спосіб увійти, перевірте дальню сторону й підтвердьте, чи sshd прив'язаний до всіх адрес чи лише до однієї.

Використовуйте адресу, яка була призначена для маршрутизації

Для всього, до чого треба дістатися через тунель, використовуйте адресу, яку служба отримала саме для цієї мети: глобальну unicast адресу або unique-local адресу з fc00::/7, діапазон, зарезервований саме для цього внутрішнього випадку. Підтвердьте, що слухач справді її прив'язує, і перевірте зворотний шлях та будь-яке правило брандмауера хоста.

Подивіться на віддалений хост замість здогадок. ip -6 addr show перелічує наявні адреси, а ss -6 -ltn перелічує те, що слухає демон. Служба, прив'язана лише до fe80::, доступна тільки зі свого сегмента, що зазвичай є значенням за замовчуванням, яке ніхто не вибирав навмисно і яке можна змінити за згодою адміністратора.

Коли службу справді не можна прив'язати повторно, підніміть міст на прикладний рівень, а не на мережевий. Посередник на віддаленому хості, що слухає маршрутизовану адресу й підключається до link-local, вирішує проблему без розширення будь-якого сегмента:

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

Тут зона на правильному боці, на хості, який справді має eth0 у цьому каналі. Ваш клієнт спілкується з fd00:1:2::10, яка маршрутизується нормально, а посередник виконує link-local перехід локально. Той самий трюк працює для веб-інтерфейсу пристрою або старого BMC, який оголошує лише link-local адресу.

Коли міст справді є відповіддю, і що перевіряти

Деяким розгортанням справді потрібен один спільний сегмент: пристрій, що говорить лише виявленням link-local, прилад, залежний від multicast, лабораторія, що відтворює плаский LAN. Це проблема Layer 2, і їй потрібна відповідь Layer 2, наприклад tap-пристрій, з'єднаний мостом із віддаленим інтерфейсом, або клієнтський продукт із явним режимом мосту. Це коштує вам широкомовного та multicast трафіку, що перетинає тунель, плюс виявлення сусідів, яке має працювати від краю до краю.

Не наближайтеся до цього, додаючи fe80::/64 до маршрутизованого профілю. Це дає найгірший стан: конфігурація виглядає завершеною, таблиця маршрутизації показує запис, а кожен пакет усе одно відкидається десь між двома стеками, які обидва поводяться правильно.

Перевіряйте інтерфейсом, а не ping. ip -6 addr show tun0 повідомляє, чи сформував канал тунелю власну link-local адресу, а ip -6 route get fe80::1%tun0 повідомляє, що ядро насправді зробить із призначенням, що має область. Коли ядро каже, що призначення недосяжне на цьому інтерфейсі, жодне налаштування тунелю цього не змінить, і час припиняти редагувати профіль.

Коротка послідовність, що вирішує питання:

  • Прочитайте адресу на віддаленому хості й зауважте, чи це fe80:: або маршрутизований префікс.
  • Якщо це fe80::, прив'яжіть службу заново, зробіть посередника на цьому хості або з'єднайте сегмент мостом; якщо вона маршрутизована, виправте маршрут, брандмауер або адресу прив'язки.
  • Перевіряйте зону щоразу при повторному тесті, бо скопійована команда зазвичай зберігає неправильний інтерфейс.

Джерела: RFC 4291, архітектура адресації IPv6.

Схожі статті