Почему AWS Client VPN отбрасывает трафик без подходящего маршрута
Конечная точка передаёт пакет только тогда, когда таблица маршрутов покрывает назначение. Прочитайте маршруты, объявите префиксы через for_each, проверьте обратный путь.
Client VPN выдаёт клиенту адрес, рукопожатие завершается, а соединение всё равно никуда не идёт. Прежде чем трогать сертификаты или версии клиента, посмотрите на собственную таблицу маршрутов конечной точки. Конечная точка AWS Client VPN передаёт пакет только тогда, когда один из её маршрутов покрывает префикс назначения; если ничего не совпадает, пакет отбрасывается на конечной точке, и целевой хост никогда не видит SYN.
Это решение о пересылке, а не об аутентификации. Оно принимается после поднятия туннеля и после оценки правил авторизации, поэтому действующий сертификат и действующая группа всё равно могут дать мёртвое соединение.
Конечная точка пересылает только то, что покрывает её таблица маршрутов
Каждый маршрут — это CIDR назначения плюс подсеть, которая должна получить трафик. Конечная точка сравнивает назначение клиента с этим списком, выбирает подходящую запись и отправляет пакет в связанную подсеть. Нет записи — нет следующего перехода.
Обратите внимание, чем маршрут не является. Это не запись в таблице маршрутов VPC, и он ничего не авторизует. Правила авторизации решают, может ли группа добраться до назначения; маршруты решают, есть ли у конечной точки куда отправить пакет. Оба должны совпадать, а отказывают они с разными симптомами, поэтому угадывание, что именно сломано, тратит половину дня.
Классическое несоответствие — пиринг VPC. Кто-то добавляет маршрут для 10.20.0.0/24, тогда как хост живёт в 10.20.4.0/24, поэтому адрес оказывается вне каждой записи. Запись на стороне клиента показывает повторяющиеся SYN без ответа, а журналы цели не показывают вообще ничего.
Прочитайте список маршрутов раньше сертификата
Маршруты конечной точки — отдельный объект, поэтому запрашивайте их напрямую, а не читайте таблицу VPC:
aws ec2 describe-client-vpn-routes --client-vpn-endpoint-id cvpn-endpoint-0123456789abcdef0 --query 'Routes[].{Dest:DestinationCidr,Target:TargetSubnet,Origin:Origin}'Возьмите точный адрес и длину префикса у сбойного клиента, затем проверьте покрытие символ за символом. Действует совпадение по самому длинному префиксу, поэтому более широкий маршрут не спасёт, если более узкий указывает в другое место.
Один ресурс на назначение через for_each
Написанные вручную блоки маршрутов расходятся в тот момент, когда кто-то добавляет префикс в консоли. Держите назначения в карте и создавайте один ресурс на ключ, чтобы каждое добавление или удаление оставалось изолированным.
variable "client_vpn_routes" {
type = map(string)
default = {
"10.20.0.0/16" = "subnet-0aa11bb22cc33dd44"
"172.31.0.0/20" = "subnet-0aa11bb22cc33dd44"
}
}
resource "aws_ec2_client_vpn_route" "this" {
for_each = var.client_vpn_routes
client_vpn_endpoint_id = var.client_vpn_endpoint_id
destination_cidr_block = each.key
target_vpc_subnet_id = each.value
depends_on = [aws_ec2_client_vpn_network_association.this]
}Сохраните зависимость от сетевой ассоциации. Маршруту нужна связанная подсеть, поэтому apply, создающий и то и другое, должен сначала упорядочить ассоциацию, и без этой ссылки Terraform вправе попробовать маршрут первым. Затем прочитайте план: число добавлений маршрутов должно совпасть с добавленными префиксами. Если план ещё и заменяет конечную точку, ресурс конечной точки написан неверно, и его применение отключает каждого подключённого клиента.
Принятие конечной точки, которую вы не создавали
Большинство команд наследуют конечную точку, построенную в консоли, поэтому кода маршрутов не существует. Не поднимайте вторую конечную точку только ради того, чтобы завести маршруты в Terraform.
Вместо этого импортируйте или передайте идентификаторы как переменные и оставьте унаследованные объекты неуправляемыми. Импорту нужен формат идентификатора, который провайдер документирует для каждого типа ресурса; он кодирует конечную точку, префикс назначения и целевую подсеть. Скопируйте эту строку из документации ресурса, а не собирайте по памяти, запустите план и ожидайте отсутствия изменений, прежде чем добавлять что-то новое.
Проследите пакет в том порядке, в котором он движется
Если маршрут есть, а соединение всё равно не работает, пройдите путь по порядку, а не гадайте на верхнем уровне.
- Маршрут: префикс покрывает назначение и указывает на подсеть, связанную с конечной точкой.
- Авторизация: правило авторизации разрешает это назначение для группы пользователя. Один маршрут никогда не даёт доступа.
- Обратный путь: таблица маршрутов целевой подсети отправляет ответы обратно к конечной точке, а группа безопасности разрешает порт из пула адресов клиента.
- Приложение: откройте реальное TCP-соединение с клиента, затем подтвердите, что журналы цели показывают ожидаемый адрес источника из пула.
Меняйте по одному префиксу за apply, потом перечитайте список маршрутов и запишите вместе назначение, разрешающее правило и обратный путь. Следующий человек, который будет отлаживать отклонённое соединение, должен начать с этой описи, а не с теории о сертификатах.