Защо втори VPN тунел чупи първия?
Втори VPN клиент инсталира два полу-маршрута по подразбиране и първият тунел угасва: вижте кой маршрут печели, след което разделете по профил, таблица или namespace.
Инсталирането на втори VPN клиент за достъп до една клиентска мрежа е обичайният начин това да започне, и първият тунел угасва, докато и двата клиента съобщават за успех. Всеки клиент инсталира маршрут по подразбиране, вторият беше по-конкретен, и ядрото вече го следва за всичко освен собствената външна връзка на първия тунел. Нищо не се срина и никой профил не е грешен. Един маршрут замени друг, а решението е да решите кой тунел да притежава маршрута по подразбиране.
Симптомът: вторият клиент печели тихо
OpenVPN: опцията redirect-gateway def1 не презаписва 0.0.0.0/0. Тя добавя 0.0.0.0/1 и 128.0.0.0/1: заедно те покриват всеки IPv4 адрес и всеки префикс бие обикновения маршрут по подразбиране по дължина. Оригиналният маршрут по подразбиране остава в таблицата и престава да се използва за обикновен трафик, а маршрут до хоста на VPN сървъра пази тунела да не улавя собствените си външни пакети. И двата клиента правят това, а вторият просто инсталира своята двойка по-късно.
Затова първият тунел изглежда мъртъв, а не прекъснат. Интерфейсът му е вдигнат, контролният канал е жив и до него вече не стига трафик на приложения. Обратната жалба има същата причина — липсващ push: телефон, който се свързва, но не изпраща нищо, обикновено говори със сървър, който никога не е обявявал redirect-gateway, затова устройството пази своя маршрут по подразбиране и достига само пула.
Направете снимка на маршрутите преди и след свързването на втория клиент. Двата полу-маршрута, появили се в таблицата, са цялата промяна и обясняват и двете жалби. Нищо друго в таблицата не трябва да се мести, за да се появи симптомът. Затова премахването на втория клиент веднага връща първия.
Прочетете кой тунел всъщност печели
Не извеждайте победителя от реда, в който клиентите са стартирали, нито от иконата в системния трей. Попитайте ядрото кой маршрут би използвало за дестинация извън двете частни мрежи и прочетете върнатия интерфейс.
ip route show
ip route get 198.51.100.24
route print -4
Find-NetRoute -RemoteIPAddress 198.51.100.24
Първите две са отговорът за Linux, а последните две — еквивалентът за Windows. Изпълнете ги, докато двата тунела са вдигнати, после прекъснете единия и ги изпълнете отново. Разликата между двата изхода е фактът, който ви трябва, преди да изберете решение, и отнема по-малко време от четене на журнала на който и да е клиент.
Запишете резултата, включително името на интерфейса и съвпадналия префикс. Тикет, който казва, че вторият VPN е счупил първия, е описание на симптома, а не маршрутно твърдение, по което някой може да действа. Проверката го превръща във факт, който следващият инженер може да възпроизведе с една команда.
Windows: не позволявайте на един профил да притежава маршрута по подразбиране
Windows пази запазени профили и вграденият клиент позволява един да зависи от друг, така че първият да се вдига автоматично, когато вторият набере. Профилът, свързан последно, обикновено пази маршрута по подразбиране, затова практичният собственик е последното набиране, а не първото. Дайте на всеки профил собствени push маршрути и включете разделено тунелиране за този, който не бива да притежава маршрута по подразбиране.
Set-VpnConnection -Name "Contoso" -SplitTunneling $true
rasdial Contoso
Разделеното тунелиране променя това: в таблицата попадат само префиксите, изпратени от сървъра, което оставя маршрута по подразбиране при първия тунел. Дизайнът пак се проваля, ако и двата сървъра изпращат маршрут по подразбиране, защото тогава последната връзка печели и никоя настройка от страна на клиента не променя това. Поправете push-а от страна на сървъра или приемете един собственик.
Профилите, задействани от приложение, са друга функция и си струва да се знаят: профил на Windows може да стартира при пускането на посочен изпълним файл, а филтрите на трафика решават какво носи. Това е настройка на профил, не правило на защитна стена, и решава различен проблем от конфликта на маршрута по подразбиране.
Linux: дръжте втория тунел извън основната таблица
Пускането на два екземпляра openvpn --config на една машина слага двата клиента в една таблица и три опции ги разделят с нарастваща изолация. Най-леката е да спрете втория клиент да редактира таблицата изобщо, чрез route-nopull с явни маршрути, или скрипт route-up, който инсталира само това, което искате. Тогава вторият тунел носи точно посочените префикси и нищо друго. Тогава решавате кой префикс къде отива, вместо да го откривате после.
Политическото маршрутизиране е средната опция. Правило избира отделна таблица за един адрес на източник или маркировка на защитна стена и тази таблица носи маршрутите на втория тунел. Филтрирането на обратния път е капанът тук, защото отговор, пристигнал на различен интерфейс от този, който таблицата би избрала, се изхвърля, затова проверете настройката rp_filter, преди да заключите, че тунелът е счупен.
ip rule add from 10.44.7.0/24 table 100
ip route add default dev tun1 table 100
sysctl net.ipv4.conf.all.rp_filter
Мрежовите namespace-и са най-тежката и най-чистата опция. Стартирайте втория клиент вътре в ip netns, дайте му двойка veth и влезте в този namespace, за да го използвате. Смущенията изчезват, защото всеки namespace притежава свои таблици, вместо да споделя една; това си струва допълнителната настройка, когато двата тунела трябва да стоят седмици.
За всяко приложение и верижното свързване като отделен проблем
Понякога само една програма трябва да използва втория тунел. В Linux политическото маршрутизиране по потребител, cgroup или порт постига това, а една дестинация може да се закачи за интерфейс, без да се пипа маршрутът по подразбиране. Приложение, което закача сокета си за един интерфейс, изобщо не се обръща към таблицата за маршрутизиране, затова стартер може да продължи да ползва физическия адаптер, докато адрес не бъде избран в собствените му настройки.
Верижното свързване е друга операция от пускането на два тунела един до друг. Свързването на A през B означава, че адресът на вътрешния сървър трябва да е достъпен отвътре във външния тунел. Външният клиент също не бива да взема криптираните пакети на вътрешния клиент за изтичане. Един клиент във виртуална машина е грубата, но надеждна версия; двата на един хост изискват маршрутната работа по-горе плюс външен път към вътрешния сървър, който никога не влиза във вътрешния тунел.
Запишете собственика на маршрута по подразбиране, списъка с префикси на всеки тунел и пътя на DNS. Тези три факта превръщат следващия инцидент в проверка, а не в разследване.