Два VPN-приложения сразу: какой kill switch действительно действует?
Второй VPN-клиент никогда не наследует kill switch первого. Какая политика действует, решают три условия — и как проверить свою.
Два VPN-клиента могут работать бок о бок, но их kill switch не сливаются в одну политику. Каждый клиент устанавливает правила для своего туннеля, и ни один не знает о существовании другого. Я столкнулся с этим, когда первым был подключён рабочий клиент: второе приложение не могло завершить рукопожатие, десять минут висело на «Connecting», а первый туннель тихо уносил всё. Защищено ли второе приложение, зависит от трёх условий, а не от того, показывают ли обе иконки «Подключено».
На что на самом деле распространяется kill switch
В операционной системе нет единого флага kill switch. Клиент, который его рекламирует, устанавливает набор правил: отбрасывать всё, что не уходит через мой туннель, и часто fail closed, когда туннель пропадает. В Linux это обычно цепочка nftables или iptables, в Windows набор фильтров Windows Filtering Platform, в Android и iOS собственный маршрут туннельной службы плюс системная настройка, блокирующая соединения без VPN. Руководство по VPN для Android описывает эту модель службы, если нужен взгляд со стороны платформы.
Область действия — вот что важно. Правило вроде «разрешать только пакеты на выходном интерфейсе wg0» не интересуется, существует ли второй туннель. Если другой клиент поднимет wg1, правила первого клиента сочтут эти пакеты обычным трафиком: обычно отбросят, иногда пропустят. Так или иначе решает первый клиент, и он понятия не имеет, что второе приложение ждёт.
Три условия, которые решают, кто окажется под защитой
Перебирать все комбинации не нужно. Три вопроса решают дело за несколько минут.
- Допускает ли платформа второй туннель вообще? Большинство телефонов на Android и iPhone принимают только одну активную службу VPN на профиль пользователя, так что второе приложение никогда не получает туннель и ничего не контролирует. Вы получаете одну политику — от приложения, которое заняло место.
- Какой процесс владеет маршрутом по умолчанию? Windows, macOS и Linux спокойно несут два туннеля. Маршрут по умолчанию принадлежит тому клиенту, который настроил его последним или с лучшей метрикой, а второй клиент подключён, но простаивает. В Linux режим маршрута по умолчанию у wg-quick использует маршрутизацию по политике с частной таблицей и правилом fwmark, поэтому второй туннель wg-quick добавляет конкурирующее правило, а не заменяет первое.
- Может ли второй клиент достучаться до своего сервера? Если первый kill switch работает по принципу «запрещено по умолчанию», внешняя конечная точка второго приложения — просто ещё один отброшенный адрес. Оно молча повторяет попытки и никогда не сообщает об ошибке.
Короткая версия для тредов поддержки:
| Setup | What you actually get |
|---|---|
| Second client cannot hold a tunnel | One active policy; the other app only reports that it is waiting |
| Both tunnels up, second took the default route | The first kill switch blocks traffic it never meant to touch; the connection dies, or leaks if its rules are broad |
| First kill switch allows only its own endpoint and interface | Second client never connects; first tunnel unaffected |
| Both up, DNS written by whichever client ran last | Name resolution breaks for one side when either tunnel drops |
Две из этих строк выглядят одинаково с иконки в трее, поэтому иконка здесь — худшее из доступных доказательств.
Что ломается первым и как это выглядит
Клиент, застрявший на «Connecting», когда второй здоров, — почти всегда голод по конечной точке: работающий kill switch отбрасывает рукопожатие второго клиента к его собственному серверу. Проверьте это дёшево, приостановив блокирующие правила первого клиента на одну попытку. Если второй подключается сразу, вопрос закрыт.
DNS — второй отказ. Клиенты настраивают конфигурацию преобразователя для своего интерфейса, а некоторые попросту перезаписывают глобальный список. Когда подняты оба туннеля, запросы могут уходить через одну сторону, пока преобразователь принадлежит другой. Отключите любое приложение — и выживший останется с недоступным сервером имён: страницы зависают на минуту и затем снова разрешаются, а VPN всё ещё показывает подключение.
Третий — мигание маршрутов. Переподключения переупорядочивают маршрут по умолчанию, а kill switch, привязанный к интерфейсу, за ним не следует. Трафик, который мгновение назад был в туннеле, теперь попадает под правило отбрасывания, и для пользователя это выглядит как VPN, который случайно перестаёт работать.
Проверьте, какая политика действует на самом деле
Делайте это с безобидным трафиком, а не с тем, чего вам будет жалко.
В Linux спросите ядро, кто побеждает и к чему привязан межсетевой экран. ip -4 route show default называет туннель, владеющий выходом. ip rule show показывает, участвует ли маршрутизация по политике. sudo nft list ruleset | grep -n oifname показывает, привязаны ли сбросы к имени интерфейса, метке или всей выходной цепочке.
В Windows та же история живёт в метрике маршрута и списке фильтров: Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Sort-Object RouteMetric и Get-NetFirewallRule -Enabled True | Where-Object DisplayName -match "VPN". В macOS — netstat -rn -f inet | head -5 и scutil --dns | head -20.
Затем сделайте шаг, который люди пропускают: намеренно остановите туннель и убедитесь, что трафик, который должен сломаться, действительно ломается. Подключённая иконка — это состояние интерфейса, а не обеспечение правил.
Когда два клиента — неправильный дизайн
Если единственное требование ко второму приложению — больше защиты, уберите его. Две взаимодействующие политики блокировки менее предсказуемы, чем одна, и каждое переподключение — шанс оказаться в состоянии, которое не тестирует ни один поставщик.
Если вам действительно нужна цепочка, например корпоративный шлюз через коммерческий хоп, выбирайте схему с единственной точкой контроля. Обычно это маршрутизатор или один клиент, поддерживающий цепочку, а не два настольных приложения, соревнующихся за один и тот же маршрут по умолчанию. На управляемом устройстве держитесь санкционированного клиента, а всё остальное считайте вне области действия, что бы оно ни показывало в трее.
Контрольный список перед тем, как оставить оба
Пройдите список по порядку; первый не пройденный пункт и нужно исправлять.
- Убедитесь, что ровно один клиент владеет маршрутом по умолчанию и преобразователем.
- Если хотите, чтобы второй клиент работал, разрешите явно конечную точку его сервера и перепроверяйте после каждого обновления клиента.
- Запишите ожидаемый исход при падении любого туннеля и проверьте именно этот случай.
- Проверьте путь отказа после перезагрузки, когда порядок запуска другой.
- На управляемом профиле остановитесь и спросите владельца, прежде чем что-то добавлять.
Если третий шаг не проходит, честный ответ таков: политику даёт только один клиент. Решите, какому доверяете, и отпустите второй.