Трябва ли IPv6 трафикът да минава през VPN или директно?
Решете дали ::/0 принадлежи вътре в тунела, по три условия: поддръжка на изхода, достъпност на крайната точка и само локални мрежи.
Миналия месец двама души поискаха от мен противоположни резултати: единият искаше IPv6 да бъде покрит от VPN, другият искаше офисният принтер да продължи да работи. Един маршрут ::/0 не може да осигури и двете сам по себе си. Дали този маршрут принадлежи вътре в тунела, зависи от три условия и първото го изключва за повечето комерсиални изходи. Ако изходът не носи IPv6, насочването на маршрута по подразбиране към него скрива трафика ви в тунел, който няма къде да го изпрати.
Три условия решават отговора
Маршрутът по подразбиране е един ред, ::/0, и съвпада с всяка дестинация IPv6 без по-конкретен маршрут (RFC 4291). Инсталирането му е лесно. Решаването дали трябва се свежда до три условия.
Условие първо: изходът, към който се свързвате, има работещ IPv6 и е готов да го препраща. Условие второ: клиентът ви може да запази път до крайната точка на тунела, която обикновено се намира в диапазона, който ще насочвате. Условие трето: можете да назовете локалните дестинации IPv6, които трябва да останат извън тунела.
Всяко условие се проваля по свой начин и затова гаденето струва цяла вечер. Провалено първо условие ви дава тишина и таблица за маршрутизация, която изглежда правилна. Провалено второ условие убива ръкостискането няколко секунди след началото му. Провалено трето условие оставя работещ тунел и недоволен колега до принтера.
| What you see | Decision |
|---|---|
| Exit answers IPv6 probes, no local IPv6 devices to protect | Route ::/0 into the tunnel |
| Exit answers IPv6 probes, printer or NAS reachable by a global address | Route ::/0, then give those prefixes a route of their own |
| Exit is IPv4-only inside the tunnel | Do not route ::/0; block IPv6 on the client |
Endpoint is reached over IPv6 and sits inside ::/0 | Install a host route for the endpoint first |
Наистина ли изходът носи IPv6?
Интерфейс на тунел с адрес IPv6 не доказва нищо за отсрещната страна. Много комерсиални профили са само IPv4 отвътре: сървърът ви дава адрес v4 и изхвърля всичко останало. Инсталирайте маршрут по подразбиране от AllowedIPs върху това и ядрото с удоволствие ще изпраща IPv6 към интерфейс, чийто партньор никога не го вижда.
Тествайте от клиента, докато тунелът е активен. ping -6 -c 3 2001:4860:4860::8888 и ip -6 route get 2001:4860:4860::8888 отговарят на различни въпроси: дали се връща отговор и кое устройство е избрало ядрото. Когато второто назове вашия тунел, а първото не върне нищо, проблемът е в изхода, не в маршрута.
Ако управлявате изхода сами, клиентският тест може да мине, а пътят пак да стигне до задънена улица. Потвърдете net.ipv6.conf.all.forwarding=1 на шлюза и че неговият файлуол приема пакети, препратени от тунела. Правилно маршрутизиран пакет към изход, който отказва да препраща, изглежда точно като проблем с маршрутизацията от страна на клиента.
Може ли клиентът да запази пътя си до крайната точка?
Това е случаят, който ме хвана на лаптоп с крайна точка WireGuard само на IPv6. Адресът на крайната точка е обикновен глобален адрес, така че попада вътре в ::/0. Насочете целия префикс към интерфейса и пакетите за ръкостискане ще се гонят сами в тунела, който още се опитват да изградят. Тунелът така и не се вдига и нищо в изхода на клиента не казва защо.
wg-quick се справя с това в Linux. Той извлича маршрути от AllowedIPs, инсталира ги в собствена таблица и добавя политично правило, така че трафикът към крайната точка първо се решава през основната таблица: правилото suppress_prefixlength 0, което намирате в ip -6 rule. Затова wg-quick up успява там, където написаният на ръка ip -6 route add default dev wg0 ви отрязва.
Проверете и двете състояния с ip -6 route get <endpoint-v6>, преди и след вдигане на тунела. Ако отговорът се промени към устройството на тунела, вие сте премахнали пътя, който тунелът изисква. Когато пишете маршрутите сами, добавете маршрут за хоста към крайната точка през първоначалния шлюз или се свържете с крайната точка през IPv4 и оставете IPv6 на полезния товар.
Какво трябва да остане извън тунела?
По-конкретните маршрути побеждават този по подразбиране, така че префикс на връзката или диапазон ULA със собствен маршрут продължава да работи без допълнителни усилия. Това е тихата причина толкова много настройки с пълен тунел IPv4 да оцеляват: префиксите на LAN са по-конкретни от този по подразбиране и никога не влизат в тунела.
Това се чупи, когато локално устройство е достъпно през глобален адрес, което е нормално за принтер, получил публичен префикс от същия рутер, NAS или телевизор. Тези адреси съвпадат с ::/0 и с нищо друго, затова се преместват в тунела с всичко останало и изчезват.
Решавайте по дестинация, не по протокол. Ако два или три локални хоста имат значение, дайте на префиксите им маршрут през физическия интерфейс или ги премахнете от договорения набор. Ако списъкът продължава да расте, честният отговор е разделен тунел за IPv6 с писмен списък на изключенията, а не маршрут по подразбиране, който постоянно кърпите.
Ако отговорът е не, блокирайте го
Оставянето на IPv6 без маршрут не е същото като оставянето му на мира. Хост с работещ маршрут по подразбиране за IPv6 продължава да го използва, докато тунелът носи IPv4, така че трафикът излиза покрай VPN и всяка услуга, която предпочита IPv6, вижда реалния ви адрес. Това е изтичане, не разделен тунел.
Изберете едно и запишете кое избрахте. Насочете маршрута по подразбиране и приемете компромисите по-горе или изключете IPv6 за времетраенето на тунела. Пропускането на префикса от AllowedIPs не е достатъчно само по себе си, защото операционната система пази свой собствен маршрут по подразбиране. В Linux грубият вариант е sysctl -w net.ipv6.conf.all.disable_ipv6=1; по-финият изхвърля IPv6 извън тунела с правило на файлуола. Телефонните клиенти имат явен превключвател за блокиране на IPv6, който върши същата работа.
Проверете го като изтичане
Вдигнете тунела и прочетете състоянието, вместо да се доверявате на превключвателя. ip -6 route show default трябва да покаже един маршрут по подразбиране, а ip -6 route get за дестинация извън вашата LAN трябва да назове устройството на тунела. Повторете двете след прекъсване: маршрут по подразбиране, който преживява тунела, е грешката, която търсехте.
След това тествайте другата посока. От хост в локалната мрежа достигнете клиента на локалния му адрес IPv6. Ако това спре да работи, условие трето никога не е било изпълнено, каквото и да твърдеше тогава таблицата за маршрутизация.
Запишете резултата там, където следващият човек ще го намери: кои префикси остават локални, защо и какво прави клиентът след прекъсване. Два реда в runbook спестяват на следващия инженер преоткриването на цикъла на крайната точка по полунощ.