VPN на Mac и PAC-прокси: два решения, а не одна настройка
Файл PAC выбирает прокси для каждого запроса, а VPN выбирает маршрут. Отследите загрузку, выбор и сокет и перестаньте читать DIRECT как офлайн.
Ваш Mac загружает скрипт политики, а затем спрашивает этот скрипт, через какого посредника должен идти запрос, тогда как туннель решает только, как достичь выбранного узла. Оба ответа оказываются на одном сокете, поэтому запрос, который терпит неудачу после того, как оба преуспели, выглядит как одна неисправность, хотя их две. Разделение загрузки и выбора, а выбора и маршрута, — это большая часть работы в этих тикетах. Порядок ниже повторяет то, что macOS действительно делает, с проверками, которые делают каждый этап видимым.
Где адрес PAC и прокси расходятся
Адрес вроде https://config.corp.example/proxy.pac называет документ для загрузки, а этот документ называет сервер, через который идёт трафик. Вставка URL в поле хоста прокси просит клиента открыть прокси-соединение с файловым сервером, который никогда не ждёт такого соединения. Внутри файла есть функция, которую клиент вызывает при каждом запросе, и её возвращаемое значение — следующий узел для этого единственного адресата. Эта косвенность объясняет, почему две машины в одной сетевой службе могут вести себя по-разному, хотя обе хранят правильный URL. Она же объясняет, почему изменение политики вступает в силу, хотя никто не трогает сам прокси.
Прочитайте скрипт, прежде чем что-либо интерпретировать дальше, потому что правила внутри него несут исключения организации и порядок их применения. Ранний широкий диапазон может заслонить более поздний внутренний суффикс, и хост, который явно должен обходить прокси, продолжает им пользоваться. Когда кто-то настаивает, что политика неверна, скрипт — единственное место, где это утверждение разрешается.
Скрипт нужно загрузить, прежде чем он что-либо решит
Чтобы загрузить политику, нужны разрешённое имя и маршрут к тому, что отдаёт файл, а подключённый туннель не гарантирует ни того, ни другого. Если хост разрешается только через частный DNS, используемый в этот момент резолвер решает, может ли начаться загрузка. Если хост находится в частном диапазоне, маршрут должен существовать с этой машины, а не с ноутбука коллеги. Копия, закэшированная в прошлом сеансе, скрывает всё это до истечения кэша или перезапуска машины.
Выполните три проверки ниже по порядку и остановитесь на первом сбое, потому что этапы не имеют общей причины. Вместе они показывают, настроена ли политика, доступна ли она и что она возвращает.
scutil --proxy
networksetup -getautoproxyurl "Wi-Fi"
curl -sS -o /dev/null -w "%{http_code}\n" https://config.corp.example/proxy.pac
Первая команда печатает словарь прокси для активной службы, включая любой URL автонастройки, который держит система. Вторая сообщает URL, привязанный к одной именованной службе, что важно на ноутбуке, который переходит между Wi-Fi и Ethernet. Третья получает файл, не отображая его, поэтому 404, тайм-аут и сбой резолвера остаются различимыми. Если последняя команда возвращает скрипт, а приложения всё ещё падают, проблема уже миновала загрузку.
Что на самом деле пропускает ответ DIRECT
Спецификация PAC даёт клиенту небольшой словарь, и DIRECT — одно из его слов. Это слово говорит клиенту пропустить прокси для данного запроса и ничего не говорит о том, какой интерфейс затем использует сокет. Прямой сокет в полном туннеле всё равно выходит через VPN и всё равно показывает адресату адрес выхода туннеля.
Читать DIRECT как находящийся вне VPN — это ошибка, которая отправляет людей в неверную панель настроек. Зеркальная картина столь же часта, потому что к частному прокси можно добраться по разделённому маршруту, пока остальная часть машины остаётся вне туннеля. То, что тогда сообщает адресат, принадлежит собственному выходу прокси, который может находиться в другой стране. Запись ожидания для одного внутреннего хоста и одного публичного хоста быстро это выявляет, поскольку скрипт часто отвечает им по-разному. Как только вы знаете, какой узел создал адрес, отчёт перестаёт быть загадочным.
Три сбоя, которые выглядят как одна страница ошибки
Политика может не загрузиться, выбранный прокси может оказаться недоступным, а запрос, который доходит до службы, там всё равно может быть отклонён. Все три приходят как тайм-аут или общая страница ошибки, и ни один не называет сломавшийся этап. Фиксация решения рядом с ошибкой — это то, что их разделяет. Две пробы ниже проверяют узел, выбранный скриптом, по одной на каждую ветвь, которую он может вернуть.
curl -v --max-time 8 http://proxy.corp.example:8080/
curl -v --max-time 8 https://intranet.corp.example/
Завершённое соединение с прокси переносит вопрос на аутентификацию или на собственную политику прокси, у которой другой владелец. Завершённое соединение с внутренним хостом без прокси на пути исключает маршрут и указывает на политику. Обе команды игнорируют словарь прокси macOS, если оболочка не экспортирует переменные прокси, поэтому сначала очистите их. Ни одна проба не доказывает другую, и поэтому одна страница ошибки так долго вводит в заблуждение.
Что передать вместе с тикетом
Отправьте активную сетевую службу, URL PAC, результат оценки для сбойного хоста и этап, на котором появилась ошибка. Эти четыре позволяют следующему человеку воспроизвести решение, а не гадать, какой слой был задействован. Добавьте состояние туннеля на момент теста, потому что результат, снятый до переподключения, устарел. Сохраните и ревизию скрипта, так как файл политики меняется без предупреждения, и вчерашний ответ может быть уже неактуален.
Запишите, как клиент ведёт себя, когда скрипт невозможно загрузить, потому что реализации различаются, а решение прокси не является общим выключателем устройства. Некоторые возвращаются к прямому соединению, другие отказывают закрыто, и эта разница меняет, выглядит ли сбой как сломанный прокси или как работающая политика. Подтвердите поведение для точного клиента и версии, прежде чем полагаться на него во время инцидента.