Тест kill switch: измеряйте разрыв, а не только переподключение
Быстрое переподключение доказывает, что клиент быстрый. Запишите, что покинуло машину за время разрыва, вместе с использованным триггером, иначе тест измерил только половину.
Переподключение, завершающееся за секунду, говорит, что клиент быстрый. Оно не говорит, утекло ли что-то, пока туннель был выключен. Переподключение, занимающее минуту, говорит, что клиент медленный, и всё равно не говорит, был ли разрешён прямой трафик в разрыве. Это два измерения, и тест kill switch, сообщающий только о первом, не проверил выключатель.
Два наблюдения, два отдельных вердикта
Вопрос доступности прост: когда туннель снова стал пригодным и понадобилось ли защищённому приложению новое соединение, чтобы туда добраться. Вопрос принуждения другой: какие пакеты покинули машину между моментом, когда защита упала, и моментом, когда она вернулась.
Отвечайте на них отдельными записями. Одна строка говорит, что разрыв длился определённое число секунд. Другая строка говорит, удался ли незащищённый запрос за этот разрыв. Слияние их в одно прошло или не прошло скрывает самый важный случай: быстрое переподключение с утечкой.
Соберите зонд, время которого можно измерить
Используйте запрос, который безвреден, дёшев и не зависит от собственного канала управления туннеля. Цикл ниже раз в секунду печатает отметку времени, статус HTTP и прошедшее время, и он громко падает вместо того, чтобы зависнуть:
while true; do
printf '%s ' "$(date +%H:%M:%S)"
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' --max-time 2 https://example.com || echo "curl-exit-$?"
sleep 1
done
Читайте коды выхода curl, а не только статус. 28 означает, что запрос вышел по тайм-ауту, так выглядит заблокированный путь. 6 означает, что разрешение имён не удалось, это другая находка и часто более интересная. 200 с малым прошедшим временем в разрыве означает, что трафику разрешили выйти.
Запишите вывод в файл и сохраните его. История терминала не является доказательством, а интересная часть обычно — три строки в середине.
Вызовите настоящий сбой, а не аккуратный
Отключение из собственного меню клиента проверяет кооперативный путь, где у клиента есть время установить свои правила блокировки. Убейте процесс или оборвите нижележащий канал, и вы проверите путь, по которому идёт настоящий сбой.
Каждый триггер задействует свой путь в коде. Сбой на стороне сервера, потеря локального канала и падение клиента могут оставить разное состояние, и один из них, вероятно, и будет тем случаем, с которым вы в итоге столкнётесь. Прогоните зонд хотя бы с двумя триггерами и пометьте результаты по триггеру.
Читайте журнал, чтобы увидеть, как выглядит разрешённый трафик
200 или быстрый сбой соединения в разрыве — это утечка, в какую бы сторону она ни указывала. Истечения времени на протяжении всего разрыва — ожидаемая форма политики блокировки. Успешное разрешение имён при падающих соединениях говорит, что резолвер всё ещё доступен, а это утечка другого рода.
Существующие сокеты требуют осторожности. Программа может продолжать использовать соединение, открытое до отключения, поэтому внешне живой трафик может не доказывать, что новый путь был разрешён. Список сокетов показывает, предшествует ли соединение событию:
ss -tunp | grep -E 'ESTAB|SYN-SENT' ip route get 198.51.100.7 resolvectl status | sed -n '1,20p'
Сравните время запуска сокета с отметкой времени отключения. Соединение старше сбоя — доказательство повторного использования сокета, а не утечки, и сообщение о нём как о сбое отправляет следующего человека искать ошибку, которой нет.
Запишите результат в форме, которая переживёт обновление
Запишите триггер, разрыв в секундах, удался ли какой-либо незаблокированный запрос, удалось ли разрешение имён, а также версии клиента и операционной системы. Этот набор из пяти фактов можно сравнивать между выпусками, чего абзац прозы не может.
Повторите тот же тест после обновления клиента или смены профиля, потому что поведение блокировки — деталь реализации, и оно смещается. Смысл записи — заметить смещение до того, как оно станет инцидентом, а не удостоверить клиент однажды.