1. Введение
Одна из главных проблем при миграции на IPv6 — поддержание доступности конечных точек и сетей, использующих только IPv4. Передовая технология для решения этой проблемы — это сочетание использования DNS64 (определенного в RFC6147) для преобразования A-записей в AAAA-записи для клиентов, а затем NAT64 (определенного в RFC6146) для преобразования специально отформатированных IPv6-адресов в IPv4, где IPv4-адрес встраивается в специальный IPv6-адрес. Данный практический пример поможет пользователю настроить обе функции в виртуальной частной сети (VPC) Google Cloud Platform (GCP). При совместной настройке GCP NAT64 и DNS64 позволяют экземплярам, использующим только IPv6, взаимодействовать с серверами, использующими только IPv4, в интернете.
В этой лабораторной работе вы настроите VPC с различными типами подсетей и экземпляров IPv6: только с глобальным одноадресным адресом (GUA), только с уникальным локальным адресом (ULA) и с двойным стеком ULA. Затем вы настроите и протестируете управляемые сервисы DNS64 и NAT64 Google Cloud для доступа к веб-сайтам, работающим только с IPv4.
2. Чему вы научитесь
- Как создать подсети и экземпляры, поддерживающие только IPv6.
- Как включить управляемую службу DNS64 от Google Cloud для VPC.
- Как создать шлюз Google Cloud NAT, настроенный для NAT64.
- Как проверить разрешение DNS64 из экземпляров, работающих только с IPv6, в адреса, работающие только с IPv4.
- Чем отличается поведение DNS64 и NAT64 в одностековых и двухстековых конфигурациях.
- Как настроить NAT-шлюз для NAT64.
- Как проверить подключение NAT64 от экземпляров, работающих только с IPv6, к адресатам, работающим только с IPv4.
3. Прежде чем начать
Обновите проект, чтобы он поддерживал практическое занятие.
В этом практическом занятии используется переменная `$variables` для упрощения настройки gcloud в Cloud Shell.
Внутри Cloud Shell выполните следующие действия.
gcloud config list project
gcloud config set project [YOUR-PROJECT-ID]
export projectname=$(gcloud config list --format="value(core.project)")
export zonename=[COMPUTE ZONE NAME]
export regionname=[REGION NAME]
Общая архитектура лаборатории

Чтобы продемонстрировать взаимодействие NAT64 и DNS64 с различными типами подсетей IPv6, вы создадите одну VPC с подсетями IPv6 в форматах GUA и ULA. Вы также создадите подсеть с поддержкой двух стеков (используя адресацию ULA), чтобы показать, что DNS64 и NAT64 не применяются к виртуальным машинам с поддержкой двух стеков.
Затем вы настроите DNS64 и NAT64 и проверите подключение к адресам IPv6 и IPv4 в интернете.
4. Этапы подготовки
Для начала настройте необходимую учетную запись службы, IAM, сетевую инфраструктуру и экземпляры в вашем проекте Google Cloud.
Создание учетной записи службы и привязок IAM.
Начнём с создания новой учетной записи службы, которая позволит экземплярам подключаться друг к другу по SSH с помощью gcloud. Эта возможность нам понадобится, поскольку мы не можем использовать IAP для доступа к экземпляру GUA, работающему только по IPv6, а cloudshell пока не поддерживает прямой доступ по IPv6. Выполните следующие команды в cloudshell.
gcloud iam service-accounts create ipv6-codelab \
--description="temporary service account for a codelab" \
--display-name="ipv6codelabSA" \
--project $projectname
gcloud projects add-iam-policy-binding $projectname \
--member=serviceAccount:ipv6-codelab@$projectname.iam.gserviceaccount.com \
--role=roles/compute.instanceAdmin.v1
gcloud iam service-accounts add-iam-policy-binding \
ipv6-codelab@$projectname.iam.gserviceaccount.com \
--member=serviceAccount:ipv6-codelab@$projectname.iam.gserviceaccount.com \
--role=roles/iam.serviceAccountUser
Создайте VPC и включите ULA.
Создайте сеть VPC с пользовательским режимом подсети и включенным внутренним IPv6 от ULA, выполнив следующие команды в Cloudshell.
gcloud compute networks create ipv6-only-vpc \
--project=$projectname \
--subnet-mode=custom \
--mtu=1500 --bgp-routing-mode=global \
--enable-ula-internal-ipv6
Создание правил брандмауэра
Создайте правила брандмауэра для разрешения доступа по SSH. Одно правило разрешает SSH из всего диапазона ULA (fd20::/20). Еще два правила разрешают трафик из предопределенных диапазонов IPv6 и IPv4 IAP (2600:2d00:1:7::/64 и 35.235.240.0/20 соответственно).
Выполните следующие команды в Cloudshell:
gcloud compute firewall-rules create allow-v6-ssh-ula \
--direction=INGRESS --priority=200 \
--network=ipv6-only-vpc --action=ALLOW \
--rules=tcp:22 --source-ranges=fd20::/20 \
--project=$projectname
gcloud compute firewall-rules create allow-v6-iap \
--direction=INGRESS --priority=300 \
--network=ipv6-only-vpc --action=ALLOW \
--rules=tcp --source-ranges=2600:2d00:1:7::/64 \
--project=$projectname
gcloud compute firewall-rules create allow-v4-iap \
--direction=INGRESS --priority=300 \
--network=ipv6-only-vpc --action=ALLOW \
--rules=tcp --source-ranges=35.235.240.0/20 \
--project=$projectname
Создание подсетей
Создайте подсеть только с GUA версии 6, подсеть только с ULA версии 6 и подсеть ULA с поддержкой двух стеков. Выполните следующие команды в Cloudshell:
gcloud compute networks subnets create gua-v6only-subnet \
--network=ipv6-only-vpc \
--project=$projectname \
--stack-type=IPV6_ONLY \
--ipv6-access-type=external \
--region=$regionname
gcloud compute networks subnets create ula-v6only-subnet \
--network=ipv6-only-vpc \
--project=$projectname \
--stack-type=IPV6_ONLY \
--ipv6-access-type=internal \
--enable-private-ip-google-access \
--region=$regionname
gcloud compute networks subnets create ula-dualstack-subnet \
--network=ipv6-only-vpc \
--project=$projectname \
--stack-type=IPV4_IPV6 \
--range=10.120.0.0/16 \
--ipv6-access-type=internal \
--region=$regionname
Создание экземпляров
Создайте экземпляры в каждой из только что созданных подсетей. Экземпляр ULA, поддерживающий только IPv6, указан в облачной платформе, чтобы мы могли использовать его в качестве промежуточного узла для экземпляра GUA, поддерживающего только IPv6. Выполните следующие команды в Cloudshell:
gcloud compute instances create gua-instance \
--subnet gua-v6only-subnet \
--stack-type IPV6_ONLY \
--zone $zonename \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--service-account=ipv6-codelab@$projectname.iam.gserviceaccount.com \
--project=$projectname
gcloud compute instances create ula-instance \
--subnet ula-v6only-subnet \
--stack-type IPV6_ONLY \
--zone $zonename \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--service-account=ipv6-codelab@$projectname.iam.gserviceaccount.com \
--project=$projectname
gcloud compute instances create dualstack-ula-instance \
--subnet ula-dualstack-subnet \
--stack-type IPV4_IPV6 \
--zone $zonename \
--project=$projectname
Первоначальный доступ и настройка экземпляра
Подключитесь к экземпляру ULA по SSH, который по умолчанию будет использовать IAP. Используйте следующую команду в CloudShell для подключения к экземпляру ULA по SSH:
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
Мы также будем использовать экземпляр ULA в качестве промежуточного сервера для экземпляра GUA (поскольку IAP не работает с экземплярами GUA, а виртуальные машины Cloudshell не могут получить доступ к адресам IPv6).
Находясь внутри оболочки экземпляра ULA, попробуйте подключиться к экземпляру GUA по SSH, используя следующую команду gcloud.
При первом запуске команды SSH внутри экземпляра вам будет предложено настроить пару ключей SSH. Нажимайте Enter до тех пор, пока ключ не будет создан и не будет выполнена команда SSH; это создаст новую пару ключей без парольной фразы.
ula-instance:~$ gcloud compute ssh gua-instance
WARNING: The private SSH key file for gcloud does not exist.
WARNING: The public SSH key file for gcloud does not exist.
WARNING: You do not have an SSH key for gcloud.
WARNING: SSH keygen will be executed to generate a key.
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/galhabian/.ssh/google_compute_engine
Your public key has been saved in /home/galhabian/.ssh/google_compute_engine.pub
The key fingerprint is:
SHA256:5PYzydjcpWYiFtzetYCBI6vmy9dqyLsxgDORkB9ynqY galhabian@ula-instance
The key's randomart image is:
+---[RSA 3072]----+
|.. |
|+.o . |
|o= o . + . |
| o= * o o |
|+o. . S o . o |
|Eo . . . O + = . |
| .=. .+ @ * . |
| +ooo... * |
| **.. |
+----[SHA256]-----+
В случае успеха команда SSH будет выполнена корректно, и вы успешно подключитесь к экземпляру GUA по SSH:
Updating instance ssh metadata...done.
Waiting for SSH key to propagate.
Warning: Permanently added 'compute.3639038240056074485' (ED25519) to the list of known hosts.
Linux gua-instance 6.1.0-34-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.135-1 (2025-04-25) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
<username>@gua-instance:~$
5. Изучите экземпляры, использующие только IPv6.
Давайте рассмотрим оба экземпляра, работающих только с IPv6, подключившись к ним по SSH и изучив их таблицы маршрутизации.
Проверьте экземпляр GUA.
Подключитесь по SSH к экземпляру "gua", сначала перейдя к экземпляру "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$ gcloud compute ssh gua-instance
Давайте посмотрим на таблицу маршрутизации IPv6 экземпляра, используя следующую команду.
<username>@gua-instance:~$ ip -6 route
2600:1900:4041:461::/65 via fe80::56:11ff:fef9:88c1 dev ens4 proto ra metric 100 expires 81sec pref medium
fe80::/64 dev ens4 proto kernel metric 256 pref medium
default via fe80::56:11ff:fef9:88c1 dev ens4 proto ra metric 100 expires 81sec mtu 1500 pref medium
Мы видим три записи в таблице маршрутизации.
- Маршрут /65 для подсети GUA, к которой принадлежит экземпляр, с производным следующим переходом, использующим локальный адрес канала связи для шлюза по умолчанию. Помните, что верхняя граница /65 зарезервирована для балансировщиков нагрузки IPv6 Pass-Through Network Load Balancers.
- Встроенный маршрут /64 для локального одноадресного префикса fe80::/64
- Маршрут по умолчанию, указывающий на локальный адрес шлюза по умолчанию подсети.
Давайте посмотрим на таблицу маршрутизации IPv4, выполнив следующую команду.
<username>@gua-instance:~$ ip -4 route
default via 169.254.1.1 dev ens4 proto dhcp src 169.254.1.2 metric 100
169.254.1.1 dev ens4 proto dhcp scope link src 169.254.1.2 metric 100
169.254.169.254 via 169.254.1.1 dev ens4 proto dhcp src 169.254.1.2 metric 100
Удивительно? На самом деле, мы поддерживаем таблицу маршрутизации IPv4 в экземплярах, работающих только с IPv6, исключительно для обеспечения доступа к серверу метаданных вычислительных ресурсов (169.254.169.154), поскольку это по-прежнему конечная точка, работающая только с IPv4.
Поскольку экземпляр, работающий только с IPv6, получает IP-адрес 169.254.1.2, этот IP-адрес не маршрутизируется никуда, кроме как к серверу метаданных вычислительных ресурсов, поэтому экземпляр фактически изолирован от всех сетей IPv4.
Тесты на завивку
Давайте проверим реальное подключение к веб-сайтам, поддерживающим только версии v4 и v6, с помощью curl.
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
Ниже приведён пример выходных данных.
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
* Trying [2600:9000:20be:cc00:9:ec55:a1c0:93a1]:80...
* Connected to v6.ipv6test.app (2600:9000:20be:cc00:9:ec55:a1c0:93a1) port 80 (#0)
> GET / HTTP/1.1
> Host: v6.ipv6test.app
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
!! Rest of output truncated
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
* Trying 3.163.165.4:80...
* ipv4 connect timeout after 4985ms, move on!
* Trying 3.163.165.50:80...
* ipv4 connect timeout after 2492ms, move on!
* Trying 3.163.165.127:80...
* ipv4 connect timeout after 1246ms, move on!
* Trying 3.163.165.37:80...
* ipv4 connect timeout after 1245ms, move on!
* Failed to connect to v4.ipv6test.app port 80 after 10000 ms: Timeout was reached
* Closing connection 0
curl: (28) Failed to connect to v4.ipv6test.app port 80 after 10000 ms: Timeout was reached
Как и ожидалось, экземпляр, работающий только с IPv6, не имеет доступа к интернет-точке IPv4. Без настройки DNS64 и NAT64 экземпляр, работающий только с IPv6, не имеет пути к целевому IPv4-адресу. Доступ к целевому IPv6-адресу работает нормально, поскольку экземпляр имеет IPv6-адрес GUA.
Изучите экземпляр ULA.
Подключитесь по SSH к экземпляру "ula-instance" (по умолчанию используется IAP).
gcloud compute ssh ula-instance --project $projectname --zone $zonename
Давайте посмотрим на таблицу маршрутизации IPv6 экземпляра, используя следующую команду.
<username>@ula-instance:~$ ip -6 route
fd20:f06:2e5e:2000::/64 via fe80::55:82ff:fe6b:1d7 dev ens4 proto ra metric 100 expires 84sec pref medium
fe80::/64 dev ens4 proto kernel metric 256 pref medium
default via fe80::55:82ff:fe6b:1d7 dev ens4 proto ra metric 100 expires 84sec mtu 1500 pref medium
Мы видим три записи в таблице маршрутизации, аналогичные записи в экземпляре GUA, за исключением того, что маска равна /64 вместо /65. А маршрут подсети принадлежит диапазону ULA (в рамках агрегата fd20::/20).
Давайте посмотрим на таблицу маршрутизации IPv4, выполнив следующую команду.
<username>@ula-instance:~$ ip -4 route
default via 169.254.1.1 dev ens4 proto dhcp src 169.254.1.2 metric 100
169.254.1.1 dev ens4 proto dhcp scope link src 169.254.1.2 metric 100
169.254.169.254 via 169.254.1.1 dev ens4 proto dhcp src 169.254.1.2 metric 100
Это демонстрирует ситуацию, аналогичную той, что наблюдалась в случае с экземпляром GUA.
Тесты на завивку
Повторное тестирование подключения к веб-сайтам, поддерживающим только версии v4 и v6, с использованием curl.
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
Ниже приведён пример выходных данных.
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
* Trying [2600:9000:20be:8400:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 4986ms, move on!
* Trying [2600:9000:20be:9000:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 2493ms, move on!
* Trying [2600:9000:20be:d600:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 1246ms, move on!
* Trying [2600:9000:20be:b000:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 622ms, move on!
* Trying [2600:9000:20be:7200:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 312ms, move on!
* Trying [2600:9000:20be:8600:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 155ms, move on!
* Trying [2600:9000:20be:7a00:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 77ms, move on!
* Trying [2600:9000:20be:ce00:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 77ms, move on!
* Failed to connect to v6.ipv6test.app port 80 after 10000 ms: Timeout was reached
* Closing connection 0
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
* Trying 3.163.165.4:80...
* ipv4 connect timeout after 4985ms, move on!
* Trying 3.163.165.50:80...
* ipv4 connect timeout after 2492ms, move on!
* Trying 3.163.165.127:80...
* ipv4 connect timeout after 1246ms, move on!
* Trying 3.163.165.37:80...
* ipv4 connect timeout after 1245ms, move on!
* Failed to connect to v4.ipv6test.app port 80 after 10000 ms: Timeout was reached
* Closing connection 0
curl: (28) Failed to connect to v4.ipv6test.app port 80 after 10000 ms: Timeout was reached
В случае использования экземпляра ULA отсутствует доступ к обеим интернет-точкам, поскольку для точки доступа IPv6 мы не можем использовать адрес ULA для исходящей связи, а экземпляр, работающий только с IPv6, не имеет доступа к IPv4.
6. Включите NAT64 и DNS64.
Настройте управляемые службы DNS64 и NAT64 для вашей VPC.
DNS64
Включите политику DNS64 Server для вашей VPC. Это укажет DNS-резолверу VPC синтезировать записи AAAA для ответов только с символом A. Выполните следующие команды в Cloudshell:
gcloud beta dns policies create allow-dns64 \
--description="Enable DNS64 Policy" \
--networks=ipv6-only-vpc \
--enable-dns64-all-queries \
--project $projectname
NAT64
Создайте Cloud Router, необходимый для Cloud NAT. Затем создайте шлюз Cloud NAT, настроенный для NAT64, включив его для всех диапазонов IP-адресов подсетей, поддерживающих только IPv6, и автоматически выделяя внешние IP-адреса. Выполните следующие команды в cloudshell:
gcloud compute routers create nat64-router \
--network=ipv6-only-vpc \
--region=$regionname \
--project=$projectname
gcloud beta compute routers nats create nat64-natgw \
--router=nat64-router \
--region=$regionname \
--auto-allocate-nat-external-ips \
--nat64-all-v6-subnet-ip-ranges \
--project=$projectname
7. Проверьте работу NAT64 и DNS64.
Теперь давайте протестируем вашу конфигурацию NAT64 и DNS64 на экземплярах, работающих только с IPv6, начиная с экземпляра GUA, а затем перейдя к экземпляру ULA.
Тестирование DNS64/NAT64 из экземпляра GUA.
Подключитесь по SSH к экземпляру "gua", сначала перейдя к экземпляру "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$ gcloud compute ssh gua-instance
Тесты DNS
Проверьте разрешение DNS для веб-сайта, использующего только IPv6 (например, v6.ipv6test.app , но любой веб-сайт, использующий только IPv6, должен дать аналогичный результат).
<username>@gua-instance:~$ host -t AAAA v6.ipv6test.app
<username>@gua-instance:~$ host -t A v6.ipv6test.app
Мы ожидаем получения только ответов IPv6 AAAA.
Пример выходных данных
<username>@gua-instance:~$ host -t AAAA v6.ipv6test.app
v6.ipv6test.app has IPv6 address 2600:9000:269f:1000:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:6600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:b600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:3e00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:9c00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:b200:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:a600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:1400:9:ec55:a1c0:93a1
<username>@gua-instance:~$ host -t A v6.ipv6test.app
v6.ipv6test.app has no A record
Проверьте разрешение DNS для веб-сайта, использующего только IPv4 (например, v4.ipv6test.app). Ожидается как запись A (исходный IPv4), так и запись AAAA, синтезированная DNS64 с использованием известного префикса 64:ff9b::/96.
<username>@gua-instance:~$ host -t AAAA v4.ipv6test.app
<username>@gua-instance:~$ host -t A v4.ipv6test.app
Пример выходных данных
<username>@gua-instance:~$ host -t AAAA v4.ipv6test.app
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3318
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3344
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:333c
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3326
<username>@gua-instance:~$ host -t A v4.ipv6test.app
v4.ipv6test.app has address 54.192.51.68
v4.ipv6test.app has address 54.192.51.24
v4.ipv6test.app has address 54.192.51.60
v4.ipv6test.app has address 54.192.51.38
В приведенном выше примере десятичный IPv4-адрес (54.192.51.38) будет преобразован в шестнадцатеричное значение как (36 c0 33 26), и, следовательно, мы ожидаем получить ответ для записи AAAA в виде (64:ff9b::36c0:3326), что соответствует одному из полученных нами ответов AAAA.
Тесты на завивку
Давайте проверим фактическое подключение к тем же конечным точкам, поддерживающим только v4 и v6, используя curl по IPv6.
<username>@gua-instance:~$ curl -vv -6 v6.ipv6test.app
<username>@gua-instance:~$ curl -vv -6 v4.ipv6test.app
Ниже приведён пример выходных данных.
<username>@gua-instance:~$ curl -vv -6 v6.ipv6test.app
* Trying [2600:9000:269f:1000:9:ec55:a1c0:93a1]:80...
* Connected to v6.ipv6test.app (2600:9000:269f:1000:9:ec55:a1c0:93a1) port 80 (#0)
> GET / HTTP/1.1
##
## <Output truncated for brevity>
##
<username>@gua-instance:~$ curl -vv -6 v4.ipv6test.app
* Trying [64:ff9b::36c0:333c]:80...
* Connected to v4.ipv6test.app (64:ff9b::36c0:333c) port 80 (#0)
> GET / HTTP/1.1
##
## <Output truncated for brevity>
##
Обе команды curl выполнены успешно. Обратите внимание, что подключение к веб-сайту, работающему только по IPv4, через IPv6 стало возможным благодаря совместной работе NAT64 и DNS64, обеспечивающей успешное соединение.
Проверьте исходные IP-адреса
Давайте воспользуемся службой отражения IP-адресов, чтобы проверить исходный IP-адрес, наблюдаемый получателем.
<username>@gua-instance:~$ curl -6 v4.ipv6test.app
<username>@gua-instance:~$ curl -6 v6.ipv6test.app
Пример выходных данных
<username>@gua-instance:~$ curl -6 v4.ipv6test.app
34.47.60.91
<username>@gua-instance:~$ curl -6 v6.ipv6test.app
2600:1900:40e0:6f:0:1::
Указанный IPv6-адрес должен совпадать с IPv6-адресом экземпляра. Этот адрес должен совпадать с результатом выполнения команды "ip -6 address" на экземпляре. В качестве примера
<username>@gua-instance:~$ ip -6 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 2600:1900:40e0:6f:0:1::/128 scope global dynamic noprefixroute
valid_lft 79912sec preferred_lft 79912sec
inet6 fe80::86:d9ff:fe34:27ed/64 scope link
valid_lft forever preferred_lft forever
Однако сообщаемый IPv4-адрес должен совпадать с внешним IP-адресом шлюза Cloud NAT, поскольку он выполняет функцию NAT64 перед отправкой данных в интернет. Это можно проверить, выполнив команду gcloud в Cloudshell.
gcloud compute routers get-nat-ip-info \
nat64-router \
--region=$regionname
Пример выходных данных
result:
- natIpInfoMappings:
- mode: AUTO
natIp: 34.47.60.91
usage: IN_USE
natName: nat64-natgw
Обратите внимание, что значение "natIp", указанное в выходных данных, совпадает с данными, полученными с веб-сайта IP-отражения.
Тестирование DNS64/NAT64 из экземпляра ULA.
Сначала подключитесь по SSH к экземпляру ULA "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
Тесты DNS
Проверьте разрешение DNS для веб-сайта, использующего только IPv6 (например, v6.ipv6test.app , но любой веб-сайт, использующий только IPv6, должен дать аналогичный результат).
<username>@ula-instance:~$ host -t AAAA v6.ipv6test.app
<username>@ula-instance:~$ host -t A v6.ipv6test.app
Мы ожидаем получения только ответов IPv6 AAAA.
Пример выходных данных
<username>@ula-instance:~$ host -t AAAA v6.ipv6test.app
v6.ipv6test.app has IPv6 address 2600:9000:269f:1000:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:6600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:b600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:3e00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:9c00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:b200:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:a600:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:1400:9:ec55:a1c0:93a1
<username>@ula-instance:~$ host -t A v6.ipv6test.app
v6.ipv6test.app has no A record
Проверьте разрешение DNS для веб-сайта, использующего только IPv4 (например, v4.ipv6test.app). Ожидается как запись A (исходный IPv4), так и запись AAAA, синтезированная DNS64 с использованием известного префикса 64:ff9b::/96.
<username>@ula-instance:~$ host -t AAAA v4.ipv6test.app
<username>@ula-instance:~$ host -t A v4.ipv6test.app
Пример выходных данных
<username>@gua-instance:~$ host -t AAAA v4.ipv6test.app
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3318
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3344
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:333c
v4.ipv6test.app has IPv6 address 64:ff9b::36c0:3326
<username>@gua-instance:~$ host -t A v4.ipv6test.app
v4.ipv6test.app has address 54.192.51.68
v4.ipv6test.app has address 54.192.51.24
v4.ipv6test.app has address 54.192.51.60
v4.ipv6test.app has address 54.192.51.38
В приведенном выше примере десятичный IPv4-адрес (54.192.51.38) будет преобразован в шестнадцатеричное значение как (36 c0 33 26), и, следовательно, мы ожидаем получить ответ для записи AAAA в виде (64:ff9b::36c0:3326), что соответствует одному из полученных нами ответов AAAA.
Тесты на завивку
Давайте проверим фактическое подключение к тем же конечным точкам, доступным только для версий v4 и v6, используя curl.
Для начала покажем, что доступность по IPv4 невозможна, поскольку данный экземпляр поддерживает только IPv6.
<username>@ula-instance:~$ curl -vv -4 --connect-timeout 10 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv -4 --connect-timeout 10 v4.ipv6test.app
Оба варианта выполнения команды curl завершатся неудачей. Причины неудачи будут разными. Ниже приведён пример выходных данных.
<username>@ula-instance:~$ curl -vv -4 v6.ipv6test.app
* Could not resolve host: v6.ipv6test.app
* Closing connection 0
curl: (6) Could not resolve host: v6.ipv6test.app
<username>@ula-instance:~$ curl -vv -4 --connect-timeout 10 v4.ipv6test.app
* Trying 54.192.51.68:80...
* ipv4 connect timeout after 4993ms, move on!
* Trying 54.192.51.38:80...
* ipv4 connect timeout after 2496ms, move on!
* Trying 54.192.51.24:80...
* ipv4 connect timeout after 1248ms, move on!
* Trying 54.192.51.60:80...
* Connection timeout after 10000 ms
* Closing connection 0
curl: (28) Connection timeout after 10000 ms
Запрос curl к IPv4-адресу, доступному только по IPv6, завершается неудачей, поскольку разрешение DNS-записей для записи A завершается ошибкой (как было продемонстрировано во время тестов DNS). Запрос curl к IPv4-адресу, доступному только по IPv4, завершается неудачей, поскольку экземпляр, работающий только по IPv6, не имеет доступа ни к одному IPv4-адресу, и по этой причине происходит таймаут.
Теперь давайте проверим доступность по IPv6.
<username>@ula-instance:~$ curl -vv -6 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv -6 v4.ipv6test.app
Ниже приведён пример выходных данных.
<username>@ula-instance:~$ curl -vv -6 v6.ipv6test.app
* Trying [2600:9000:20be:c000:9:ec55:a1c0:93a1]:80...
* connect to 2600:9000:20be:c000:9:ec55:a1c0:93a1 port 80 failed: Connection timed out
* Trying [2600:9000:20be:f000:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 84507ms, move on!
* Trying [2600:9000:20be:ae00:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 42253ms, move on!
* Trying [2600:9000:20be:2000:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 21126ms, move on!
* Trying [2600:9000:20be:b600:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 10563ms, move on!
* Trying [2600:9000:20be:7600:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 5282ms, move on!
* Trying [2600:9000:20be:b000:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 2640ms, move on!
* Trying [2600:9000:20be:3400:9:ec55:a1c0:93a1]:80...
* ipv6 connect timeout after 2642ms, move on!
* Failed to connect to v6.ipv6test.app port 80 after 300361 ms: Timeout was reached
* Closing connection 0
<username>@ula-instance:~$ curl -vv -6 v4.ipv6test.app
* Trying [64:ff9b::36c0:333c]:80...
* Connected to v4.ipv6test.app (64:ff9b::36c0:333c) port 80 (#0)
> GET / HTTP/1.1
##
## <Output truncated for brevity>
##
В то время как запрос curl к веб-сайту, работающему только по IPv6, завершается неудачей, поскольку подсети ULA не имеют прямого доступа к интернету, запрос curl к веб-сайту, работающему только по IPv4, выполняется успешно, поскольку DNS64 и NAT64 работают одинаково для экземпляров GUA и ULA; единственное требование — чтобы экземпляр работал только по IPv6.
Тестирование DNS64/NAT64 из экземпляра ULA с поддержкой DualStack.
Сначала подключитесь по SSH к экземпляру Dual-Stack ULA "dualstack-ula-instance". Необходимо использовать флаг "–tunnel-through-iap", чтобы заставить gcloud использовать IPv4-адрес для IAP.
gcloud compute ssh dualstack-ula-instance --project $projectname --zone $zonename --tunnel-through-iap
<username>@dualstack-ula-instance:~$
Давайте теперь протестируем DNS64, используя утилиту "host".
<username>@dualstack-ula-instance:~$ host v4.ipv6test.app
v4.ipv6test.app has address 54.192.51.38
v4.ipv6test.app has address 54.192.51.24
v4.ipv6test.app has address 54.192.51.68
v4.ipv6test.app has address 54.192.51.60
<username>@dualstack-ula-instance:~$ host v6.ipv6test.app
v6.ipv6test.app has IPv6 address 2600:9000:269f:fc00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:1c00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:a200:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:8a00:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:c800:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:c200:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:5800:9:ec55:a1c0:93a1
v6.ipv6test.app has IPv6 address 2600:9000:269f:dc00:9:ec55:a1c0:93a1
Обратите внимание, что веб-сайт, работающий только с IPv4, теперь возвращает только IPv4-адреса, а не синтетические ответы DNS64. Это связано с тем, что DNS64 применяется только к экземплярам, работающим только с IPv6, и не оценивается для экземпляров с двойным стеком.
Чтобы обойтись без DNS64, добавим запись в файл /etc/hosts, чтобы проверить, работает ли NAT64. Выполните следующую команду внутри экземпляра с поддержкой двух стеков:
<username>@dualstack-ula-instance:~$ echo '64:ff9b::36c0:3326 v4.ipv6test.app' | sudo tee -a /etc/hosts
Теперь давайте воспользуемся curl, чтобы проверить доступ к веб-сайту IPv4 по протоколу IPv6.
<username>@dualstack-ula-instance:~$ curl -vv -6 --connect-timeout 10 v4.ipv6test.app
Вот пример вывода приведенной выше команды.
<username>@dualstack-ula-instance:~$ curl -vv -6 --connect-timeout 10 v4.ipv6test.app
* Trying [64:ff9b::36c0:3326]:80...
* ipv6 connect timeout after 10000ms, move on!
* Failed to connect to v4.ipv6test.app port 80 after 10001 ms: Timeout was reached
* Closing connection 0
curl: (28) Failed to connect to v4.ipv6test.app port 80 after 10001 ms: Timeout was reached
Запрос curl должен завершиться по таймауту, поскольку, как и DNS64, NAT64 также требует, чтобы экземпляр работал только с IPv6.
Чтобы убедиться, что NAT64 на самом деле не применяется к экземпляру с двойным стеком, воспользуемся командой "get-nat-mapping", чтобы вывести список всех сопоставлений портов, которые применяет шлюз NAT. Выполните следующие команды в Cloudshell:
gcloud compute routers get-nat-mapping-info \
nat64-router --region $regionname \
--project $projectname
В результате вы получите код, похожий на приведенный ниже фрагмент:
---
instanceName: gua-instance
interfaceNatMappings:
- natIpPortRanges:
- 34.47.60.91:1024-1055
numTotalDrainNatPorts: 0
numTotalNatPorts: 32
sourceAliasIpRange: ''
sourceVirtualIp: '2600:1900:40e0:6f:0:1::'
- natIpPortRanges:
- 34.47.60.91:32768-32799
numTotalDrainNatPorts: 0
numTotalNatPorts: 32
sourceAliasIpRange: ''
sourceVirtualIp: '2600:1900:40e0:6f:0:1::'
---
instanceName: ula-instance
interfaceNatMappings:
- natIpPortRanges:
- 34.47.60.91:1056-1087
numTotalDrainNatPorts: 0
numTotalNatPorts: 32
sourceAliasIpRange: ''
sourceVirtualIp: fd20:9c2:93fc:2800:0:0:0:0
- natIpPortRanges:
- 34.47.60.91:32800-32831
numTotalDrainNatPorts: 0
numTotalNatPorts: 32
sourceAliasIpRange: ''
sourceVirtualIp: fd20:9c2:93fc:2800:0:0:0:0
Результаты NAT показывают, что шлюз NAT64 выделил порты только для экземпляров GUA и ULA, поддерживающих только IPv6, но не для экземпляра с поддержкой двойного стека.
8. Уборка
Очистка облачного маршрутизатора
Внутри Cloud Shell выполните следующие действия:
gcloud compute routers delete nat64-router \
--region $regionname \
--project $projectname --quiet
Отменить привязку и очистить политику DNS
Внутри Cloud Shell выполните следующие действия:
gcloud beta dns policies update allow-dns64 \
--networks="" \
--project $projectname
gcloud beta dns policies delete allow-dns64 \
--project $projectname --quiet
Очистка экземпляров
Внутри Cloud Shell выполните следующие действия: (обратите внимание, что используется бета-версия gcloud, позволяющая применять флаг no-graceful-shutdown для более быстрой операции удаления экземпляра)
gcloud beta compute instances delete gua-instance \
--zone $zonename \
--no-graceful-shutdown \
--project=$projectname --quiet
gcloud beta compute instances delete ula-instance \
--zone $zonename \
--no-graceful-shutdown \
--project=$projectname --quiet
gcloud beta compute instances delete dualstack-ula-instance \
--zone $zonename \
--no-graceful-shutdown \
--project=$projectname --quiet
Очистка подсетей
Внутри Cloud Shell выполните следующие действия:
gcloud compute networks subnets delete gua-v6only-subnet \
--project=$projectname --quiet \
--region=$regionname
gcloud compute networks subnets delete ula-v6only-subnet \
--project=$projectname --quiet \
--region=$regionname
gcloud compute networks subnets delete ula-dualstack-subnet \
--project=$projectname --quiet \
--region=$regionname
Очистка правил брандмауэра
Внутри Cloud Shell выполните следующие действия:
gcloud compute firewall-rules delete allow-v6-iap \
--project=$projectname \
--quiet
gcloud compute firewall-rules delete allow-v6-ssh-ula \
--project=$projectname \
--quiet
gcloud compute firewall-rules delete allow-v4-iap \
--project=$projectname \
--quiet
Очистка VPC
Внутри Cloud Shell выполните следующие действия:
gcloud compute networks delete ipv6-only-vpc \
--project=$projectname \
--quiet
Устраните неполадки в разрешениях IAM и учетной записи службы.
Внутри Cloud Shell выполните следующие действия:
gcloud projects remove-iam-policy-binding $projectname \
--member=serviceAccount:ipv6-codelab@$projectname.iam.gserviceaccount.com \
--role=roles/compute.instanceAdmin.v1
gcloud iam service-accounts delete \
ipv6-codelab@$projectname.iam.gserviceaccount.com \
--quiet \
--project $projectname
9. Поздравляем!
Вы успешно использовали NAT64 и DNS64, чтобы разрешить экземплярам, использующим только IPv6, доступ к адресам в интернете, использующим только IPv4.
Что дальше?
Посмотрите некоторые из этих практических занятий по программированию...
- Доступ к API Google с локальных хостов с использованием IPv6-адресов.
- Варианты IP-адресации: IPv4 и IPv6
- Использование статических маршрутов IPv6: экземпляр следующего перехода, адрес следующего перехода и шлюз следующего перехода.