Amazon Linux 2023でNAT Instanceを手作りしてみた

2023.03.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

しばたです。

私は昔から検証環境でNAT Instanceを利用しているのですが、先日Amazon Linux 2023が正式リリースされたのを受け「流石にそろそろインスタンスを更新するか」という気分になりAmazon Linux 2023でNAT Instanceを作成してみました。

本記事ではその手順を紹介します。

作成手順

Amazon Linux 2以降のディストリビューションにおいてはAWS公式でNAT Instance AMIは提供されておらず、以下の記事にある様に自分で手作りする必要があります。

こちらの記事はAmazon Linux 2のものであり、当然ながらまだAmazon Linux 2023向けの公式手順といったものは存在してません。(現在は公式手順が存在します)
とはいえ、そこまでディストリビューション独自の作業は少ないため「多分Amazon Linux 2の手順と同じで大丈夫だろう。」との考えで作業を進めていきます。

【2023年11月13日 追記】AWS公式ドキュメントの手順

具体的にいつ頃ドキュメントが更新されたかは不明ですが、現在はAWS公式ドキュメントにAmazon Linux 2023での手順が記載されています。

内容としてはiptablesコマンドを追加インストールしてAmazon Linux 2と同じ手順を行う形になっています。

「公式の手順」が欲しい方は上記ドキュメントを参照してください。
本記事の内容はnftablesコマンドを使った実装例としてお使いください。

注意事項

一応動作確認まではしていますが、非公式の手順となるので以降の内容については無保証です。ご了承ください。

基本方針とAmazon Linux 2023独自の事情

基本方針としてはAmazon Linux 2の時と同様に、

  1. 当該インスタンスでnet.ipv4.ip_forwardカーネルパラメーターの設定およびiptablesを設定する
  2. 当該インスタンスのENIで「送信元/送信先チェック」を無効にする

を行います。

ただ、Amazon Linux 2023の初期状態ではiptablesコマンドがインストールされていません。
このため今回は代わりに後継のnftablesコマンドをインストールしてNATの設定を行います。

1. EC2インスタンスの作成

今回は私の検証アカウントの東京リージョンに以下の条件でEC2インスタンスを用意しました。

  • AMIは ami-00cd61829b9bb9eca : al2023-ami-2023.0.20230315.0-kernel-6.1-arm64
  • インスタンスタイプは t4g.micro
  • EBSボリュームは最低容量の gp3 8GiB
  • セキュリティグループは事前準備済みのものを使用 (作成手順は割愛)
    • インバウンドルールはVPC内からHTTP, HTTPSを許可
    • アウトバウンドは全ての通信を許可
  • SSM Sessionで接続可能なIAMロールをアタッチ

2. インスタンス内部設定 (net.ipv4.ip_forward)

SSM Sessionでインスタンスに接続し、以下のコマンドを実行してnet.ipv4.ip_forwardカーネルパラメーターを設定します。

sudo sysctl -w net.ipv4.ip_forward=1 | sudo tee -a /etc/sysctl.conf

ここはAmazon Linux 2の時と変わりません。

3. インスタンス内部設定 (nftables)

続けてiptablesの代わりにnftablesをインストールしてNATの設定を行います。

# Amazon Linux 2023の初期状態ではiptablesは未インストール
# このため今回はnftablesをインストール
sudo yum install -y nftables

nftablesでNATするための基本設定は以下のRed Hatのドキュメントを参考にしています。

基本的にはドキュメント通りの内容ですが、一点ハマったところがあり、Amazon Linux 2023ではNICが予測可能なデバイス名となっておりeth0固定では無いのでご注意ください。(代わりにENI IDやdevice-munber-0といった代替名が与えられています)
下記手順ではip -o link show device-number-0コマンドを使いデバイス名を取得しています。

あとは設定内容を/etc/nftables/al2023-nat.nftファイルに保存しサービス起動時にロードする様にしています。

# NAT設定追加 : NICデバイス名がeth0ではないので注意。今回の環境では ens5 だった
sudo nft add table nat
sudo nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
sudo nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
sudo nft add rule nat postrouting oifname "$(ip -o link show device-number-0 | awk -F': ' '{print $2}')" masquerade
# NAT設定保存
sudo nft list table nat | sudo tee /etc/nftables/al2023-nat.nft
echo 'include "/etc/nftables/al2023-nat.nft"' | sudo tee -a /etc/sysconfig/nftables.conf

# サービス起動+自動起動設定
sudo systemctl start nftables
sudo systemctl enable nftables

ちなみに/etc/nftables/al2023-nat.nftの中身はこんな感じになります。

/etc/nftables/al2023-nat.nft (環境によってoifnameは変わります)

table ip nat {
        chain prerouting {
                type nat hook prerouting priority dstnat; policy accept;
        }

        chain postrouting {
                type nat hook postrouting priority srcnat; policy accept;
                oifname "ens5" masquerade
        }
}

4. インスタンスの送信元/送信先チェックの無効化

続けて当該インスタンスのENI設定を開き「送信元/送信先チェック」を無効にします。

これもAmazon Linux 2の時と同様ですね。
以上でインスタンスの設定変更は完了です。

5. ルートテーブルの更新

あとはルートテーブルを更新してやれば完了ですが本記事では説明を割愛します。
こちらは環境に応じてよしなにやってください。

動作確認

別途動作確認用のEC2インスタンスを用意しcheckip.amazonaws.comへアクセスして動作確認すると以下の結果となりました。

いい感じですね。

最後に

以上となります。

ちょっとハマりましたがなんとかなりました。
次は古いNAT Instanceからの切り替え手順について解説する予定です。