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

Страница загружается снаружи, а не через туннель

Сравниваются два разных запроса. Из мобильной сети браузер напрямую попадает на публичный адрес. Изнутри туннеля то же имя разрешается в тот же публичный адрес, и пакет теперь должен выйти через туннель, чтобы достичь адреса на собственной дальней стороне туннеля. То же имя, тот же адрес, две совершенно разные позиции.

Маршрут назначения выбирает адрес, а не порт. Ничто в таблице маршрутизации не знает, что порт 443 предназначен для администрирования, а порт 1194 — для транспорта, поэтому оба считаются одним и тем же назначением.

Поэтому страница иногда работает, а иногда нет, в зависимости от того, какое имя и какую сеть использовал клиент. Это проблема пути, а не проблема аутентификации. Оба клиента прекрасно проходят аутентификацию.

Держите внешнюю конечную точку доступной

Профилям полного туннеля нужен маршрут-исключение для конечной точки VPN, и параметр redirect-gateway в OpenVPN документирует именно это: удалённая конечная точка сохраняет маршрут через ранее существовавший шлюз, чтобы туннель не маршрутизировал в себя. Уберите это исключение, и шифрованный транспорт пойдёт за туннелем, что завершит сеанс в петле. Именно из-за этого исключения адрес конечной точки остаётся доступным изнутри туннеля.

Следствие в том, что публичный адрес остаётся доступным с клиента, поэтому запрос браузера к этому адресу тоже может последовать тому же исключению и выйти, не входя в туннель. Исключение делает свою работу, а вред наносит имя.

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

ip -4 route get 203.0.113.77
ip -4 rule show
ip -4 route show table all

Если поиск показывает маршрут конечной точки через физический шлюз, поведение верное, и страница администрирования просто отправляется не тем путём. Именно здесь разрешение имён становится исправлением.

Дайте службе приватное имя

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

Не перенаправляйте имя транспорта на внутренний адрес, потому что следующее установление туннеля тогда попытается достичь адреса, который существует только внутри туннеля. Эта ошибка даёт VPN, работающий ровно один раз.

Проверьте и оба семейства адресов, потому что оставленная запись AAAA может отправить браузер туда, куда приватный план никогда не доставал.

dig +short admin.hq.internal
dig +short -t AAAA admin.hq.internal
curl -sS -o /dev/null -w '%{http_code} %{remote_ip}\n' https://admin.hq.internal/

Согласуйте политику с местом, где работает процесс

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

Контейнер, опубликованный на порту хоста, идёт другим путём, потому что пакет транслируется по назначению и пересылается. Этот запрос встречает политику пересылки хоста и собственные правила Docker, поэтому работающий нативный слушатель может сосуществовать с контейнером, который отвергает тот же порт.

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

Проверьте приватный доступ и отклонённый публичный путь

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

Читайте привязки и состояние фильтра, а не имя хоста, которое получили пользователи. Открытость — свойство сокета, а не имени. Это различие переживает любое изменение DNS.

ss -lntp | grep ':443'
nft list ruleset | grep -n 443
curl -sS -m 5 -o /dev/null -w '%{http_code}\n' https://203.0.113.77/

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

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