У вас два аплінки, і ip -6 route show виводить той самий наступний перехід на обох: default via fe80::1 dev uplink0 і default via fe80::1 dev uplink1. Це не конфлікт дубльованої адреси, і копіювання голого наступного переходу fe80::1 до таблиці політики не повідомляє ядру, який канал ви маєте на увазі. Справжнє питання вужче, ніж підказує симптом: чи потрібен другій таблиці один канал чи обидва, і що зберігає ці маршрути живими після перезавантаження. Три умови, перевірені по черзі, вирішують більшість.

Той самий fe80::1 — це два різні сусіди

Адреси, локальні для каналу, обмежені одним каналом, тому fe80::1 — не одна адреса, надрукована двічі; це два сусіди, які випадково поділяють суфікс. Індекс зони — це спосіб хоста сказати, який саме він має на увазі, тому fe80::1%uplink0 і fe80::1%uplink1 для ядра різні призначення, і цей суфікс ніколи не потрапляє на віддалений маршрутизатор. RFC 4007 описує модель зон, що стоїть за цим, і саме тому таблиця політики мусить нести пристрій при кожному локальному наступному переході.

Генератор конфігурації VPN, який копіює числовий ідентифікатор зони з одного хоста до шаблону, поводиться з локальним контекстом так, ніби він частина адреси, і записаний ним файл неправильний на кожній машині з іншими назвами або індексами інтерфейсів. Таблиця політики й не зливає два канали в один: маршрутизований VPN передає пакети між мережами, але не переносить локальну ідентичність віддаленого сусіда Ethernet через тунель, тому локальний трафік залишається на своєму каналі.

Приберіть пристрій, і маршрут стане незаписуваним. ip -6 route add default via fe80::1 table 200 не може розв'язати шлюз, і iproute2 відхиляє це з Error: Nexthop has invalid gateway. помилкою. Додайте dev uplink0 і команда вдасться, бо саме пристрій прив'язує наступний перехід до одного з тих двох сусідів. Чого пристрій сказати не може — чи правильний uplink0 канал для цієї таблиці, а маршрут, скопійований з іншого хоста, приносить із собою назви інтерфейсів того хоста, і справжні помилки беруться саме звідси.

Умова перша: один канал чи два в таблиці

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

У другому випадку правило вирішує, коли звертатися до таблиці, а маршрут вирішує, куди пакет піде після цього:

ip -6 rule add fwmark 0x2 table 201
ip -6 route add default via fe80::1 dev uplink1 metric 100 table 201
ip -6 route add 2001:db8:100::/48 dev uplink1 metric 100 table 201
ip -6 route show table 201

Жоден об'єкт не замінює інший, і таблиця лише з маршрутом за замовчуванням усе одно може не розв'язати свій шлюз. Якщо додавання відхилено або маршрут є, але непридатний, помістіть під'єднаний префікс цього інтерфейсу до тієї самої таблиці або позначте перехід як onlink , коли цей префікс маршрутизується в іншому місці. У блоці вище 2001:db8:100::/48 позначає саме той під'єднаний префікс на uplink1, а не довільне призначення. Правило fwmark лише споживає позначку, яку має встановити щось інше, — правило nftables або iptables на шляху пересилання або SO_MARK у сокеті, тому скопійований блок без джерела позначки нічого не зіставляє.

Умова друга: метрики не виявляють мертвого провайдера

Метрика — це перевага серед наявних маршрутів, а не перевірка стану. Коли оператор падає, ядро видаляє маршрути на цьому пристрої, і другий маршрут за замовчуванням перебирає керування. Коли кабель лишається ввімкненим, а провайдер за ним помирає, у таблиці нічого не змінюється: бажаний маршрут встановлено, сусід доступний на рівні 2, і пакети виходять у чорну діру. Якщо ця різниця важлива для вашої схеми, відмовостійкість має надходити від чогось, що зондує шлях і видаляє маршрут, — чи то демон маршрутизації, чи маленький скрипт, що видаляє й наново встановлює запис.

Перевірте вибір після побудови таблиці й перевірте так, як його побачить ядро. ip -6 route get 2001:db8:100::1 виводить маршрут, який було б використано, включно з пристроєм і вибраною адресою джерела, і він дотримується правил політики. Адреса джерела, що належить неправильному аплінку, зазвичай означає, що правило збіглося раніше, ніж ви очікували.

Умова третя: вирішіть, кому належить збереженість

Маршрут, доданий через ip -6 route add , живе до перезавантаження або до того, як щось його скине. Маршрут за замовчуванням, вивчений з оголошень маршрутизатора, несе час життя і може бути відкликаний маршрутизатором, тоді як доданий вручну за замовчуванням ніколи не спливає сам. Змішування обох в одній таблиці — це шлях, яким застарілий постійний маршрут починає переважати свіжий оголошений, задовго після того, як описаний ним аплінк перестав існувати.

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

ip -6 route flush table 201
ip -6 rule del fwmark 0x2 table 201

На маршрутизаторі, який пересилає трафік інших хостів, перш ніж звинувачувати таблицю, перевірте net.ipv6.conf.all.forwarding . Якщо пересилання вимкнено, пакети, адресовані іншій мережі, відкидаються, хоч би якою правильною була таблиця 201.

Запишіть проєкт, щоб наступна людина могла його перевірити

Інвентар, який зберігає лише fe80::1 , викидає поля, що мають значення. Записуйте призначення, наступний перехід, пристрій, таблицю й метрику разом, а також звідки взявся кожен маршрут: оголошений, згенерований менеджером чи статичний. Коли хтось згодом запитає, чи справді другий аплінк несе трафік, цей запис відповість без здогадів.

Перш ніж оголосити таблицю готовою, підтвердьте сусіда через ip -6 neigh show dev uplink0 , перечитайте ip -6 rule show щодо випадковостей порядку й перевірте трафіком, що відповідає правилу, а не ping, який бере маршрут за замовчуванням. Потім навмисно вимкніть один аплінк і подивіться, на який маршрут ядро відступить; відповідь має збігатися із записаною.

Схожі статті