Политики за маршрутизация в IPv6, когато два ъплинка споделят fe80::1
Два ъплинка могат да показват една и съща следваща точка fe80::1 по различни връзки. Изберете една таблица за всяка политика, следете времената на живот и проверявайте с търсене на маршрут.
Имате два ъплинка и 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, който поема маршрута по подразбиране. След това изключете един ъплинк нарочно и наблюдавайте към кой маршрут се връща ядрото; отговорът трябва да съвпадне с този, който сте записали.