Мой ноутбук показывал подключено. Клиент AWS Client VPN показывал зелёное состояние, endpoint записал сессию, и всё равно я не мог открыть порт MongoDB на инстансе EC2 в приватной подсети. Ничего явно не было сломано: сертификат действителен, профиль пришёл из консоли, туннель передавал трафик. Ошибка была моя, потому что я читал подключено как авторизовано.

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

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

Что на самом деле доказывает подключённая сессия

Во время handshake endpoint проверяет клиентский сертификат по своему trust store или перенаправляет браузер к вашему провайдеру идентичности, если настроен SAML. Если это проходит, клиент получает адрес из клиентского CIDR endpoint, и консоль показывает активное подключение. Ни в один момент этой процедуры никто не спрашивает, можно ли достучаться до 10.0.4.17 по порту 27017.

Разрешение на назначение — отдельный объект на endpoint. Каждый поток сверяется с правилами авторизации, и каждое из них связывает CIDR назначения с группой, которой выдано правило. Когда ни одно правило не покрывает назначение, endpoint принимает сессию и отбрасывает трафик. Нет ни баннера, ни цикла переподключения, ни чего-либо в интерфейсе клиента, что сказало бы отказано.

Сравнивайте правило авторизации с ресурсом, а не с VPC

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

aws ec2 describe-client-vpn-authorization-rules \
  --client-vpn-endpoint-id cvpn-endpoint-0a1b2c3d4e5f6a7b8

Вывод показывает CIDR назначения и идентификатор группы для каждого правила. В нём спрятаны две неисправности. Правило может разрешать 10.0.0.0/16, тогда как инстанс находится в объединённой через peering VPC на 10.1.0.0/16; маршрут peering существует, но никто не написал правило авторизации для второго диапазона. Либо правило указывает на группу каталога, в которой пользователь состоит в каталоге, но не в той группе, которую оценивает endpoint.

Напишите самое узкое правило, которое покрывает назначение, и добавляйте второе только тогда, когда второй CIDR действительно нужен. Широкое правило 0.0.0.0/0 из быстрого старта работает, и именно поэтому оно доживает до продакшена и скрывает модель.

Движение пакета решают две таблицы маршрутов

Маршрут endpoint сопоставляет CIDR назначения с одной из подсетей, с которыми связан endpoint. Это половина пути. Собственная таблица маршрутов подсети всё ещё должна знать, как передать пакет дальше, и это важно в тот момент, когда назначение находится за peering-соединением, transit gateway или локальным диапазоном, доступным через туннель site-to-site.

aws ec2 describe-client-vpn-routes \
  --client-vpn-endpoint-id cvpn-endpoint-0a1b2c3d4e5f6a7b8

Ищите маршрут, у которого назначение совпадает с CIDR ресурса, а целью является связанная подсеть. Если маршрута нет, добавьте его. Если он есть, а хост молчит, зазор на стороне VPC, поэтому сравните с таблицей маршрутов подсети ассоциации.

Одна настройка на стороне клиента ломает маршрутизацию, не ломая туннель: профиль, содержащий route-nopull. Директива велит клиенту на основе OpenVPN игнорировать маршруты, которые продвигает сервер, поэтому интерфейс поднимается только с собственным адресом endpoint, и у назначения просто нет маршрута. Проверьте с помощью ip route show в Linux или netstat -rn в macOS, есть ли маршрут через интерфейс tun. Если нет, удалите route-nopull из экспортированного профиля и переподключитесь, чтобы продвинутые маршруты применились.

Группы безопасности не видят адрес вашего клиента

Это та часть, которую я целый день понимал неправильно. Для IPv4 endpoint, связанного с подсетью, сервис транслирует адрес источника клиента в адрес сетевого интерфейса endpoint в этой подсети. Пакет, который приходит на инстанс, не несёт адрес, который показывал ваш клиент, поэтому правило группы безопасности, разрешающее пул клиентов, скажем 172.16.0.0/22, не совпадает ни с чем.

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

Подключайтесь и к приватному адресу инстанса. Публичный IP выводит пакет из VPC и возвращает его другим путём с другими правилами, поэтому проверка по публичному адресу ничего не говорит о приватном пути.

Порядок изоляции, который останавливается на первой неисправности

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

  1. Подтвердите, какую учётную запись использовала сессия и какую группу оценивает endpoint. Сертификат из одного trust store не является тем же субъектом, что утверждение SAML из каталога.
  2. Подтвердите, что правило авторизации покрывает CIDR ресурса для этой группы.
  3. Подтвердите, что маршрут endpoint существует и указывает на связанную подсеть, а затем что таблица маршрутов подсети умеет передавать дальше.
  4. Подтвердите, что группа безопасности разрешает порт из интерфейса endpoint, а не из пула клиентов.
  5. Проверьте изнутри VPC, с сессией SSM на другом инстансе в той же подсети, чтобы отделить проблему приложения от проблемы клиентского пути.

Когда шаги не решают, я опираюсь на эту таблицу:

SymptomLayer to inspect
Client shows connected, host times out, no byte growth on the interfaceAuthorization rule, then security group
Ping fails but a TCP connect to the port succeedsICMP is blocked; not an access failure
Tunnel reconnects every few minutesTwo machines sharing one client certificate
Works on one laptop, fails on anotherLocal profile has route-nopull or stale pushed routes

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

Если пятый шаг заводит в тупик, выгрузите журнал подключений endpoint и прочитайте записи авторизации, прежде чем что-то менять. Журнал называет проверенное назначение и правило, которое совпало или нет, и это сводит вопрос из четырёх слоёв к одному ответу.

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