Предоставление исходящего доступа частной подсети

AWSBeginner
Практиковаться сейчас

Введение

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

Сначала завершите Control Application Access with Security Groups. Новая среда предоставляет собственное приложение, публичную и частную подсети, публичный маршрут в Internet и правила безопасности. CLI уже настроен. Сохраните эти ресурсы и постороннюю контрольную сеть; создайте и затем удалите только свой NAT-шлюз, его Elastic IP и частный маршрут по умолчанию.

Связь с сертификацией

Лабораторная работа позволяет отработать следующие темы экзаменов.

Проверка частного приложения и выделение адреса NAT

Проверьте предоставленную сеть, наблюдайте отсутствие исходящего пути и выделите адрес будущему NAT-шлюзу.

Выполняйте команды CLI в Terminal, открыв рядом AWS View. Представление читает то же состояние ресурсов. Приложение имеет частный IPv4-адрес 10.20.2.10 в private-subnet, а не в public-subnet.

cd /home/labex/project

Выберите VPC приложения по тегу Name. --filters ограничивает результаты, --query выбирает ID, а $(...) сохраняет его в переменной оболочки:

VPC_ID=$(aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=application-network \
  --query 'Vpcs[0].VpcId' \
  --output text)

Выберите публичную подсеть этой VPC. Здесь NAT-шлюз получит путь в Internet:

PUBLIC_SUBNET_ID=$(aws ec2 describe-subnets \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=public-subnet \
  --query 'Subnets[0].SubnetId' \
  --output text)

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

PRIVATE_RT_ID=$(aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=private-routes \
  --query 'RouteTables[0].RouteTableId' \
  --output text)

Проверьте обе предоставленные таблицы. Проекция после []. выбирает удобные для чтения поля каждой таблицы:

aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=$VPC_ID" \
  --query 'RouteTables[].{Name:Tags[?Key==`Name`].Value|[0],Routes:Routes,Associations:Associations}' \
  --output json

Обе именованные таблицы содержат маршрут VPC local. Может также появиться главная таблица без имени; не изменяйте ее. Именованные таблицы явно связаны с подсетями, поэтому используйте выбранную private-routes. Публичная таблица также направляет 0.0.0.0/0 к Internet-шлюзу, а частная не имеет маршрута по умолчанию. Частная подсеть не имеет прямого маршрута к Internet-шлюзу. Публичный NAT-шлюз позволяет частным приложениям инициировать IPv4-соединения со своего публичного адреса. Он располагается в публичной подсети, чей собственный маршрут в Internet уже предоставлен.

В AWS View нажмите Request outbound service. HTTP-запрос частного приложения возвращает Connection failed, поскольку нет маршрута к внешнему сервису 198.51.100.20:9000. Нажмите Request private application from outside: незапрошенный внешний HTTP-запрос к 10.20.2.10:80 также не проходит. Приложение сохраняет частный адрес.

Elastic IP — выделенный публичный IPv4-адрес. Выделите один в домене VPC и добавьте теги для распознавания учебного ресурса. Значение --tag-specifications в кавычках является одним аргументом, описывающим тип ресурса и его теги:

ALLOCATION_ID=$(aws ec2 allocate-address \
  --domain vpc \
  --tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=parcel-nat-address},{Key=Project,Value=parcel}]' \
  --query 'AllocationId' \
  --output text)

Прочитайте выделенный адрес:

aws ec2 describe-addresses \
  --allocation-ids "$ALLOCATION_ID" \
  --query 'Addresses[].{Allocation:AllocationId,PublicIP:PublicIp,Domain:Domain}' \
  --output table

Результат содержит ID выделения, публичный IPv4-адрес и домен vpc. Запишите публичный адрес для последующего сравнения с трафиком. Он принадлежит будущему NAT, поэтому не связывайте его с приложением. Оставьте этот Terminal открытым, чтобы сохранить ID.

Создание публичного NAT-шлюза

Разместите NAT в публичной подсети и убедитесь, что одно лишь создание шлюза не настраивает маршрутизацию частного приложения.

NAT требует два существующих ресурса: публичную подсеть и выделенный Elastic IP. --subnet-id задает размещение, --allocation-id — публичный адрес, а --connectivity-type public выбирает шлюз для трафика в Internet. Тип ресурса natgateway применяет теги принадлежности. Сохраните созданный ID:

NAT_ID=$(aws ec2 create-nat-gateway \
  --subnet-id "$PUBLIC_SUBNET_ID" \
  --allocation-id "$ALLOCATION_ID" \
  --connectivity-type public \
  --tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=parcel-nat},{Key=Project,Value=parcel}]' \
  --query 'NatGateway.NatGatewayId' \
  --output text)

Создание может вернуть ответ до готовности шлюза. CLI waiter повторно читает состояние, пока не будет выполнено указанное условие. Перед добавлением маршрута дождитесь available:

aws ec2 wait nat-gateway-available --nat-gateway-ids "$NAT_ID"

Успешный waiter завершается без вывода. Прочитайте состояние, подсеть и привязку адреса:

aws ec2 describe-nat-gateways \
  --nat-gateway-ids "$NAT_ID" \
  --query 'NatGateways[].{ID:NatGatewayId,State:State,Subnet:SubnetId,Addresses:NatGatewayAddresses}' \
  --output json

State равен available, Subnet соответствует публичной подсети, а NatGatewayAddresses содержит ваш ID выделения и публичный адрес. PrivateIp находится в диапазоне публичной подсети 10.20.1.0/24: это частный адрес интерфейса NAT, отличный от Elastic IP и адреса приложения. NAT — отдельный ресурс; частное приложение не получило этот адрес.

AWS View теперь показывает NAT. Снова нажмите Request outbound service. Запрос еще не проходит, поскольку в частной таблице нет маршрута по умолчанию. Создание шлюза предоставляет возможный следующий узел, но не выбирает его автоматически для частной подсети. Существующий публичный маршрут к Internet-шлюзу не изменяется.

Маршрутизация исходящего частного трафика через NAT

Добавьте частный маршрут по умолчанию и сравните частный адрес приложения с источником, наблюдаемым внешним сервисом.

Маршрут выбирает следующий узел для диапазона назначения. 0.0.0.0/0 соответствует IPv4-адресам назначения, не покрытым более конкретным маршрутом. --nat-gateway-id выбирает ваш NAT вместо Internet-шлюза. Добавьте маршрут только в сохраненную частную таблицу:

aws ec2 create-route \
  --route-table-id "$PRIVATE_RT_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --nat-gateway-id "$NAT_ID"

Ответ подтверждает успешное создание. Прочитайте маршруты частной таблицы:

aws ec2 describe-route-tables \
  --route-table-ids "$PRIVATE_RT_ID" \
  --query 'RouteTables[].Routes' \
  --output json

Локальный маршрут сохраняется. Новый маршрут по умолчанию содержит ваш NatGatewayId и состояние active. Путь пакета теперь: частное приложение → NAT в публичной подсети → Internet-шлюз → внешний сервис.

Когда AWS View покажет частный маршрут по умолчанию, нажмите Request outbound service. Возвращается Success; тело ответа содержит IPv4-адрес источника, реально наблюдаемый внешним HTTP-сервисом. Сравните его с выделенным публичным адресом:

aws ec2 describe-addresses \
  --allocation-ids "$ALLOCATION_ID" \
  --query 'Addresses[0].PublicIp' \
  --output text

Адреса совпадают. Преобразование сетевых адресов (NAT) заменяет частный адрес источника на публичный адрес шлюза и отслеживает соединение, чтобы ответ вернулся инициатору. Собственный адрес приложения остается 10.20.2.10.

Частное приложение достигает внешнего сервиса через маршрут NAT

Пример AWS View: приложение остается на 10.20.2.10, частный маршрут по умолчанию выбирает доступный NAT, а тело HTTP-ответа показывает выделенный публичный адрес. Созданные ID и адреса могут отличаться.

Нажмите Request private application from outside. По-прежнему возвращается Connection failed. Исходящая связность и ответный трафик не создают публичный входящий путь к частному приложению. NAT не принимает незапрошенное соединение из Internet для этого приложения.

Диагностика и восстановление отсутствующего частного маршрута

Удалите один маршрут, наблюдайте отказ и восстановите связность без повторного создания NAT.

Шлюз может быть доступен, хотя клиент не имеет пригодного маршрута. Удалите только частный маршрут по умолчанию, сохранив NAT и публичный маршрут в Internet:

aws ec2 delete-route --route-table-id "$PRIVATE_RT_ID" --destination-cidr-block 0.0.0.0/0

Успешное удаление не выводит результат. Проверьте частную таблицу:

aws ec2 describe-route-tables \
  --route-table-ids "$PRIVATE_RT_ID" \
  --query 'RouteTables[].Routes' \
  --output json

Остается только локальный маршрут VPC. AWS View еще показывает доступный NAT, но без частного маршрута по умолчанию. Нажмите Request outbound service: новый запрос не проходит. Предыдущий успех — историческая запись, а не результат нового запроса.

Восстановите тот же маршрут к тому же шлюзу:

aws ec2 create-route \
  --route-table-id "$PRIVATE_RT_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --nat-gateway-id "$NAT_ID"

Снова прочитайте маршруты:

aws ec2 describe-route-tables \
  --route-table-ids "$PRIVATE_RT_ID" \
  --query 'RouteTables[].Routes' \
  --output json

Активный маршрут по умолчанию возвращается. Выполните новый Request outbound service в AWS View: он проходит и показывает тот же публичный адрес NAT. Request private application from outside по-прежнему не проходит. Эти наблюдения отличают доступность шлюза от полного пути маршрутизации клиента.

Удаление учебного пути NAT и освобождение адреса

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

Удалите частный маршрут по умолчанию раньше его следующего узла. Иначе таблица может сохранить маршрут к удаленному шлюзу:

aws ec2 delete-route --route-table-id "$PRIVATE_RT_ID" --destination-cidr-block 0.0.0.0/0

Успешное удаление не выводит результат. Удалите только свой NAT:

aws ec2 delete-nat-gateway --nat-gateway-id "$NAT_ID"

Ответ идентифицирует запрошенный шлюз. Перед освобождением адреса используйте waiter удаления:

aws ec2 wait nat-gateway-deleted --nat-gateway-ids "$NAT_ID"

Успешный waiter завершается без вывода. Удаление NAT удаляет сетевой интерфейс и отвязывает Elastic IP, но не освобождает выделение. Прочитайте адрес до освобождения:

aws ec2 describe-addresses \
  --allocation-ids "$ALLOCATION_ID" \
  --query 'Addresses[].{Allocation:AllocationId,PublicIP:PublicIp,Association:AssociationId}' \
  --output json

Выделение и публичный адрес остаются, а Association равен null: адрес выделен, но больше не привязан. Освободите этот отдельный ресурс:

aws ec2 release-address --allocation-id "$ALLOCATION_ID"

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

aws ec2 describe-nat-gateways \
  --query 'NatGateways[].{ID:NatGatewayId,State:State,Subnet:SubnetId}' \
  --output table

Ваш шлюз может остаться в списке в состоянии deleted; активного учебного NAT быть не должно. Сохранившаяся запись удаления не означает возможность пересылать трафик. Проверьте полный список адресов:

aws ec2 describe-addresses \
  --query 'Addresses[].{Allocation:AllocationId,PublicIP:PublicIp}' \
  --output table

Учебное выделение отсутствует. Теперь прочитайте частные маршруты:

aws ec2 describe-route-tables \
  --route-table-ids "$PRIVATE_RT_ID" \
  --query 'RouteTables[].Routes' \
  --output json

Локальный маршрут VPC остается, а маршрут по умолчанию отсутствует. Предоставленные приложение, подсети, правила безопасности, публичный Internet-шлюз и контрольная сеть сохраняются. Ошибка запроса списка ресурсов не доказывает удаление.

В AWS View нажмите Request outbound service: запрос опять не проходит, поскольку вы намеренно удалили путь NAT. Request private application from outside остается заблокированным. Результаты соответствуют исходному состоянию частной сети.

Выполните проверку завершения этого шага.

Итоги

Вы выделили публичный адрес, разместили NAT в публичной подсети и направили через него исходящие запросы частного приложения. Внешний сервис наблюдал преобразованный адрес NAT, а незапрошенные входящие запросы оставались заблокированными. Удаление и восстановление частного маршрута по умолчанию показало, почему одной доступности шлюза недостаточно для связности.

Затем вы удалили маршрут и NAT, освободили адрес и проверили сохранение исходного состояния частной сети.