1. Introducción
Uno de los principales desafíos de la migración a IPv6 es mantener la accesibilidad a las redes y los extremos solo IPv4. Una tecnología líder para abordar este desafío es combinar el uso de DNS64 (definido en RFC6147) para traducir registros A en registros AAAA para los clientes, que luego se combina con NAT64 (definido en RFC6146) para traducir direcciones IPv6 con formato especial en IPv4, donde la dirección IPv4 está integrada en la dirección IPv6 especial. En este codelab, se guía al usuario para que configure ambas funciones en una nube privada virtual (VPC) de Google Cloud Platform (GCP). Cuando se configuran juntos, GCP NAT64 y DNS64 permiten que las instancias solo IPv6 se comuniquen con los servidores solo IPv4 en Internet.
En este lab, configurarás una VPC con diferentes tipos de subredes e instancias de IPv6 : GUA (dirección de unidifusión global) solo IPv6, ULA (dirección local única) solo IPv6 y ULA de pila doble. Luego, configurarás y probarás los servicios administrados de DNS64 y NAT64 de Google Cloud para acceder a sitios web solo para IPv4 desde ellos.
2. Qué aprenderás
- Cómo crear subredes e instancias de solo IPv6
- Cómo habilitar el servicio DNS64 administrado de Google Cloud para una VPC
- Cómo crear una puerta de enlace de Cloud NAT de Google Cloud configurada para NAT64
- Cómo probar la resolución de DNS64 desde instancias solo IPv6 a destinos solo IPv4
- Cómo se diferencia el comportamiento de DNS64 y NAT64 entre las instancias de pila única y de pila doble
- Cómo configurar una puerta de enlace NAT para NAT64
- Cómo probar la conectividad de NAT64 desde instancias solo IPv6 a destinos solo IPv4
3. Antes de comenzar
Actualiza el proyecto para que sea compatible con el codelab
En este codelab, se usan variables para facilitar la implementación de la configuración de gcloud en Cloud Shell.
Dentro de Cloud Shell, haz lo siguiente:
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]
Arquitectura general del lab
Para demostrar cómo NAT64 y DNS64 interactúan con diferentes tipos de subredes IPv6, crearás una sola VPC con subredes IPv6 en formatos GUA y ULA. También crearás una subred de pila doble (con direccionamiento ULA) para demostrar que DNS64 y NAT64 no se aplican a las VMs de pila doble.
Luego, configurarás DNS64 y NAT64, y probarás la conectividad a destinos IPv6 e IPv4 en Internet.
4. Pasos de preparación
Primero, configura la cuenta de servicio, IAM, infraestructura de red y las instancias necesarias en tu proyecto de Google Cloud.
Crea una cuenta de servicio y vinculaciones de IAM
Comenzaremos por crear una cuenta de servicio nueva para permitir que las instancias se conecten entre sí a través de SSH con gcloud. Necesitaremos esta capacidad porque no podemos usar IAP para acceder a la instancia solo para IPv6 de GUA, y Cloud Shell aún no permite el acceso directo a IPv6. Ejecuta los siguientes comandos en Cloud Shell.
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
Crea una VPC y habilita la ULA
Ejecuta los siguientes comandos en Cloud Shell para crear una red de VPC con el modo de subred personalizado y el IPv6 interno de ULA habilitado.
gcloud compute networks create ipv6-only-vpc \
--project=$projectname \
--subnet-mode=custom \
--mtu=1500 --bgp-routing-mode=global \
--enable-ula-internal-ipv6
Crea reglas de firewall
Crea reglas de firewall para permitir el acceso SSH. Una regla permite SSH desde el rango ULA general (fd20::/20). Dos reglas más permiten el tráfico desde los rangos IPv6 e IPv4 predefinidos de IAP (2600:2d00:1:7::/64 y 35.235.240.0/20, respectivamente).
Ejecuta los siguientes comandos en Cloud Shell:
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
Crea subredes
Crea una subred de solo GUA v6, una subred de solo ULA v6 y una subred de ULA de pila doble. Ejecuta los siguientes comandos en Cloud Shell:
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
Crea instancias
Crea instancias en cada una de las subredes que acabas de crear. La instancia de ULA solo IPv6 se especifica con la plataforma de Cloud para permitirnos usarla como jumpbox en la instancia de GUA solo IPv6. Ejecuta los siguientes comandos en Cloud Shell:
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
Configuración y acceso inicial a la instancia
Conéctate por SSH a la instancia de ULA, que usará IAP de forma predeterminada. Usa el siguiente comando en Cloud Shell para establecer una conexión SSH a la instancia de ULA:
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
También usaremos la instancia de ULA como jumpbox para la instancia de GUA (porque IAP no funciona con instancias de GUA y las VMs de Cloud Shell no pueden acceder a destinos IPv6).
Aún dentro del shell de la instancia de ULA. Intenta aplicar SSH a la instancia de la GUA con el siguiente comando de gcloud.
La primera vez que ejecutes un comando SSH dentro de una instancia, se te pedirá que configures un par de claves SSH. Sigue presionando Intro hasta que se cree la clave y se ejecute el comando SSH. Esto creará un nuevo par de claves sin frase de contraseña.
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]-----+
Si se ejecuta correctamente, el comando SSH se completará y te conectarás a la instancia de GUA a través de 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. Examina las instancias que solo admiten IPv6.
Examinemos ambas instancias solo con IPv6 a través de SSH y analicemos sus tablas de enrutamiento.
Examina la instancia de GUA
Establece una conexión SSH a "gua-instance" primero a través de "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$ gcloud compute ssh gua-instance
Veamos la tabla de enrutamiento de IPv6 de la instancia con el siguiente comando:
<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
Observamos tres entradas en la tabla de enrutamiento.
- Una ruta /65 para la subred de GUA a la que pertenece la instancia con un siguiente salto derivado que usa una dirección local de vínculo para la puerta de enlace predeterminada. Recuerda que el /65 superior está reservado para los balanceadores de cargas de red de transferencia de IPv6.
- Una ruta /64 integrada para el prefijo unicast local de vínculo fe80::/64
- Una ruta predeterminada que apunta a la dirección local del vínculo de la puerta de enlace predeterminada de la subred
Veamos la tabla de enrutamiento IPv4 con este comando
<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
¿Te sorprende? De hecho, mantenemos una tabla de enrutamiento IPv4 en instancias solo IPv6 estrictamente para permitir el acceso al servidor de metadatos de Compute (169.254.169.154), ya que sigue siendo un extremo solo IPv4.
Dado que la instancia adopta la IP 169.254.1.2 cuando es una instancia solo de IPv6. Esta IP no se puede enrutar a ningún lugar, excepto al servidor de metadatos de Compute, por lo que la instancia está aislada de todas las redes IPv4.
Pruebas de cURL
Probemos la conectividad real a sitios web solo para IPv4 y solo para IPv6 con curl.
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
<username>@gua-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
A continuación, se muestra un ejemplo de resultado.
<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
Como se esperaba, no hay accesibilidad a un extremo de Internet IPv4 desde una instancia solo IPv6. Sin el aprovisionamiento de DNS64 y NAT64, la instancia solo IPv6 no tiene una ruta a un destino IPv4. La accesibilidad a un destino IPv6 funciona normalmente, ya que la instancia tiene una dirección IPv6 de GUA.
Examina la instancia de ULA
Establece una conexión SSH a la instancia "ula-instance" (usa IAP de forma predeterminada).
gcloud compute ssh ula-instance --project $projectname --zone $zonename
Veamos la tabla de enrutamiento de IPv6 de la instancia con el siguiente comando:
<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
Observamos tres entradas en la tabla de enrutamiento, similares a la instancia de GUA, con la excepción de que la máscara es /64 en lugar de /65. Además, la ruta de subred pertenece a un rango de ULA. (en el agregado fd20::/20)
Veamos la tabla de enrutamiento IPv4 con este comando
<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
Lo que muestra una situación similar a la de la instancia de GUA.
Pruebas de cURL
Repetir las pruebas de conectividad a sitios web solo para IPv4 y solo para IPv6 con curl
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv --connect-timeout 10 v4.ipv6test.app
A continuación, se muestra un ejemplo de resultado.
<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
En el caso de la instancia de ULA, no hay accesibilidad a ambos extremos de Internet, ya que, para el extremo IPv6, no podemos usar una dirección de ULA para comunicarnos, y la instancia no tiene accesibilidad a IPv4 como instancia solo IPv6.
6. Habilita NAT64 y DNS64
Configura los servicios administrados de DNS64 y NAT64 para tu VPC.
DNS64
Habilita la política del servidor DNS64 para tu VPC . Esto le indica al agente de resolución de DNS de la VPC que sintetice registros AAAA para las respuestas solo A. Ejecuta los siguientes comandos en Cloud Shell:
gcloud beta dns policies create allow-dns64 \
--description="Enable DNS64 Policy" \
--networks=ipv6-only-vpc \
--enable-dns64-all-queries \
--project $projectname
NAT64
Crea un Cloud Router, que es necesario para Cloud NAT . Luego, crea una puerta de enlace de Cloud NAT configurada para NAT64, habilítala para todos los rangos de IP de subred solo IPv6 y asigna automáticamente IPs externas. Ejecuta los siguientes comandos en Cloud Shell:
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. Prueba NAT64 y DNS64
Ahora, probemos la configuración de NAT64 y DNS64 desde las instancias solo para IPv6, comenzando con la instancia de GUA y, luego, con la instancia de ULA.
Prueba de DNS64/NAT64 desde una instancia de GUA
Establece una conexión SSH a "gua-instance" primero a través de "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$ gcloud compute ssh gua-instance
Pruebas de DNS
Prueba la resolución de DNS de un sitio web solo para IPv6 (p.ej., v6.ipv6test.app, pero cualquier sitio web solo para IPv6 debería arrojar un resultado similar).
<username>@gua-instance:~$ host -t AAAA v6.ipv6test.app
<username>@gua-instance:~$ host -t A v6.ipv6test.app
Esperamos que solo se muestren respuestas AAAA de IPv6.
Ejemplo de resultado:
<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
Prueba la resolución de DNS de un sitio web solo para IPv4 (p.ej., v4.ipv6test.app) . Se espera un registro A (el IPv4 original) y un registro AAAA sintetizado por DNS64 con el prefijo conocido 64:ff9b::/96 .
<username>@gua-instance:~$ host -t AAAA v4.ipv6test.app
<username>@gua-instance:~$ host -t A v4.ipv6test.app
Ejemplo de resultado:
<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
En el ejemplo anterior, la dirección IPv4 (54.192.51.38) en decimal se traduciría a (36 c0 33 26) en hexadecimal, por lo que esperaríamos que la respuesta para el registro AAAA sea (64:ff9b::36c0:3326), que coincide con una de las respuestas AAAA que recibimos.
Pruebas de cURL
Probemos la conectividad real a los mismos extremos solo para IPv4 y solo para IPv6 con curl a través de IPv6.
<username>@gua-instance:~$ curl -vv -6 v6.ipv6test.app
<username>@gua-instance:~$ curl -vv -6 v4.ipv6test.app
A continuación, se muestra un ejemplo de resultado.
<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>
##
Ambos comandos curl se ejecutan correctamente. Observa cómo fue posible conectarse a un sitio web solo IPv4 a través de IPv6 gracias a que NAT64 y DNS64 trabajaron en conjunto para habilitar la conectividad correctamente.
Verificar las IPs de origen
Usemos un servicio de reflexión de IP para verificar la IP de origen que observó el destino .
<username>@gua-instance:~$ curl -6 v4.ipv6test.app
<username>@gua-instance:~$ curl -6 v6.ipv6test.app
Ejemplo de resultado
<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::
La dirección IPv6 informada debe coincidir con la dirección IPv6 de la instancia . Esta dirección debe coincidir con el resultado del comando "ip -6 address" en la instancia. Por ejemplo:
<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
Sin embargo, la dirección IPv4 informada debe coincidir con la dirección IP externa de la puerta de enlace de Cloud NAT, ya que realiza la función de NAT64 antes de salir a Internet. Esto se puede verificar ejecutando este comando de gcloud en Cloud Shell
gcloud compute routers get-nat-ip-info \
nat64-router \
--region=$regionname
Ejemplo de resultado
result:
- natIpInfoMappings:
- mode: AUTO
natIp: 34.47.60.91
usage: IN_USE
natName: nat64-natgw
Ten en cuenta que la "natIp" que se informa en el resultado coincide con el resultado que se recibe del sitio web de reflexión de IP.
Prueba de DNS64/NAT64 desde una instancia de ULA
Primero, establece una conexión SSH a la instancia de ULA "ula-instance".
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
Pruebas de DNS
Prueba la resolución de DNS de un sitio web solo para IPv6 (p.ej., v6.ipv6test.app, pero cualquier sitio web solo para IPv6 debería arrojar un resultado similar).
<username>@ula-instance:~$ host -t AAAA v6.ipv6test.app
<username>@ula-instance:~$ host -t A v6.ipv6test.app
Esperamos que solo se muestren respuestas AAAA de IPv6.
Ejemplo de resultado:
<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
Prueba la resolución de DNS de un sitio web solo para IPv4 (p.ej., v4.ipv6test.app) . Se espera un registro A (el IPv4 original) y un registro AAAA sintetizado por DNS64 con el prefijo conocido 64:ff9b::/96 .
<username>@ula-instance:~$ host -t AAAA v4.ipv6test.app
<username>@ula-instance:~$ host -t A v4.ipv6test.app
Ejemplo de resultado:
<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
En el ejemplo anterior, la dirección IPv4 (54.192.51.38) en decimal se traduciría a (36 c0 33 26) en hexadecimal, por lo que esperaríamos que la respuesta para el registro AAAA sea (64:ff9b::36c0:3326), que coincide con una de las respuestas AAAA que recibimos.
Pruebas de cURL
Probemos la conectividad real a los mismos extremos solo para IPv4 y solo para IPv6 con curl.
Como punto de partida, demostremos que no es posible acceder a través de IPv4, ya que la instancia es solo de 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
Si bien ambos comandos curl fallarán. Fallarán por diferentes motivos. A continuación, se muestra un ejemplo de resultado.
<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
El comando curl de IPv4 a un extremo solo de IPv6 falla porque falla la resolución de DNS para el registro A (como se demostró durante las pruebas de DNS). El comando curl de IPv4 a un extremo solo de IPv4 falla porque una instancia solo de IPv6 no tiene accesibilidad a ninguna dirección IPv4, y se produce un tiempo de espera debido a eso.
Ahora probemos la accesibilidad a través de IPv6.
<username>@ula-instance:~$ curl -vv -6 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv -6 v4.ipv6test.app
A continuación, se muestra un ejemplo de resultado.
<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>
##
Si bien la solicitud curl al sitio web solo para IPv6 falla porque las subredes de ULA no tienen accesibilidad directa a Internet. La operación curl en el sitio web solo IPv4 se realiza correctamente porque DNS64 y NAT64 funcionan de la misma manera para las instancias de GUA y ULA. El único requisito es que la instancia sea solo IPv6.
Prueba de DNS64/NAT64 desde una instancia de ULA de doble pila
Primero, establece una conexión SSH a la instancia de ULA de doble pila "dualstack-ula-instance". Debemos usar la marca "–tunnel-through-iap" para forzar a gcloud a usar la dirección IPv4 para IAP.
gcloud compute ssh dualstack-ula-instance --project $projectname --zone $zonename --tunnel-through-iap
<username>@dualstack-ula-instance:~$
Ahora probemos DNS64 con la utilidad "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
Observa cómo el sitio web solo IPv4 ahora devuelve solo direcciones IPv4 y ya no las respuestas sintéticas de DNS64. Esto se debe a que DNS64 solo se aplica a las instancias que solo admiten IPv6 y no se evalúa para las instancias de pila doble.
Para evitar la necesidad de DNS64, agreguemos una entrada al archivo /etc/hosts para probar si NAT64 funciona. Ejecuta el siguiente comando dentro de la instancia de doble pila:
<username>@dualstack-ula-instance:~$ echo '64:ff9b::36c0:3326 v4.ipv6test.app' | sudo tee -a /etc/hosts
Luego, usemos curl para probar el acceso al sitio web de IPv4 a través de IPv6.
<username>@dualstack-ula-instance:~$ curl -vv -6 --connect-timeout 10 v4.ipv6test.app
Este es un ejemplo del resultado del comando anterior:
<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
El comando curl debería agotar el tiempo de espera porque, al igual que DNS64, NAT64 también requiere que la instancia sea solo IPv6 para aplicarse.
Para confirmar que NAT64 no se aplica a la instancia de pila doble, usemos el comando "get-nat-mapping" para enumerar todas las asignaciones de puertos que aplica la puerta de enlace de NAT. Ejecuta los siguientes comandos en Cloud Shell:
gcloud compute routers get-nat-mapping-info \
nat64-router --region $regionname \
--project $projectname
Deberías obtener un resultado similar al siguiente fragmento:
---
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
El resultado de NAT muestra que la puerta de enlace NAT64 solo asignó puertos para las instancias de GUA y ULA solo IPv6, pero no para la instancia de pila doble.
8. Limpia
Limpia Cloud Router
En Cloud Shell, haz lo siguiente:
gcloud compute routers delete nat64-router \
--region $regionname \
--project $projectname --quiet
Desvincula y limpia la política de DNS
En Cloud Shell, haz lo siguiente:
gcloud beta dns policies update allow-dns64 \
--networks="" \
--project $projectname
gcloud beta dns policies delete allow-dns64 \
--project $projectname --quiet
Limpia instancias
Dentro de Cloud Shell, haz lo siguiente: (ten en cuenta que se usa gcloud beta para permitirnos usar la marca no-graceful-shutdown para una operación de eliminación de instancias más rápida)
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
Limpia las subredes
En Cloud Shell, haz lo siguiente:
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
Cómo limpiar reglas de firewall
En Cloud Shell, haz lo siguiente:
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
Limpia la VPC
En Cloud Shell, haz lo siguiente:
gcloud compute networks delete ipv6-only-vpc \
--project=$projectname \
--quiet
Limpia los permisos de IAM y la cuenta de servicio
En Cloud Shell, haz lo siguiente:
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. Felicitaciones
Usaste correctamente NAT64 y DNS64 para permitir que las instancias solo IPv6 lleguen a destinos solo IPv4 en Internet.
Próximos pasos
Consulta algunos codelabs sobre los siguientes temas:
- Accede a las APIs de Google desde hosts locales con direcciones IPv6
- Opciones de direccionamiento IP IPv4 e IPv6
- Uso de la instancia de próximo salto, la dirección de próximo salto y la puerta de enlace de próximo salto de las rutas estáticas IPv6