📝

NAT インスタンス構築ハンズオン

に公開

NAT インスタンスとは、一言で言うならば自動転送を可能にした踏み台サーバです。プライベートなネットワークに配置したいサーバがあります。ただ全く通信ができないと運用はできませんよね。そこでこういった仕組みが必要になります。
これまでかんたんな踏み台インスタンスを使用していましたが NAT インスタンスというものがあると知り学習目的で構築してみました。

ハンズオンの効能

簡易的な踏み台サーバは触っていましたが改めて NAT を作成してみることでネットワークまわり、通信の流れは解像度が上がった気がします。AWS の基本的なネットワークの理解を深めるのにも良いと思いました。

VPC 構築

ベースは公式のページを参考にしていますが、今回は必要最小限の構成で構築していきます。以下書いていない項目はデフォルトのまま進めてください。

  1. VPC コンソールにログインします。
    https://console.aws.amazon.com/vpc/
  2. 「VPC を作成」をクリックします。
  3. 「VPC など」を選択します。これを選択することでサブネット(パブリックとプライベート)も同時に作成されます。
  4. VPC の「名前タグ」(自動生成のチェックを入れてその下の欄に)を入力します。後から見てわかりやすい名前をつけましょう。
    例:nat-vpc
  5. アベイラビリティゾーン (AZ) の数は「1」にします。
  6. 「パブリックサブネットの数」「プライベートサブネットの数」は「1」にします。
  7. 「VPC エンドポイント」は「なし」に設定します。
  8. 「VPC を作成」をクリックします。

参考ページ

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-example-private-subnets-nat.html#create-vpc-private-subnets-nat

※上記公式ページをベースにしていますが必要最小限の構成に変更して立ち上げました。


この手順で AWS の仮想ネットワーク空間が構築できました。
ルートテーブルというのはこの VPC ネットワークと外のインターネット空間との橋渡しをする表です。IP アドレスなどが書かれています。
インターネットゲートウェイ(IGW)というのは インターネットと VPC の間にある入り口、門のようなものです。

EC2 インスタンス構築

EC2 インスタンスは public,private それぞれ2つのサブネットに 1 つずつ構築していきます。

NAT インスタンスを構築

インターネットからの通信を直接最初に受け取るインスタンスを生成します。実態は EC2 インスタンスで、それに NAT の機能を実装する形です。
以下書いてない項目はデフォルトで進めます。

  1. Amazon EC2 コンソール (https://console.aws.amazon.com/ec2/) を開き「インスタンスを起動」をクリックします。
  2. 任意の「名前」を入力します。
  3. インスタンスタイプのコストを抑えるために t3.nano にします。t4g は CPU アーキテクチャが先鋭的なので今回コストとバグを踏むリスクを考えてやめました。
  4. 「新しいキーペアの作成」リンクをクリックします。
      ポップアップが開きますので「キーペア名」を入力します。
      例:test-nat-instance-public
      「キーペアを作成」をクリックすると秘密鍵がダウンロードされます。以下の作業はローカル PC での作業です。
      ダウンロードされた鍵を~/.ssh などに保存します。
      ターミナルから以下のコマンドを実行します。
       chmod 400 ~/.ssh/test-nat-instance-public.pem
      終わったら一旦 AWS のコンソールに戻ります。
  5. ネットワーク設定の「編集」をクリックします。
      すると VPC とサブネットの欄がプルダウンになるので前の手順で作成した VPC を選択し、subnet は public となっているものを選択します。
  6. 「パブリック IP の自動割り当て」を「有効化」にします。
  7. 必要に応じて「セキュリテグループ名」を変更します。後からセキュリティグループも確認することもあるので public-nat-instance などの名前で作成するのがおすすめです。
  8. インバウンドセキュリティグループのルールとして以下を設定します。
    タイプ ポート ソースタイプ ソース 説明
    ssh 22 自分の IP Your IP Used by ssh
    カスタム TCP 9999 自分の IP Your IP Used by NAT
  9. 「インスタンスを起動」をクリックするとインスタンスが立ち上がります。
  10. 立ち上がった EC2 インスタンスを選択しコンソール画面のメニューから Actions → Networking → Change Source/Destination Check を選択。表示されるダイアログで、Disable(停止)を選び、保存してください。これによってデフォルトでは通信の転送を拒否している設定を無効にし、通信の転送を許可するようにします。
  11. 立ち上がったインスタンスのコンソール画面を開き、次の手順で使用するコマンドをコピーしておきます。
      「接続」ボタンをクリックします。
      「SSH クライアント」タブをクリックします。
      例:のところに ssh コマンドが表示されていると思いますのでコピーして以下のように鍵の部分、ポート部分を編集しておきます。
       ssh -i ~/.ssh/test-nat-instance-public.pem -p 22 ec2-user@ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
    

プライベートインスタンスを構築

プライベートサブネットに配置しインターネットには公開せず、NAT インスタンスだけと通信するインスタンスを構築します。アプリケーションサーバを想定しています。以下手順は NAT インスタンスと大まかな流れはほぼ同じですが少しだけ違うので以下の通り進めてみてください。
以下書いてない項目はデフォルトで進めます。

  1. Amazon EC2 コンソール (https://console.aws.amazon.com/ec2/) を開き「インスタンスを起動」をクリックします。
  2. 任意の「名前」を入力します。
  3. インスタンスタイプのコストを抑えるために t3.nano にします。t4g は CPU アーキテクチャが先鋭的なので今回コストとバグを踏むリスクを考えてやめました。
  4. 「新しいキーペアの作成」リンクをクリックします。
      ポップアップが開きますので「キーペア名」を入力します。
      例:test-nat-instance-private
      「キーペアを作成」をクリックすると秘密鍵がダウンロードされます。以下の作業はローカル PC での作業です。
      ダウンロードされた鍵を~/.ssh などに保存します。
      ターミナルから以下のコマンドを実行します。
       chmod 400 ~/.ssh/test-nat-instance-private.pem
      終わったら一旦 AWS のコンソールに戻ります。
  5. ネットワーク設定の「編集」をクリックします。
      すると VPC とサブネットの欄がプルダウンになるので前の手順で作成した VPC を選択し、subnet は private となっているものを選択します。
  6. 「パブリック IP の自動割り当て」を「無効化」にします。
  7. 必要に応じて「セキュリテグループ名」を変更します。後からセキュリティグループも確認することもあるので private-nat-instance などの名前で作成するのがおすすめです。
  8. インバウンドセキュリティグループのルールとして以下を設定します。
    タイプ ポート ソースタイプ ソース 説明
    ssh 22 カスタム public instans private IP Only NAT instances are passed through for communication
  9. 「インスタンスを起動」をクリックするとインスタンスが立ち上がります。

NAT アプリケーションの設定

NAT はローカル IP アドレスとパブリック IP アドレスとの間でIPを変換する機能です。EC2 インスタンスに設定していきます。
先ほど作成したインスタンスに入ってコマンド操作をしていきます。まずはローカル PC でターミナルを立ち上げます。

  1. ターミナルに以下のコマンドを入力します。NAT インスタンスを構築の手順11でコピーした ssh 接続コマンドを実行すると EC2 インスタンスに入れると思います。
$ ssh -i ~/.ssh/test-nat-instance-public.pem -p 22 ec2-user@ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
  1. ここからはインスタンスの中でコマンドを実行しています。まずは Linux ベースのインスタンスがパケットを転送できるように許可するコマンドを実行します。

$ sudo sysctl -w net.ipv4.ip_forward=1

  1. iptables というコマンドをインストール → 有効化 → スタートします。これは IP アドレス、ポート番号、通信を許可するか拒否するかなどを設定する IP テーブルを操作するコマンドになります。ここでは EC2 インスタンスのデフォルト OS である Amazon Linux 2023 用のものをインストールしていますので、他 OS の方は適宜調整が必要です。

$ sudo yum install iptables-services -y
$ sudo systemctl enable iptables
$ sudo systemctl start iptables

  1. インストールした iptables コマンドを使用して、送信元 IP アドレスを変換できるように設定します。これは SNAT と呼ばれるもので主にプライベートサブネット → インターネットの通信で使用されます。

$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

  1. 次に DNAT を設定していきます。これは主に インターネット → プライベートサブネット への通信で使用され、IP アドレスとポートの書き換えを担当します。以下の設定では 9999 ポートに来た通信を 22 ポートに書き換えて転送する設定になります。

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 9999 -j DNAT --to-destination <PrivateIP>:22

  1. NAT インスタンス → プライベートインスタンスへ TCP22 番ポートの通信を許可、同様のプライベートインスタンス →NAT インスタンスも許可します。

# プライベートEC2宛のTCP 22を許可
sudo iptables -I FORWARD 1 -p tcp -d <プライベートEC2IP> --dport 22 -j ACCEPT

# 既存接続に関して応答も許可
sudo iptables -I FORWARD 2 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT


ルートテーブルに設定を追加

プライベートサブネットのルートテーブルに設定を行います。これはプライベートサブネットからどこに通信を送るかという設定です。ここでは全ての通信を NAT インスタンスのみに通信を送る設定をします。

  1. AWS コンソールから「VPC」→ 右メニューの「ルートテーブル」をクリックします。
  2. 「ルート」タブを選択し「ルートを編集」をクリックします。
  3. 「ルートを追加」をクリックし送信先を 0.0.0.0/0、ターゲットはプルダウンから「インスタンス」→「NAT インスタンス」を選択します。そうすると自動的に eni に変換されて設定されます。もちろん eni を調べてきて設定しても大丈夫です。

接続確認

ローカル PC のターミナルから以下のコマンドを実行して接続できれば成功です。


$ ssh -A -i test-nat-instance-private.pem -p 9999 ec2-user@nat-instance-public-ip

NAT ゲートウェイとの違い

公式では以下のようにまとめてくれています。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-comparison.html

NAT インスタンスの使い所

状況によっては NAT ゲートウェイより実質コストを抑えられるという例もネットにはありました。その都度管理コストと比較検討してみると NAT インスタンスが有効になる場面があるのかもしれません。

Discussion