Amazon Linux 2023でNATインスタンスを構築

VPCにおいて、プライベートサブネットからインターネットにアクセスするには、NATが必要になります。AWSから「NATゲートウェイ」というサービスが提供されており、数クリックで簡単にNATをデプロイすることができます。

しかし、どうしてもNATゲートウェイを利用できないケースがあります。また、NATゲートウェイの料金が高く無料利用枠がないことも、初心者からすると敷居が高い理由の一つでしょう。

そんなときに、EC2のインスタンスを利用して、NAT機能を実装した「NATインスタンス」を利用するといいです。NATインスタンスとは、EC2インスタンス上にNATに必要なソフトをインストールすることで、EC2インスタンスをNATとして利用するものです。単なるEC2インスタンスなのでもちろん無料利用枠がありますし、ニーズに応じてインスタンスタイプを選択することで費用の節約が可能になります。また固定IP(Elastic IP)の必要性もないのでEIPが利用不可の環境でもNATが使えるようになります。

最新のAmazon Linux、AL2023を使ってNATインスタンスを構築する方法はクラスメソッドさんのブログにもありますので、ここで割愛しますが、CloudFormationでIaC化しました。このCloudFormationテンプレートを利用すると、一発でNATインスタンスを構築することができます。

文末に掲載しているこのCloudFormationテンプレートの仕様、注意点は以下です。

  • デプロイ先のVPC・サブネット、許可するIPアドレス範囲、インスタンスタイプ(t2.microなど)をパラメータ化していますが、それ以外は直接テンプレートを編集することで変更できます
  • キーペアを設定していないためSSHでインスタンスにログインすることはできません。SSHでログインする必要がある場合、キーペアの設定を追加してください
  • AL2023にiptablesを搭載していないため、nftablesを利用しています
  • AL2023のlatestでのみ動作確認済みです(2023年5月24日時点)

ちなみに、AL2023は頻繁にアップデート版のAMIを出しています。以下のAWS CLIコマンドでAL2023のx86フルバージョンのイメージ一覧を確認できます。

C:\> aws ec2 describe-images --owners amazon --filters "Name=name,Values=al2023-ami-20*" "Name=architecture,Values=x86_64" --query "sort_by(Images, &Name)[].{Name: Name, ImageId: ImageId}" --output table
-----------------------------------------------------------------------------
|                              DescribeImages                               |
+------------------------+--------------------------------------------------+
|         ImageId        |                      Name                        |
+------------------------+--------------------------------------------------+
|  ami-067871d950411e643 |  al2023-ami-2023.0.20230315.0-kernel-6.1-x86_64  |
|  ami-02a2700d37baeef8b |  al2023-ami-2023.0.20230322.0-kernel-6.1-x86_64  |
|  ami-079a2a9ac6ed876fc |  al2023-ami-2023.0.20230329.0-kernel-6.1-x86_64  |
|  ami-01b32aa8589df6208 |  al2023-ami-2023.0.20230419.0-kernel-6.1-x86_64  |
|  ami-0e0820ad173f20fbb |  al2023-ami-2023.0.20230503.0-kernel-6.1-x86_64  |
+------------------------+--------------------------------------------------+

CloudFormationテンプレートはこちらです。

AWSTemplateFormatVersion: "2010-09-09"
Description: CFn template for creating NAT instance
Parameters:
  TargetVpcId:
    Type: AWS::EC2::VPC::Id
  AllowedIpCidr:
    Type: String
  TargetSubnet:
    Type: AWS::EC2::Subnet::Id
  LastestAmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
  NatInstanceType:
    Type: String
    Default: t2.micro
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - 
        Label:
          default: Select the VPC and Subnet where you want to deploy the NAT instance
        Parameters:
          - TargetVpcId
          - TargetSubnet
          - AllowedIpCidr
      - 
        Label:
          default: Specify the EC2 parameter
        Parameters:
          - LastestAmiId
          - NatInstanceType
    ParameterLabels:
      TargetVpcId:
        default: "VPC ID (select from drop down list)"
      TargetSubnet:
        default: "Subnet ID to which you want to deploy (select from drop down list)"
      AllowedIpCidr:
        default: "Allowed IP CIDR (eg.: 192.168.0.0/24) from which the traffic goes in"
      LastestAmiId:
        default: "AMI for the EC2 instance"
      NatInstanceType:
        default: "Instance type"
Resources:
  NatEC2Instance:
    Type: "AWS::EC2::Instance"
    Properties: 
      ImageId: !Ref LastestAmiId
      InstanceType: !Ref NatInstanceType
      SourceDestCheck: false
      BlockDeviceMappings:
        - DeviceName: "/dev/xvda"
          Ebs:
            VolumeType: gp3
            VolumeSize: 8
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref TargetSubnet
          AssociatePublicIpAddress: true
          GroupSet:
            - !Ref NatInstanceSecurityGroup
      Tags:
        - Key: Name 
          Value: nat-instance
      UserData:
        Fn::Base64: |
          #!/bin/bash
          sysctl -w net.ipv4.ip_forward=1 >> /etc/sysctl.conf
          yum install -y nftables
          nft add table nat
          nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
          nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
          nft add rule nat postrouting oifname "$(ip -o link show device-number-0 | awk -F': ' '{print $2}')" masquerade
          nft list table nat > /etc/nftables/al2023-nat.nft
          echo 'include "/etc/nftables/al2023-nat.nft"' >> /etc/sysconfig/nftables.conf
          systemctl start nftables
          systemctl enable nftables
  NatInstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: natinstance-sg
      GroupDescription: Allow all traffic only from the specified CIDR 
      VpcId: !Ref TargetVpcId
      SecurityGroupIngress:
        - IpProtocol: -1
          CidrIp: !Ref AllowedIpCidr
      Tags:
        - Key: Name 
          Value: natinstance-sg

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top