[アップデート] インターネット向けApplication Load Balancer (ALB) が IPv6 のみのアドレスタイプをサポートしました

IPv4のクライアントからアクセスが不要な場合に
2024.05.17

デュアルスタックではなく、IPv6のみのALBを作成したい

こんにちは、のんピ(@non____97)です。

皆さんはデュアルスタックではなく、IPv6のみのALBを作成したいなと思ったことはありますか? 私はあります。

以下AWS Blogでも紹介されているとおり、2024/2/1よりパブリックIPv4アドレスへ課金が発生するようになりました。

この影響で不要なパブリックIPv4アドレスを断捨離している方も多いのではないでしょうか。

ただし、なかなか断捨離が難しい要素があります。例えば、ALBです。

従来ALBではアドレスタイプをIPv4かデュアルスタックのどちらかしか選択できませんでした。そのため、インターネット向けALBを作成する際は必ずパブリックIPアドレスが割り当てられていました。

IPv4アドレスをサポートしなくとも良い場面では必要のない課金になってしまいます。

今回のアップデートによりインターネット向けALBがIPv6 のみアドレスタイプをサポートしました。

これにより、IPv4アドレスをサポートする必要がない場面でのコストを抑えることが可能です。

実際に試してみました。

やってみた

検証環境

検証環境は以下のとおりです。

インターネット向けApplication Load Balancer (ALB) が IPv6 のみのアドレスタイプをサポートしました検証環境構成図

HTTPのリスナーを持ったIPv6オンリーのALBを作成します。

IPv6で接続できることが確認できれば良いので、ターゲットは作成せずに固定レスポンスを返すように設定します。

デプロイ

AWS公式ドキュメントでCloudFormationのプロパティを確認するとdualstack-without-public-ipv4の指定が既に設定できそうです。

IpAddressType

Note: Internal load balancers must use the ipv4 IP address type.

[Application Load Balancers] The IP address type. The possible values are ipv4 (for only IPv4 addresses), dualstack (for IPv4 and IPv6 addresses), and dualstack-without-public-ipv4 (for IPv6 only public addresses, with private IPv4 and IPv6 addresses).

[Network Load Balancers] The IP address type. The possible values are ipv4 (for only IPv4 addresses) and dualstack (for IPv4 and IPv6 addresses). You can’t specify dualstack for a load balancer with a UDP or TCP_UDP listener.

[Gateway Load Balancers] The IP address type. The possible values are ipv4 (for only IPv4 addresses) and dualstack (for IPv4 and IPv6 addresses).

Required: No

Type: String

Allowed values: ipv4 | dualstack

Update requires: No interruption

AWS::ElasticLoadBalancingV2::LoadBalancer - AWS CloudFormation

CloudFormationでできるということはAWS CDKでもできます。ということで、AWS CDKでデプロイします。

コードは以下のとおりです。

./lib/ipv6-alb-stack.ts

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";

export class Ipv6AlbStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPC
    const vpc = new cdk.aws_ec2.Vpc(this, "Vpc", {
      natGateways: 0,
      maxAzs: 2,
      ipProtocol: cdk.aws_ec2.IpProtocol.DUAL_STACK,
      subnetConfiguration: [
        {
          name: "Public",
          subnetType: cdk.aws_ec2.SubnetType.PUBLIC,
        },
      ],
    });

    // ALB
    const alb = new cdk.aws_elasticloadbalancingv2.ApplicationLoadBalancer(
      this,
      "Alb",
      {
        vpc,
        internetFacing: true,
        vpcSubnets: vpc.selectSubnets({
          subnetType: cdk.aws_ec2.SubnetType.PUBLIC,
        }),
      }
    );

    // Allow IPv6
    alb.connections.allowFrom(
      cdk.aws_ec2.Peer.anyIpv6(),
      cdk.aws_ec2.Port.HTTP
    );

    // Dualstack without public IPv4
    const cfnAlb = alb.node
      .defaultChild as cdk.aws_elasticloadbalancingv2.CfnLoadBalancer;
    cfnAlb.ipAddressType = "dualstack-without-public-ipv4";

    // Listener
    alb.addListener("ListenerHttp", {
      port: 80,
      protocol: cdk.aws_elasticloadbalancingv2.ApplicationProtocol.HTTP,
      defaultAction:
        cdk.aws_elasticloadbalancingv2.ListenerAction.fixedResponse(200, {
          contentType: "text/plain",
          messageBody: "IPv6 only ALB",
        }),
    });
  }
}

npx cdk deployでデプロイします。

デプロイ後、ALBのDNS名を確認すると、AAAAレコード用のものしかないことが確認できます。

作成されたALBの確認

動作確認

動作確認をしてみます。

まず、名前解決です。

$ dig Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com AAAA

; <<>> DiG 9.10.6 <<>> Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43963
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com. IN AAAA

;; ANSWER SECTION:
ipv6al-alb16-r5xeniwzlu7w-1468736553.us-east-1.elb.amazonaws.com. 60 IN	AAAA 2600:1f18:5527:3a01:79aa:2ef2:5001:27e7
ipv6al-alb16-r5xeniwzlu7w-1468736553.us-east-1.elb.amazonaws.com. 60 IN	AAAA 2600:1f18:5527:3a00:346d:b6fb:491a:800a

;; Query time: 153 msec
;; SERVER: 127.0.2.2#53(127.0.2.2)
;; WHEN: Fri May 17 17:45:46 JST 2024
;; MSG SIZE  rcvd: 213

$ dig Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com A

; <<>> DiG 9.10.6 <<>> Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32684
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com. IN A

;; AUTHORITY SECTION:
us-east-1.elb.amazonaws.com. 60	IN	SOA	ns-1119.awsdns-11.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 60

;; Query time: 40 msec
;; SERVER: 127.0.2.2#53(127.0.2.2)
;; WHEN: Fri May 17 17:46:04 JST 2024
;; MSG SIZE  rcvd: 202

IPv6は名前解決できて、IPv4は名前解決に失敗しましたね。確かにIPv6オンリーです。

ALBのENIを確認しても、パブリックIPv4アドレスは設定されていませんでした。

ENIの確認

次にcurlで接続してみます。

$ curl http://Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com -v
* Host Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com:80 was resolved.
* IPv6: 2600:1f18:5527:3a01:79aa:2ef2:5001:27e7, 2600:1f18:5527:3a00:346d:b6fb:491a:800a
* IPv4: (none)
*   Trying [2600:1f18:5527:3a01:79aa:2ef2:5001:27e7]:80...
* Connected to Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com (2600:1f18:5527:3a01:79aa:2ef2:5001:27e7) port 80
> GET / HTTP/1.1
> Host: Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: awselb/2.0
< Date: Fri, 17 May 2024 09:02:04 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 13
< Connection: keep-alive
<
* Connection #0 to host Ipv6Al-Alb16-R5xeniwZLu7W-1468736553.us-east-1.elb.amazonaws.com left intact
IPv6 only ALB

IPv6で名前解決した結果を元にアクセスし、ALBの固定レスポンスが表示されました。

CloudFrontのオリジンにIPv6オンリーのALBを指定して動作するか

CloudFrontのオリジンにIPv6オンリーのALBを指定できるのかも確認します。

CloudFrontがIPv6をサポートした当時のAWS Blogを確認すると、以下のように「オリジンにはIPv4を使用する」と記載がありました。

各 Amazon CloudFront ディストリビューションごとに IPv6 サポートを有効にすることができます。IPv6 を使用して CloudFront エッジロケーションに接続する閲覧者とネットワークは自動的に IPv6 でコンテンツを取得します。IPv4 を使用して接続する場合は以前のように機能します。オリジンサーバーへの接続には IPv4 を使用します。

IPv6 サポートの更新 – CloudFront、WAF、S3 Transfer Acceleration | Amazon Web Services ブログ

現在もこの制約は変わらないのでしょうか。

3ヶ月前に回答のあったre:Postを確認しても、現状変わりなさそうですが試してみます。

適当にIPv6オンリーなALBをオリジンとするCloudFrontディストリビューションを作成します。

CloudFrontの作成

CloudFrontディストリビューション作成完了後、ディストリビューションドメイン名を確認します。

作成したCloudFrontディストリビューションの確認

こちらの名前にアクセスします。

$ curl http://d11mb8ewrua964.cloudfront.net -v
* Host d11mb8ewrua964.cloudfront.net:80 was resolved.
* IPv6: (none)
* IPv4: 3.165.37.111, 3.165.37.102, 3.165.37.48, 3.165.37.7
*   Trying 3.165.37.111:80...
* Connected to d11mb8ewrua964.cloudfront.net (3.165.37.111) port 80
> GET / HTTP/1.1
> Host: d11mb8ewrua964.cloudfront.net
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 502 Bad Gateway
< Server: CloudFront
< Date: Fri, 17 May 2024 09:13:10 GMT
< Content-Type: text/html
< Content-Length: 960
< Connection: keep-alive
< X-Cache: Error from cloudfront
< Via: 1.1 fa76603d01568e6666e9a0960fb15d40.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: NRT12-P5
< X-Amz-Cf-Id: qnuyWbkslrMdGCyqHKs31-W75arqQEk5oTz9P2DmbvPP6nTXUFNp4Q==
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>502 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
CloudFront wasn't able to resolve the origin domain name.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: qnuyWbkslrMdGCyqHKs31-W75arqQEk5oTz9P2DmbvPP6nTXUFNp4Q==
</PRE>
<ADDRESS>
</ADDRESS>
* Connection #0 to host d11mb8ewrua964.cloudfront.net left intact
</BODY></HTML>⏎

「CloudFront はオリジンドメイン名を解決できなかった」とHTTP 502が返ってきました。

ブラウザからアクセスしても同様の内容が表示されました。

The request could not be satisfied

ということでIPv6オンリーのALBはCloudFrontのオリジンに指定することはできません。

IPv4のクライアントからアクセスが不要な場合に

インターネット向けApplication Load Balancer (ALB) が IPv6 のみのアドレスタイプをサポートしたアップデートを紹介しました。

IPv4のクライアントからアクセスが不要な場合には積極的に使っていきたいですね。

その他のサービスのIPv6のみのサポート状況は以下AWS公式ドキュメントのIPv6 only supportで確認できます。随時チェックしましょう。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!