Kill switch отказывают в направлении, которого люди не ждут: они созданы блокировать трафик, пока туннель опущен, а пакеты, которые строят туннель, сами являются трафиком. В этом вся ошибка. Набор правил, отбрасывающий всё, что не выходит через туннель, отбрасывает и рукопожатие, которое должно его поднять, поэтому клиент повторяет в цикле, а ошибка приписывается тому этапу, который проверяется первым. Прежде чем расширять межсетевой экран, выясните, какой из трёх этапов отклоняется: поиск имени, внешний пакет к партнёру или возвращающийся ответ.

Как туннель и его собственный транспорт зависят друг от друга

Читайте VPN-клиент как два состояния сети, которые делят один путь сокета. Пока туннеля нет, клиент открывает сокет на физическом адаптере и отправляет зашифрованные кадры на адрес и порт партнёра. Только после успеха этого обмена он создаёт туннельное устройство и устанавливает маршруты. Kill switch — это политика о втором состоянии, написанная так широко, что действует на оба.

Правила на основе интерфейса — обычная форма: принимайте то, что уходит через tun0 или wg0, отбрасывайте остальной исходящий путь. Такая формулировка не может исключить собственное соединение клиента с сервером, поэтому корректная реализация добавляет это исключение явно, и вы тоже, когда пишете правила вручную. Правила по приложениям в Windows и macOS обходят часть этого, сопоставляя процесс, а не интерфейс, но процесс всё равно должен выйти до того, как туннель появится.

Три этапа в том порядке, в котором они происходят

Первый этап — разрешение имени. Когда профиль хранит имя хоста вместо буквального адреса, клиенту нужен ответ DNS, прежде чем что-либо отправить. Профиль, направляющий DNS к резолверу туннеля, создаёт тупик: резолвер доступен только через туннель, который поиск должен включить. Разрешение вне туннеля или привязка конечной точки к адресу снимают эту двусмысленность.

Второй этап — внешний пакет, который должен пережить сначала маршрутизацию, а затем межсетевой экран, именно в таком порядке. wireguard-tools выполняет маршрутную половину этого для WireGuard: помечает собственные пакеты и добавляет правило политики, чтобы они обходили только что установленный маршрут по умолчанию; страница руководства wg-quick описывает это правило и таблицу, которую оно использует. Восстановите эту маршрутизацию вручную или позвольте второму инструменту переписать правила, и помеченные пакеты могут быть отправлены обратно в туннель, который они должны создать.

Третий этап — обратный путь. Рукопожатие без ответа не доказывает отбрасывание на выходе; оно так же согласуется с входящим правилом сервера или устройством NAT, забывшим сопоставление. Разделите это, прежде чем трогать клиента.

What you seeStageWhere to look
The client log repeats a resolve step and no packets appear on the wire1, name lookupResolver path while the tunnel is down
The send counter on the physical adapter stays flat2, routingPeer route and policy rules
The send counter rises and a firewall drop counter rises2, firewallRule order, mark, and interface match
Packets leave and nothing comes back3, return pathServer input rules, NAT, listening port

Клиенты записывают обнаруженный симптом, а не этап, который отказал, поэтому таблица обычно быстрее журнала.

Счётчики решают быстрее журналов

В Linux, nft list ruleset или iptables -vnL OUTPUT печатает счётчик пакетов для каждого правила. Подключитесь один раз, дайте отказать, затем снова прочитайте счётчики. Правило, счётчик которого сдвинулся, — это правило, в которое попало рукопожатие; если нигде ничего не сдвинулось, пакет так и не дошёл до межсетевого экрана. Я видел, как набор правил отбросил собственное рукопожатие, и об этом сказали только счётчики.

Чтобы отличить «никогда не дошёл до межсетевого экрана» от «никогда не покинул хост», наблюдайте за самим интерфейсом. ip -s link show dev wlan0 сообщает об отправленных пакетах, а tcpdump -ni wlan0 udp port 51820 показывает кадры. Если он остаётся плоским, пока клиент повторяет попытки, неисправность выше netfilter: отсутствует маршрут к партнёру, правило политики указывает на устройство, которого ещё нет, или ошибка сокета, которую клиент проглатывает.

Проверяйте исключения на документационных адресах, таких как 203.0.113.10, чтобы оплошность не могла прощупать чужой хост.

Устаревшее исключение конечной точки читается как отказ сервера

Самая обманчивая версия появляется после того, как адрес партнёра изменился: служба динамических адресов перенесла его, хост перестроили, или исходящий адрес вашей сети другой. Исключение по-прежнему называет старый адрес, поэтому пакеты к новому попадают под правило отбрасывания. Та же конфигурация работала вчера, и именно поэтому люди начинают с диагностики сервера.

Имя хоста внутри правила межсетевого экрана вас не спасёт. В nftables имя разрешается при загрузке набора правил, поэтому оно закрепляет тот адрес, который существовал в этот момент, и устаревает, как буквальный. Устойчивое решение — обновлять исключение, когда конечная точка меняется, и держать его узким: один адрес партнёра, один транспортный порт. Диапазон, достаточно широкий, чтобы пережить смену адреса, достаточно широк и для того, чтобы выпустить посторонний трафик.

Когда kill switch работает на хосте сервера

Та же зависимость есть на другом конце, и там её легче упустить. Если машина, служащая вашим VPN-сервером, также запускает настольный клиент с kill switch или профиль межсетевого экрана, скопированный с ноутбука, его правила отбрасывания действуют на службу, завершающую туннели. Ответы на рукопожатие клиента отбрасываются, поэтому каждый клиент не может подключиться, пока сервер выглядит здоровым, а его туннельный интерфейс простаивает.

Этому хосту нужны три узких разрешения перед отбрасыванием: порт прослушивания на физическом интерфейсе, туннельный интерфейс для расшифрованного трафика и пересылка из туннеля к тому, что клиенты должны достигать. Прочитайте установленный набор с помощью nft list ruleset, iptables -S, или pfctl -sr , прежде чем что-либо менять, и помните, что сохранённый набор правил переживает перезагрузку, поэтому ошибка там переживает процесс, который её создал.

Порядок восстановления, который держит машину закрытой

Работайте от профиля наружу. Прочитайте адрес и порт партнёра, которые использует клиент, подтвердите, что имя хоста разрешается без туннеля, и затем добавьте одно исключение для этого адреса и порта только на физическом адаптере. Подключитесь снова и наблюдайте за счётчиком отправки; завершённое рукопожатие — сигнал, что второй этап исправлен.

Оставьте остальную политику отбрасывания на месте во время проверки. Безвредная проверка — попытаться подключиться к постороннему документационному адресу и убедиться, что он по-прежнему заканчивается тайм-аутом, что показывает: kill switch работает, а не отключён. Ужесточите исключение, когда туннель станет стабильным, и не оставляйте постоянного разрешения всего для клиентской программы только потому, что это удобно.

Если туннель поднимается, а приложение всё равно отказывает, остальные этапы — не этот: разделённый DNS, MTU и маршрутизация по приложениям каждый дают подключённый туннель со сломанным трафиком, и у каждого своя первая проверка.

Похожие статьи