Kill-switch след преминаване от Wi-Fi към мобилна мрежа: какво се чупи
Kill-switch се пише срещу имена на интерфейси, които смяната на мрежата заменя. Проверете външния път, семействата адреси и резолвера, преди да му се доверите.
В един момент лаптопът е в офис Wi-Fi, в следващия е вързан към телефон, а индикаторът на тунела отново е зелен, преди да сте приключили със смяната на прозорците. Зелената светлина съобщава само, че тунелът се е свързал отново; какво е правила политиката за маршрутизиране и блокиране по време на прекъсването е друг въпрос. Тази политика е набор от условия за съвпадение, компилирани при последното ѝ инсталиране, и назовава интерфейс, адрес и семейство адреси, които преходът току-що е премахнал. Затова същият преход дава три изхода, които изглеждат еднакво: блокирането продължава, политиката блокира собственото си възстановяване или се отваря път, който нищо не покрива.
Нищо на екрана не разделя тези три състояния, затова питайте към кои идентификатори са били закачени правилата, а не какъв цвят показва индикаторът. В Linux правилото може да назове интерфейс или ipset, напълнен от него; в Android на VpnService може да се каже кои подлежащи мрежи да следва чрез setUnderlyingNetworks. Всяко обвързване сочи към връзка, която предстои да бъде заменена, и всяко трябва да се преоцени след това.
Какво всъщност пренаписва преходът
Когато старата връзка изчезне, ядрото премахва адресите ѝ, оттегля маршрутите, които са минавали през нея, и изгражда наново избора на адрес на източника от останалото. Маршрутът по подразбиране се мести към новия шлюз, а индексът на интерфейса, който старите правила са сочили, е изчезнал или е преизползван за друго устройство. Резолверите за всяка връзка също се обновяват, макар и не в същия миг като маршрутите. Всичко това се случва под VPN клиента, така че клиент, който следи само състоянието на своя тунел, не вижда нищо от него.
Проблемът е, че правилото кодира конкретен идентификатор вместо намерението зад него. Правило, което изхвърля всичко, което не излиза през интерфейса на тунела, кодира име на интерфейс; правило, което разрешава крайната точка, кодира адрес, който новата мрежа може да маршрутизира другаде. Когато идентификаторът изчезне, правилото не става видимо грешно — то или спира да съвпада с каквото и да е, или започва да съвпада с грешното нещо.
Възстановяване на външния тунел без пробиване на дупка
Външният транспорт беше обвързан със стария адрес на източника, затова трябва да отвори нов сокет от новия. Когато крайната точка е име на хост, а не буквален адрес, едно търсене трябва да успее, докато блокирането още е в сила. Това е капанът на реда: политика, достатъчно строга да изхвърли всичко освен крайната точка, ще изхвърли и търсенето, нужно да я намери, освен ако разрешаването не се случи преди вдигането на блокирането или не се пренесе през още жив тунел. Всеки от двата реда може да работи, но само ако клиентът знае в кой ред е.
Клиентите се различават тук по начин, който има значение при диагностика. Някои първо разрешават и после инсталират правила, така че преходът струва видимо прекъсване и после се възстановява сам; други държат блокирането и разчитат на оцелелия тунел да пренесе търсенето, което се проваля напълно, когато тунелът е умрял заедно с връзката. Добавянето на широк директен маршрут по подразбиране, за да се възстанови свързаността, винаги прави теста успешен и винаги оставя изтичането, което сте предотвратявали.
Маршрут, който още сочи към стария шлюз, дава същото заседнало възстановяване от друга причина, затова прочетете таблицата, преди да обвинявате клиента. Командите по-долу назовават интерфейса и адреса на източника, които ядрото наистина би използвало, а това решава в един ред дали старият път още е инсталиран.
ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111Когато новата връзка носи IPv6, а правилата — не
Мобилните и гостуващите мрежи често раздават глобален префикс IPv6, дори когато кабелната LAN в офиса никога не го е правила. Политика, написана само като правила IPv4 — обичайната форма на повечето ръчно правени рецепти за iptables и nftables — не покрива нищо от това. Тунелът остава свързан, приложенията с достъп до IPv6 излизат извън него, а индикаторът не може да покаже разликата, защото тунелът наистина работи. Огледалният случай е също толкова чест: набор правила само за IPv6 не прави нищо в мрежа, която не предлага v6.
Сравнете какво предлага връзката с какво споменава политиката, от двете страни на прехода. Тези команди отпечатват същите факти, с които работи клиентът:
ip -4 route show default
ip -6 route show default
sudo nft list ruleset | grep -c 'ip6 'Ако втората команда отпечата маршрут по подразбиране, а третата върне нула, новата връзка може да изведе машината през IPv6 без нито едно правило да я следи. Пуснете и трите отново след превключването, защото интересното число е разликата между двата пуска. Ако втората не отпечата нищо, важи обратният случай и всяка политика, тежка на v6, там е само украшение.
Резолверът сменя ръце по средата на сесията
В съвременните системи резолверите са прикачени към връзките, така че новата връзка идва с нов набор резолвери и вероятно с различен изглед на split-DNS. systemd-resolved държи по един scope на връзка и избира между тях по маршрут, докато macOS чете scoped резолвери от динамичното хранилище и зачита реда на интерфейсите. Клиент, който инсталира собствен резолвер, се състезава с този на връзката, и правилата за приоритет, които никой не следи, решават победителя. Тогава разрешаването на имена може да се счупи, докато филтрирането на пакети прави точно това, за което е писано.
Четете активния резолвер, а не конфигурирания. На systemd хост подкомандата status показва от коя връзка идва всеки scope и дали е в сила име private-DNS:
resolvectl status --no-pager
resolvectl query intranet.example.comАко заявката излиза през физическата връзка, а не през тунела, клиентът е загубил надпреварата за приоритет и никаква настройка на защитната стена няма да оправи имената. Сравнете пътя на заявката от двете страни на прехода, за да видите кой се е преместил. Име, което се разрешава до частен адрес, който новата мрежа не може да маршрутизира, е трети случай и се проявява като изчакване, а не като грешка.
Упражнете прехода и пазете записа
Възпроизведете промяната нарочно, вместо да я чакате. Вдигнете тунела на първата връзка, започнете дълъг трансфер и повтарящо се търсене, после сменете връзката и вижте кое оцелява. Запишете интервала между изчезването на старата връзка и съобщението на тунела, че е свързан, защото в този прозорец политиката или е удържала, или не. Пуснете последователността и в обратната посока, за да не е резултатът едностранен.
Изключенията се нуждаят от свой отделен преглед, защото обход, оправдан в старата мрежа, не е автоматично оправдан в новата. Принтер, NAS или captive portal в домашната LAN няма аналог в мобилната мрежа, а изключението, което е стигало до него, става правило без аналог.
Запишете имената на интерфейсите, предлаганите семейства, действащия резолвер и дължината на прекъсването за всяка посока. Повторното свързване доказва, че транспортът се е възстановил, а не че блокирането е удържало по време на прекъсването, и това са отделни твърдения за тикет. С този запис следващият преход се сравнява с известно състояние, а не с паметта.