
VPC origin がデュアルスタックをサポート。CloudFrontのオリジンリクエストが ALB まで IPv6 で届くか試してみた
はじめに
2026年10月15日、CloudFront の VPC origin でデュアルスタックがサポートされました。
このデュアルスタック対応により、CloudFront からプライベートサブネット上の ALB、NLB、EC2 まで、エンドツーエンドで IPv6 を利用できるようになりました。従来、この区間の通信は IPv4 のみでした。
本記事では、東京リージョンで internal ALB を VPC origin に設定し、ALB のアクセスログから、CloudFront の IPv6 アドレスが接続元として記録されることを確認しました。
構成
IPv6 を有効にした VPC にプライベートサブネットを 2 つ作り、IPv6 のデフォルトルート(::/0)は Egress-only IGW に向けました。サブネット内には internal ALB(デュアルスタック、HTTP:80 で固定応答 200)を置き、ALB のアクセスログを CloudWatch Logs へ配信します。
ALB の SG は、IPv6 のプレフィックスリスト com.amazonaws.global.ipv6.cloudfront.origin-facing から TCP 80 だけを許可しました。
VPC origin の作成には、通常の IGW を VPC にアタッチし、プライベートサブネットに IPv4 と IPv6 の空きアドレスを 1 つ以上確保する必要があります。空きアドレスは、CloudFront が作成するサービス管理の ENI に使用されます。
通常の IGW 宛てのルートは作成せず、IPv6 のデフォルトルートは Egress-only IGW に向けます。
ALB のアクセスログで IPv6 を確認する
CloudFront ディストリビューションのドメイン名へリクエストすると、ALB の固定応答が 200 で返りました。
$ curl -sS -i https://dxxxxxxxxxxxxx.cloudfront.net/
HTTP/2 200
x-cache: Miss from cloudfront
hello from internal dualstack ALB
ALB のアクセスログ(CloudWatch Logs)には、このリクエストが次のレコードで残りました。
{
"time": "2026-10-15T20:24:07.380120Z",
"user_agent": "Amazon CloudFront",
"client_port": "2001:db8:17bd:2f73:3ceb:b969:b646:3200:25216",
"elb_status_code": "200",
"ip_address": "192.168.28.87"
}
client_port は接続元アドレスとポートです。アドレスは例示用の文書用アドレスに置き換えています。確認した 4 件のアクセスログでは、置き換え前の client_port の IP アドレス部はいずれも IPv6 で、user_agent は Amazon CloudFront、elb_status_code は 200 でした。
まとめ
デュアルスタックの VPC origin を使用すると、IPv6 のデフォルトルートが Egress-only IGW を指すプライベートサブネット上の internal ALB に対し、CloudFront から IPv6 で接続できることを確認しました。
エンドツーエンドで IPv6 通信を利用するネットワークを構築したい場合や、外部公開の窓口を CloudFront に集約したい場合に有用です。オリジンをプライベートサブネットに配置したまま CloudFront 経由のアクセスに限定できるため、セキュリティグループの設定ミスなどによる直接アクセスのリスクも抑えられます。
CloudFormation テンプレート
検証に使用したテンプレートとスタック作成コマンドは次のとおりです。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: VPC origin dualstack verification (IPv6 VPC, internal dualstack ALB, CloudFront VPC origin, and ALB access logs)
Parameters:
ProjectName:
Type: String
Default: vpco-ds
CloudFrontIpv6PrefixListId:
Type: String
Default: pl-0f28cd4a128e7b13a
Description: com.amazonaws.global.ipv6.cloudfront.origin-facing
CloudFrontIpv4PrefixListId:
Type: String
Default: ''
Description: com.amazonaws.global.cloudfront.origin-facing (empty = do not allow IPv4)
Conditions:
AllowIpv4: !Not [!Equals [!Ref CloudFrontIpv4PrefixListId, '']]
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 192.168.0.0/18
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Ref ProjectName
IPv6CidrBlock:
Type: AWS::EC2::VPCCidrBlock
Properties:
VpcId: !Ref VPC
AmazonProvidedIpv6CidrBlock: true
PrivateSubnet1:
Type: AWS::EC2::Subnet
DependsOn: IPv6CidrBlock
Properties:
VpcId: !Ref VPC
CidrBlock: 192.168.0.0/20
AvailabilityZone: !Select [0, !GetAZs '']
Ipv6CidrBlock: !Select [0, !Cidr [!Select [0, !GetAtt VPC.Ipv6CidrBlocks], 2, 64]]
AssignIpv6AddressOnCreation: true
Tags:
- Key: Name
Value: !Sub '${ProjectName}-private-1'
PrivateSubnet2:
Type: AWS::EC2::Subnet
DependsOn: IPv6CidrBlock
Properties:
VpcId: !Ref VPC
CidrBlock: 192.168.16.0/20
AvailabilityZone: !Select [1, !GetAZs '']
Ipv6CidrBlock: !Select [1, !Cidr [!Select [0, !GetAtt VPC.Ipv6CidrBlocks], 2, 64]]
AssignIpv6AddressOnCreation: true
Tags:
- Key: Name
Value: !Sub '${ProjectName}-private-2'
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub '${ProjectName}-igw'
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
EgressOnlyIGW:
Type: AWS::EC2::EgressOnlyInternetGateway
Properties:
VpcId: !Ref VPC
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub '${ProjectName}-private-rt'
PrivateRouteIPv6:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationIpv6CidrBlock: '::/0'
EgressOnlyInternetGatewayId: !Ref EgressOnlyIGW
PrivateSubnet1Association:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet2Association:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable
AlbSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow CloudFront origin-facing prefix lists to the internal ALB
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourcePrefixListId: !Ref CloudFrontIpv6PrefixListId
Description: CloudFront origin-facing (IPv6)
Tags:
- Key: Name
Value: !Sub '${ProjectName}-alb-sg'
AlbSecurityGroupIngressIpv4:
Type: AWS::EC2::SecurityGroupIngress
Condition: AllowIpv4
Properties:
GroupId: !Ref AlbSecurityGroup
IpProtocol: tcp
FromPort: 80
ToPort: 80
SourcePrefixListId: !Ref CloudFrontIpv4PrefixListId
Description: CloudFront origin-facing (IPv4)
Alb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub '${ProjectName}-alb'
Scheme: internal
Type: application
IpAddressType: dualstack
Subnets:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroups:
- !Ref AlbSecurityGroup
AlbListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Port: 80
Protocol: HTTP
DefaultActions:
- Type: fixed-response
FixedResponseConfig:
StatusCode: '200'
ContentType: text/plain
MessageBody: hello from internal dualstack ALB
AccessLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '/aws/vendedlogs/${ProjectName}-alb-access'
RetentionInDays: 1
AccessLogSource:
Type: AWS::Logs::DeliverySource
Properties:
Name: !Sub '${ProjectName}-alb-access'
LogType: ALB_ACCESS_LOGS
ResourceArn: !Ref Alb
CwlDestination:
Type: AWS::Logs::DeliveryDestination
Properties:
Name: !Sub '${ProjectName}-cwl'
DeliveryDestinationType: CWL
OutputFormat: json
DestinationResourceArn: !GetAtt AccessLogGroup.Arn
AccessLogDelivery:
Type: AWS::Logs::Delivery
Properties:
DeliverySourceName: !Ref AccessLogSource
DeliveryDestinationArn: !GetAtt CwlDestination.Arn
VpcOrigin:
Type: AWS::CloudFront::VpcOrigin
DependsOn: InternetGatewayAttachment
Properties:
VpcOriginEndpointConfig:
Name: !Sub '${ProjectName}-origin'
Arn: !Ref Alb
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: http-only
IpAddressType: dualstack
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: !Sub '${ProjectName} VPC origin dualstack verification'
Enabled: true
HttpVersion: http2and3
IPV6Enabled: true
Origins:
- Id: VpcOriginAlb
DomainName: !GetAtt Alb.DNSName
VpcOriginConfig:
VpcOriginId: !Ref VpcOrigin
DefaultCacheBehavior:
TargetOriginId: VpcOriginAlb
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # Managed-CachingDisabled
Compress: true
Outputs:
DistributionId:
Value: !Ref Distribution
DistributionDomainName:
Value: !GetAtt Distribution.DomainName
VpcOriginId:
Value: !Ref VpcOrigin
LogGroupName:
Value: !Ref AccessLogGroup
:::
template.yaml として保存し、スタックを作成します。
aws cloudformation create-stack --stack-name vpco-ds --template-body file://template.yaml
aws cloudformation wait stack-create-complete --stack-name vpco-ds







