AWS Client VPN подключён, но интернета нет: проверка маршрутов
AWS Client VPN подключён, но доступа в интернет нет? Проверьте маршруты клиента, авторизацию конечной точки, выход из подсети и DNS именно в этом порядке.
Вы подключены к конечной точке AWS Client VPN, частная подсеть отвечает, и всё же каждая публичная страница заканчивается тайм-аутом. Такое сочетание сужает проблему до одного из трёх объектов на управляемой стороне: маршрута, который устанавливает клиент, маршрута конечной точки вместе с её правилом авторизации либо следующего перехода связанной подсети. Я проверяю их именно в этом порядке, потому что каждый сбой выглядит со стороны клиента по-разному. Это руководство охватывает управляемую конечную точку, связанную с VPC, а не сервер OpenVPN на инстансе EC2 и не подключение Cloud WAN или Transit Gateway.
Начните с того, что клиент действительно маршрутизирует
Состояние подключения доказывает сеанс TLS и назначение CIDR клиенту, и ничего больше. Спросите операционную систему, куда пойдёт публичный адрес, пока туннель поднят. В Linux ip route get 1.1.1.1 должен назвать интерфейс туннеля; в macOS netstat -rn -f inet | head -5 показывает запись по умолчанию; в Windows Find-NetRoute -RemoteIPAddress 1.1.1.1 печатает выбранный интерфейс и следующий переход.
Затем прочитайте флаг раздельного туннеля, потому что он решает, являются ли опубликованные маршруты конечной точки единственными назначениями, которые клиент отправляет в туннель:
aws ec2 describe-client-vpn-endpoints \
--client-vpn-endpoint-ids cvpn-endpoint-0123456789abcdef0 \
--query 'ClientVpnEndpoints[0].SplitTunnel'Когда SplitTunnel равно true, публичное назначение использует туннель только если конечная точка публикует покрывающий его маршрут, поэтому отсутствующий 0.0.0.0/0 оставляет этот трафик на локальном интерфейсе. Когда оно false, клиент перехватывает трафик, но конечная точка всё равно должна его маршрутизировать и авторизовать; иначе пакеты входят в туннель и останавливаются там. Переподключите клиент после изменения любого из двух параметров, потому что маршруты и DNS-серверы выдаются в момент подключения, а работающий клиент может сохранить старый набор.
Читайте маршрут конечной точки и правило авторизации по отдельности
Это два объекта, и создание одного не создаёт другой. Перечислите маршруты конечной точки и найдите маршрут по умолчанию, цель которого — связанная подсеть:
aws ec2 describe-client-vpn-routes \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0У каждого маршрута ровно одна целевая подсеть, поэтому трём связям нужен соответствующий маршрут по умолчанию для каждой. AWS документирует это требование покрытия, а практический симптом пробела — пользователь, который работает из одной подсети и застревает из другой, что читается как периодический сбой, а не как отсутствующий маршрут. Официальная документация сценария Client VPN описывает схему с публичной подсетью, к которой относятся эти маршруты.
Авторизация — второй объект. Когда ни одно правило не покрывает публичное назначение, туннель несёт пакет, а сервис его отбрасывает, поэтому частные ресурсы продолжают работать, а интернет нет:
aws ec2 describe-client-vpn-authorization-rules \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0Правило для CIDR VPC ничего не говорит о 0.0.0.0/0. Добавление недостающих частей для полного туннеля означает один маршрут на каждую связанную подсеть плюс правило авторизации, которое можно будет проверить позже:
aws ec2 create-client-vpn-route \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--target-vpc-subnet-id subnet-0a1b2c3d4e5f67890
aws ec2 create-client-vpn-authorization-rule \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--access-all \
--description "internet egress for full tunnel"--access-all выдаёт назначение каждому клиенту конечной точки, поэтому держите его только пока туннель должен быть полным; правило, привязанное к группе каталога, предпочтительнее, когда есть группы для привязки.
Проследите пакет за пределы связанной подсети
Маршрут конечной точки решает, что AWS передаёт пакет этой подсети. Он не решает следующий переход за ней, который живёт в собственной таблице маршрутов VPC подсети:
aws ec2 describe-route-tables \
--filters Name=association.subnet-id,Values=subnet-0a1b2c3d4e5f67890 \
--query 'RouteTables[].Routes[?DestinationCidrBlock==`0.0.0.0/0`]'Рабочий маршрут по умолчанию указывает на интернет-шлюз для публичной подсети или на шлюз NAT для частной, а состояние blackhole означает, что цель удалена и путь теперь тихо умирает. Это другие таблицы, чем список маршрутов конечной точки, и исправление одной не исправляет другую.
На этом переходе стоят два фильтра. Группа безопасности, применённая к сетевой связи цели, должна разрешать исходящий трафик к публичному назначению, а любой применимый сетевой ACL должен разрешать запрос и обратный трафик на эфемерных портах. Ограничительная группа безопасности связи — частая причина того, что частный доступ работает, а публичный нет.
Выберите первый слой по симптому, а не меняйте все три сразу:
| What you observe | Layer to check first |
|---|---|
| No tunnel interface for a public IP | Client route or split-tunnel flag |
| Tunnel interface chosen, request times out | Endpoint route and authorization rule |
| Endpoint route present, still times out | Subnet route table, association security group |
| Named host fails, numeric address works | DNS servers and their own authorization |
Отделите сбой DNS от мёртвого маршрута
Разрешение имён сбоит иначе, чем пересылка, и полный туннель делает эту разницу важной, потому что до принудительного резолвера теперь доходят через туннель. Если конечная точка указывает DNS-серверы VPC, их адресам нужны покрытие маршрутом и авторизация, как любому другому назначению. Спросите резолвер напрямую, чтобы увидеть, какой сбой у вас есть: dig +short example.com @10.0.0.2, или nslookup example.com 10.0.0.2 в Windows.
Когда числовой URL отвечает, а именованный нет, прекратите править маршрут по умолчанию и займитесь DNS. Запрос к IP-адресу ничего не доказывает об именованном виртуальном хосте и его сертификате, поэтому сохраните один именованный тест в финальной проверке.
Время помогает. TCP-соединение, которое не получает ответ за несколько секунд, указывает на маршрутизацию или фильтр, тогда как запрос, зависший внутри поиска имени, указывает на резолвер. Изменение маршрута по умолчанию, пока резолвер недоступен, обычно превращает один сбой в два.
Откатитесь аккуратно, затем проверьте путь выхода
Оба объекта были добавочными, поэтому откат — это удаление, а не исправление:
aws ec2 delete-client-vpn-route \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--target-vpc-subnet-id subnet-0a1b2c3d4e5f67890
aws ec2 delete-client-vpn-authorization-rule \
--client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--access-allПереподключитесь и подтвердите, каким путём уходит трафик. Сравните наблюдаемый публичный адрес с эластичным IP-адресом шлюза NAT или с интернет-шлюзом, который вы собирались использовать, и проверьте, что частный ресурс всё ещё отвечает в той же сессии.
Завершите коротким списком и считайте последний пункт частью изменения, а не документацией:
- Один
0.0.0.0/0маршрут конечной точки для каждой связанной подсети. - Правило авторизации, покрывающее
0.0.0.0/0для клиентов, которым вы хотите служить. - Маршрут по умолчанию VPC, не находящийся в состоянии blackhole, на каждой связанной подсети.
- Исходящий трафик группы безопасности связи плюс обратный трафик ACL.
- Адреса резолвера маршрутизированы и авторизованы, проверены именованным запросом.
- Записанный откат для маршрута и правила.
Одно замечание об области: это путь IPv4. Клиент с двойным стеком сохраняет уже имеющуюся у него связность IPv6, поэтому маршрут по умолчанию IPv6 — отдельное решение с собственной авторизацией, а не побочный эффект этого.