EgressOnlyInternetGatewayを通してIPv6アドレスのみの環境でSSMを使用してEC2を操作したかったけどまだ駄目でした

今はまだその時ではない
2023.10.01

たぬき( @tanuki_tzp )です。

AWSサービスにアタッチされているパブリックIPv4アドレスの有料化に伴い、IPv6アドレスのみ使用し、Session Managerでサクッと操作できて、コストも抑えられる検証環境を立てるCloudFormationテンプレートもあるとちょっと便利かな〜と思ったので作ってみたかったです。
作ってみたかったというのが出オチとなります、お察しください。

妄想していたこと

IPv6トラフィックのアウトバウンドのみを通す、EgressOnlyInternetGatewayを使用することで、IPv6トラフィックをPublicSubnet(と呼んで良いのかわからないですが…)から直接インターネットへ通すことで、NATGateway等を使用せずにコストを抑えて検証環境を立てられるのでは…と思っていました。

イメージしていた構成図はこちらです。

結論

できませんでした。
Session Managerの開始ドキュメントにあるように、エンドポイントへのアクセスルートが必要です。

The managed nodes you connect to must also allow HTTPS (port 443) outbound traffic to the following endpoints:
ec2messages.region.amazonaws.com
ssm.region.amazonaws.com
ssmmessages.region.amazonaws.com

Step 1: Complete Session Manager prerequisites - AWS Systems Manager

そして、エンドポイントはIPv4トラフィックのみにしか対応していないため、妄想していた構成では接続できません。

現在、IPv6アドレスしか持たないEC2インスタンスをSession Managerで操作するためには、たかくにさんの下記のブログにあるような、NATGatewayを通してIPv4アドレスに変換する方法を取るしかないようです。

エンドポイントがIPv6対応したら使えるようになるかもしれないCFnテンプレート

せっかく作ったので貼らせてください、でも悲しいことに今は使えません。早く使えるようになって欲しいですね。

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  EnvironmentName:
    Type: String
    Default: test

  VPCCIDR:
    Type: String
    Default: 10.0.0.0/16

  Ec2ImageId:
    Description: "Default: Amazon Linux 2023"
    Type: AWS::SSM::Parameter::Value<String>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64

  Ec2InstanceType:
    Type: String
    Default: t3.micro

Resources:
  # VPC
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-VPC
  Ipv6VPCCidrBlock:
    Type: AWS::EC2::VPCCidrBlock
    Properties:
      AmazonProvidedIpv6CidrBlock: true
      VpcId: !Ref 'VPC'

  # Gateway
  EgressOnlyInternetGateway:
    Type: AWS::EC2::EgressOnlyInternetGateway
    Properties:
      VpcId: !Ref 'VPC'

  # Subnet
  PublicSubnet:
    Type: AWS::EC2::Subnet
    DependsOn:
    - Ipv6VPCCidrBlock
    Properties:
      AvailabilityZone: !Select [0, !GetAZs ""]
      Ipv6CidrBlock: !Sub ['${Param1}00::/64', {Param1: !Select ['0', !Split ['00::/', !Select [0, !GetAtt 'VPC.Ipv6CidrBlocks']]]}]
      AssignIpv6AddressOnCreation: true
      Ipv6Native: true
      MapPublicIpOnLaunch: false
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-Public-Subnet

  # RouteTable
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-Public-RouteTable
  PublicRouteV6:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      DestinationIpv6CidrBlock: ::/0
      EgressOnlyInternetGatewayId: !Ref 'EgressOnlyInternetGateway'    
  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # EC2IAMRole
  EC2IAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${EnvironmentName}-SSM-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub ${EnvironmentName}-EC2InstanceProfile

  # EC2
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref Ec2InstanceType
      SubnetId: !Ref PublicSubnet
      ImageId: !Ref Ec2ImageId
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      IamInstanceProfile: !Ref EC2InstanceProfile
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 8
            VolumeType: gp3
      EbsOptimized: true
      SourceDestCheck: true
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroup
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${EnvironmentName}-EC2SecurityGroup

おわりに

AWSサービスに紐づくパブリックIPv4アドレスの有料化のアナウンスもあったので、そのうち対応するのでは…という淡い期待を持っています。
無駄にならない日が来ることを願って……。