1. 소개
IPv6으로 마이그레이션할 때의 주요 과제 중 하나는 IPv4 전용 엔드포인트 및 네트워크에 대한 연결 가능성을 유지하는 것입니다. 이 문제를 해결하는 주요 기술은 DNS64 (RFC6147에 정의됨)를 사용하여 클라이언트의 A 레코드를 AAAA 레코드로 변환하는 것입니다. 그런 다음 NAT64 (RFC6146에 정의됨)와 결합하여 특수 형식의 IPv6 주소를 IPv4로 변환합니다. 여기서 IPv4 주소는 특수 IPv6 주소에 삽입됩니다. 이 Codelab에서는 Google Cloud Platform (GCP) Virtual Private Cloud (VPC)에서 두 기능을 모두 구성하는 방법을 안내합니다. 함께 구성된 경우 GCP NAT64 및 DNS64를 사용하면 IPv6 전용 인스턴스가 인터넷의 IPv4 전용 서버와 통신할 수 있습니다.
이 실습에서는 IPv6 전용 GUA (글로벌 유니캐스트 주소), IPv6 전용 ULA (고유한 로컬 주소), 이중 스택 ULA 등 다양한 유형의 IPv6 서브넷과 인스턴스가 있는 VPC를 설정합니다. 그런 다음 Google Cloud의 관리형 DNS64 및 NAT64 서비스를 구성하고 테스트하여 IPv4 전용 웹사이트에 액세스합니다.
2. 학습할 내용
- IPv6 전용 서브넷 및 인스턴스를 만드는 방법
- VPC에 Google Cloud의 관리형 DNS64 서비스를 사용 설정하는 방법
- NAT64용으로 구성된 Google Cloud NAT 게이트웨이를 만드는 방법
- IPv6 전용 인스턴스에서 IPv4 전용 대상으로 DNS64 변환을 테스트하는 방법
- 단일 스택 인스턴스와 이중 스택 인스턴스 간의 DNS64 및 NAT64 동작 차이점
- NAT64용 NAT 게이트웨이를 구성하는 방법
- IPv6 전용 인스턴스에서 IPv4 전용 대상으로 NAT64 연결을 테스트하는 방법
3. 시작하기 전에
코드랩을 지원하도록 프로젝트 업데이트
이 Codelab에서는 Cloud Shell에서 gcloud 구성 구현을 지원하기 위해 $변수를 사용합니다.
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 서브넷 유형과 상호작용하는 방식을 보여주기 위해 GUA와 ULA 버전 모두에 IPv6 서브넷이 있는 단일 VPC를 만듭니다. 또한 DNS64 및 NAT64가 이중 스택 VM에 적용되지 않는 방법을 보여주기 위해 이중 스택 서브넷 (ULA 주소 지정 사용)을 만듭니다.
그런 다음 DNS64 및 NAT64를 구성하고 인터넷의 IPv6 및 IPv4 대상에 대한 연결을 테스트합니다.
4. 준비 단계
먼저 Google Cloud 프로젝트에서 필요한 서비스 계정, IAM, 네트워크 인프라, 인스턴스를 설정합니다.
서비스 계정 및 IAM 바인딩 만들기
인스턴스가 gcloud를 사용하여 서로 SSH할 수 있도록 새 서비스 계정을 만드는 것부터 시작합니다. IAP를 사용하여 GUA IPv6 전용 인스턴스에 액세스할 수 없고 Cloud Shell에서는 아직 직접 IPv6 액세스를 허용하지 않으므로 이 기능이 필요합니다. 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
VPC를 만들고 ULA 사용 설정
Cloud Shell에서 다음 명령어를 실행하여 커스텀 서브넷 모드와 ULA 내부 IPv6가 사용 설정된 VPC 네트워크를 만듭니다.
gcloud compute networks create ipv6-only-vpc \
--project=$projectname \
--subnet-mode=custom \
--mtu=1500 --bgp-routing-mode=global \
--enable-ula-internal-ipv6
방화벽 규칙 만들기
SSH 액세스를 허용하는 방화벽 규칙을 만듭니다. 한 규칙은 전체 ULA 범위 (fd20::/20)에서 SSH를 허용합니다. 두 개의 규칙은 IAP 사전 정의 IPv6 및 IPv4 범위 (각각 2600:2d00:1:7::/64, 35.235.240.0/20)에서 들어오는 트래픽을 허용합니다.
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
서브넷 만들기
GUA v6 전용 서브넷, ULA v6 전용 서브넷, 이중 스택 ULA 서브넷을 만듭니다. 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
인스턴스 만들기
방금 만든 각 서브넷에 인스턴스를 만듭니다. IPv6 전용 ULA 인스턴스는 GUA IPv6 전용 인스턴스로 연결하는 점프박스로 사용할 수 있도록 cloud-platform으로 지정됩니다. 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
초기 인스턴스 액세스 및 설정
기본적으로 IAP를 사용하는 ULA 인스턴스에 SSH로 연결합니다. cloudshell에서 다음 명령어를 사용하여 ULA 인스턴스에 SSH로 연결합니다.
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
또한 ULA 인스턴스를 GUA 인스턴스의 점프박스로 사용합니다 (IAP는 GUA 인스턴스와 작동하지 않고 Cloudshell VM은 IPv6 대상에 액세스할 수 없기 때문).
ULA 인스턴스 셸 내에 있는 동안 다음 gcloud 명령어를 사용하여 GUA 인스턴스에 SSH로 연결해 보세요.
인스턴스 내에서 SSH 명령어를 처음 실행하면 SSH 키 쌍을 설정하라는 메시지가 표시됩니다. 키가 생성되고 SSH 명령어가 실행될 때까지 Enter 키를 계속 누릅니다. 그러면 암호가 없는 새 키 쌍이 생성됩니다.
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 전용 인스턴스를 검사합니다.
SSH를 통해 IPv6 전용 인스턴스에 연결하고 라우팅 테이블을 검사해 보겠습니다.
GUA 인스턴스 검사
먼저 'ula-instance' 인스턴스를 통해 'gua-instance'에 SSH로 연결합니다.
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
라우팅 테이블에 세 개의 항목이 있습니다.
- 인스턴스가 속한 GUA 서브넷의 /65 경로(기본 게이트웨이의 링크-로컬 주소를 사용하여 파생된 다음 홉 포함) 상위 /65는 IPv6 패스 스루 네트워크 부하 분산기용으로 예약되어 있습니다.
- 링크 로컬 유니캐스트 접두사 fe80::/64의 내장 /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
놀라운가요? 실제로 IPv6 전용 인스턴스에서는 여전히 IPv4 전용 엔드포인트인 Compute 메타데이터 서버 (169.254.169.154)에 대한 액세스를 허용하기 위해 IPv4 라우팅 테이블을 유지합니다.
인스턴스가 IPv6 전용 인스턴스인 경우 IP 169.254.1.2를 사용하기 때문입니다. 이 IP는 Compute 메타데이터 서버로만 라우팅할 수 있으므로 인스턴스는 모든 IPv4 네트워크에서 효과적으로 격리됩니다.
Curl 테스트
curl을 사용하여 v4 전용 및 v6 전용 웹사이트에 대한 실제 연결을 테스트해 보겠습니다.
<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 대상 경로가 없습니다. 인스턴스에 GUA IPv6 주소가 있으므로 IPv6 대상에 대한 연결 가능성은 정상적으로 작동합니다.
ULA 인스턴스 검사
'ula-instance' 인스턴스에 SSH로 연결합니다 (기본적으로 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
마스크가 /65가 아닌 /64인 것을 제외하고 GUA 인스턴스와 유사한 라우팅 테이블에 세 개의 항목이 있습니다. 서브넷 경로는 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 인스턴스와 유사한 상황을 보여줍니다.
Curl 테스트
curl을 사용하여 v4 전용 및 v6 전용 웹사이트에 대한 연결 테스트를 반복합니다.
<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 사용 설정
VPC의 관리형 DNS64 및 NAT64 서비스를 구성합니다.
DNS64
VPC에 DNS64 서버 정책을 사용 설정합니다 . 이렇게 하면 VPC의 DNS 리졸버가 A 전용 응답에 대한 AAAA 레코드를 합성합니다. Cloud Shell에서 다음 명령어를 실행합니다.
gcloud beta dns policies create allow-dns64 \
--description="Enable DNS64 Policy" \
--networks=ipv6-only-vpc \
--enable-dns64-all-queries \
--project $projectname
NAT64
Cloud NAT에 필요한 Cloud Router를 만듭니다 . 그런 다음 NAT64용으로 구성된 Cloud NAT 게이트웨이를 만들어 모든 IPv6 전용 서브넷 IP 범위에 대해 사용 설정하고 외부 IP를 자동 할당합니다. 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. NAT64 및 DNS64 테스트
이제 IPv6 전용 인스턴스에서 NAT64 및 DNS64 구성을 테스트해 보겠습니다. 먼저 GUA 인스턴스부터 시작하고 ULA 인스턴스로 이어집니다.
GUA 인스턴스에서 DNS64/NAT64 테스트
먼저 'ula-instance' 인스턴스를 통해 'gua-instance'에 SSH로 연결합니다.
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$ gcloud compute ssh gua-instance
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
IPv4 전용 웹사이트 (예: v4.ipv6test.app)의 DNS 변환을 테스트합니다. A 레코드 (원래 IPv4)와 잘 알려진 프리픽스 64:ff9b::/96을 사용하여 DNS64로 합성된 AAAA 레코드가 모두 표시됩니다 .
<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
위 예에서 10진수의 IPv4 주소 (54.192.51.38)는 16진수 (36 c0 33 26)로 변환되므로 AAAA 레코드의 답변은 (64:ff9b::36c0:3326)이 될 것으로 예상되며, 이는 수신된 AAAA 답변 중 하나와 일치합니다.
Curl 테스트
IPv6를 통해 curl을 사용하여 동일한 v4 전용 및 v6 전용 엔드포인트에 대한 실제 연결을 테스트해 보겠습니다.
<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 명령어 모두 성공합니다. NAT64와 DNS64가 함께 작동하여 연결을 성공적으로 사용 설정했기 때문에 IPv6를 통해 IPv4 전용 웹사이트에 연결할 수 있었습니다.
소스 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
하지만 인터넷으로 나가기 전에 NAT64 기능을 실행하므로 보고된 IPv4 주소는 Cloud NAT 게이트웨이의 외부 IP 주소와 일치해야 합니다. 이는 Cloud Shell에서 다음 gcloud 명령어를 실행하여 확인할 수 있습니다.
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 리플렉션 웹사이트에서 수신된 출력과 일치합니다.
ULA 인스턴스에서 DNS64/NAT64 테스트
먼저 ULA 인스턴스 'ula-instance'에 SSH를 설정합니다.
gcloud compute ssh ula-instance --project $projectname --zone $zonename
<username>@ula-instance:~$
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
IPv4 전용 웹사이트 (예: v4.ipv6test.app)의 DNS 변환을 테스트합니다. A 레코드 (원래 IPv4)와 잘 알려진 프리픽스 64:ff9b::/96을 사용하여 DNS64로 합성된 AAAA 레코드가 모두 표시됩니다 .
<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
위 예에서 10진수의 IPv4 주소 (54.192.51.38)는 16진수 (36 c0 33 26)로 변환되므로 AAAA 레코드의 답변은 (64:ff9b::36c0:3326)이 될 것으로 예상되며, 이는 수신된 AAAA 답변 중 하나와 일치합니다.
Curl 테스트
curl을 사용하여 동일한 v4 전용 및 v6 전용 엔드포인트에 대한 실제 연결을 테스트해 보겠습니다.
시작점으로 인스턴스가 IPv6 전용 인스턴스이므로 IPv4를 통한 연결이 불가능함을 보여줍니다.
<username>@ula-instance:~$ curl -vv -4 --connect-timeout 10 v6.ipv6test.app
<username>@ula-instance:~$ curl -vv -4 --connect-timeout 10 v4.ipv6test.app
두 컬 모두 실패합니다. 다양한 이유로 실패합니다. 아래는 샘플 출력입니다.
<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
A 레코드의 DNS 변환이 실패하므로 (DNS 테스트 중에 설명됨) IPv6 전용 엔드포인트에 대한 IPv4 curl이 실패합니다. IPv6 전용 인스턴스는 IPv4 주소에 연결할 수 없으므로 IPv4 전용 엔드포인트에 대한 IPv4 curl이 실패하고 이로 인해 타임아웃이 발생합니다.
이제 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>
##
ULA 서브넷은 인터넷에 직접 연결할 수 없으므로 IPv6 전용 웹사이트에 대한 curl은 실패합니다. DNS64와 NAT64는 GUA 및 ULA 인스턴스에서 동일한 방식으로 작동하므로 IPv4 전용 웹사이트에 대한 curl이 성공합니다. 유일한 요구사항은 인스턴스가 IPv6 전용이어야 한다는 것입니다.
듀얼 스택 ULA 인스턴스에서 DNS64/NAT64 테스트
먼저 이중 스택 ULA 인스턴스 'dualstack-ula-instance'에 SSH를 설정합니다. gcloud가 IAP에 IPv4 주소를 사용하도록 강제하려면 '–tunnel-through-iap' 플래그를 사용해야 합니다.
gcloud compute ssh dualstack-ula-instance --project $projectname --zone $zonename --tunnel-through-iap
<username>@dualstack-ula-instance:~$
이제 'host' 유틸리티를 사용하여 DNS64를 테스트해 보겠습니다.
<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 전용 웹사이트가 합성 DNS64 응답이 아닌 IPv4 주소만 반환하는 것을 확인할 수 있습니다. DNS64는 IPv6 전용 인스턴스에만 적용되며 이중 스택 인스턴스에는 적용되지 않기 때문입니다.
DNS64의 필요성을 우회하려면 /etc/hosts 파일에 항목을 추가하여 NAT64가 작동하는지 테스트합니다. 듀얼 스택 인스턴스 내에서 다음 명령어를 실행합니다.
<username>@dualstack-ula-instance:~$ echo '64:ff9b::36c0:3326 v4.ipv6test.app' | sudo tee -a /etc/hosts
그런 다음 curl을 사용하여 IPv6를 통해 ipv4 웹사이트에 연결되는지 테스트합니다.
<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
NAT64도 적용하려면 인스턴스가 IPv6 전용이어야 하므로 DNS64와 마찬가지로 curl이 타임아웃되어야 합니다.
NAT64가 실제로 이중 스택 인스턴스에 적용되지 않는지 확인하려면 'get-nat-mapping' 명령어를 사용하여 NAT 게이트웨이가 적용하는 모든 포트 매핑을 나열합니다. Cloud Shell에서 다음 명령어를 실행합니다.
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 게이트웨이가 IPv6 전용 GUA 및 ULA 인스턴스에만 포트를 할당하고 이중 스택 인스턴스에는 할당하지 않은 것으로 표시됩니다.
8. 삭제
Cloud Router 정리
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 내에서 다음을 실행합니다. (참고로, 더 빠른 인스턴스 삭제 작업을 위해 no-graceful-shutdown 플래그를 사용할 수 있도록 gcloud 베타가 사용됩니다.)
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 전용 대상에 연결되도록 했습니다.
다음 단계
다음 Codelab을 확인하세요.
- IPv6 주소를 사용하여 온프레미스 호스트에서 Google API에 액세스
- IP 주소 지정 옵션 IPv4 및 IPv6
- IPv6 정적 경로 다음 홉 인스턴스, 다음 홉 주소, 다음 홉 게이트웨이 사용