← ハンズオン一覧に戻る

AWS Hands-on / Networking

NAT の仕組みを、自分の手で組み立てる

マネージドサービスの NAT ゲートウェイを使わず、ふつうの EC2 インスタンスに設定を施して「NAT インスタンス」を自分の手で組み立てます。IP フォワーディングと送信元/送信先チェックの無効化という、裏側で行われている処理を、実際に自分の手で設定して体感します。

● Lv.3 複数のサービスを組み合わせられる人 ⏱ 所要 50〜70 分 コンソール操作に加えて PowerShell から SSH を使用します
01 — Prerequisites

はじめる前に

  • 必須AWS アカウントを持ち、マネジメントコンソールにサインインできること
  • 必須VPC・パブリックサブネット・プライベートサブネットを作成した経験があること
  • 必須EC2 を SSH でログインした経験があること
  • あると良い「ネットワークアドレス変換(NAT)」という言葉の意味をなんとなく知っている
  • あると良いLinux のネットワーク設定を触った経験がある

※ ローカルの PowerShell から Windows 標準の OpenSSH を使って、2 段階の SSH 接続を行います。エージェントフォワード(-A オプション)を使うため、事前に ssh-agent サービスを有効化する手順をこのページ内で案内します。

02 — References

参照する公式ドキュメント

手順に迷ったときや、用語の意味を確かめたいときに開きましょう。

※ リンク切れの場合は、ページタイトルで検索してください。

03 — Background

背景・シナリオ

プライベートサブネットのサーバーが外向きの通信を行うには、何らかの形で「外への出口」を用意する必要があります。マネージドサービスの「NAT ゲートウェイ」を使えば AWS が管理を代わりにやってくれますが、その裏側では何が起きているのでしょうか。

実は、ふつうの EC2 インスタンスに「IP フォワーディング(他の宛先向けの通信を中継する設定)」「送信元/送信先チェックの無効化」を施すだけで、同じ役割を持つ「NAT インスタンス」を自分で作ることができます。今回はそれを実際に手作業で組み立て、ネットワークアドレス変換の仕組みが裏側で何をしているのかを体感します。

「送信元/送信先チェック」って何のためにあるの?

通常、EC2 インスタンスは「自分宛て」または「自分が送信元」の通信だけを処理します。これがオンになっていると、他のインスタンス(プライベートサブネットのサーバー)宛ての通信を中継できません。NAT インスタンスは「自分以外の宛先の通信」を転送する役割なので、このチェックを無効化する必要があります。

IP フォワーディングって何?

Linux カーネルの設定の 1 つで、自分宛てでないパケットを別のネットワークインターフェースに転送できるようにする機能です。デフォルトでは無効になっており、有効にしないと NAT インスタンスはパケットを中継できません。

マネージドサービスとの違いは何?

マネージドサービスを使う方式は、冗長性・スケーリング・パッチ適用を AWS が管理してくれます。今回作る NAT インスタンスは、自分で用意した EC2 インスタンス 1 台に役割を持たせるため、その 1 台が落ちると中継機能全体が止まり、スループットもインスタンスタイプの性能に依存します。今回はその「裏側の仕組み」を理解するために、あえて手作業で組み立てます。

Goal

パブリックサブネットにNAT インスタンス(送信元/送信先チェック無効化、IP フォワーディング有効化、firewalld でのマスカレード設定済みの EC2)を 1 台、プライベートサブネットにテスト用 EC2を 1 台作成する。プライベートサブネットのルートテーブルで NAT インスタンスを経由させ、テスト用 EC2 からの外向き通信が成功することを確認する。

04 — Architecture

つくる構成

パブリックサブネットに NAT インスタンスを置き、プライベートサブネットのサーバーは NAT インスタンス経由でだけ外に出られるようにします。CIDR は VPC の範囲内で重ならなければ自由に決めて構いません(例の数値は一例です)。

インターネット
aws AWS Cloud
Region : ap-northeast-1(東京)
VPC : 10.0.0.0/16(例)
インターネットゲートウェイ(VPC にアタッチ)
public-subnet
ap-northeast-1a
10.0.1.0/24
NAT インスタンス(送信元/送信先チェック:無効)
ルート: 0.0.0.0/0 → インターネットゲートウェイ
private-subnet
ap-northeast-1a
10.0.2.0/24
テスト用サーバー(パブリック IP なし)
ルート: 0.0.0.0/0 → NAT インスタンス
プライベートサブネットの「外向き」の通信は、いったん NAT インスタンスを経由してインターネットゲートウェイへ向かいます。マネージドサービスの NAT ゲートウェイの代わりに、設定済みの EC2 が同じ役割を担います。
※ 数値は一例です。CIDR は VPC の範囲内で重ならなければ自由に決められます。
05 — Requirements

要件

以下の要件を満たす構成を作り、プライベートサブネットから NAT インスタンス経由で外向き通信ができることを確認してください。

No要件
1リージョンは「東京(ap-northeast-1)」を使用する。
2VPC 内にパブリックサブネットとプライベートサブネットを 1 つずつ用意する(既存の VPC を使ってもよい)。CIDR は重ならなければ自由に決める(例:10.0.1.0/2410.0.2.0/24)。
3パブリックサブネットに EC2 を 1 台起動し「NAT インスタンス」とする(パブリック IP を自動割り当て、Amazon Linux 2023)。
4NAT インスタンスの「ソース/宛先のチェック」を無効化する。
5NAT インスタンスの OS 内でIP フォワーディングを有効化し、firewalld でマスカレード(送信元アドレス変換)を設定する。
6NAT インスタンス用セキュリティグループで、プライベートサブネットの CIDR からの通信を許可する。
7プライベートサブネットにテスト用 EC2 を 1 台起動し(パブリック IP なし)、ルートテーブルで 0.0.0.0/0 の宛先を NAT インスタンスに向ける。テスト用 EC2 から外向き通信(dnf update 等)が成功することを確認する。
06 — Steps

構築の進め方

「NAT インスタンスを起動する → AWS 側の設定を変える → OS 内部の設定をする → プライベート側の経路を向ける → 確認する」の順に積み上げます。各ステップで「なぜそうするのか」を意識すると理解が定着しやすくなります。

  1. マネジメントコンソールにサインインし、リージョンを合わせる

    ブラウザで AWS マネジメントコンソールにサインインし、画面右上のリージョンが「アジアパシフィック(東京)ap-northeast-1」になっていることを確認します。

  2. VPC 内にパブリックサブネットとプライベートサブネットを用意する

    既存の VPC を使う場合はそのまま進めて構いません。新しく作る場合は、VPC コンソールで VPC を 1 つ用意し(例:10.0.0.0/16)、その中にサブネットを 2 つ作ります。名前タグは public-subnet / private-subnet、アベイラビリティーゾーンは同じもの(例:ap-northeast-1a)、CIDR は重ならないように決めます(例:10.0.1.0/2410.0.2.0/24)。パブリックサブネットにはインターネットゲートウェイへの経路と「パブリック IPv4 アドレスの自動割り当て」を設定しておきます。

  3. パブリックサブネットに EC2 を 1 台起動する(NAT インスタンスになる)

    EC2 コンソールでインスタンスを起動します。Amazon Linux 2023public-subnetパブリック IP 自動割り当て有効で起動し、セキュリティグループは SSH(22)を「マイ IP」から許可するものを使います。名前は自由に決めます(例:nat-instance)。

    特別なAMIは不要

    NAT インスタンス専用の特別な仕組みがあるわけではなく、ふつうの EC2 インスタンスに、これから行う設定を施すことで NAT インスタンスとして機能するようになります。

  4. 「送信元/送信先の変更チェック」を無効化する

    起動した NAT インスタンスを選択し、「アクション」→「ネットワーキング」→「送信元/送信先の変更チェック」を選び、無効化します。

    なぜこの操作が必須なのか

    EC2 インスタンスは、デフォルトでは「自分が送信元」または「自分宛て」の通信だけを処理し、それ以外のパケットは破棄してしまいます。NAT インスタンスはプライベートサブネットのサーバー宛て・発の通信を中継する役割なので、このチェックを外し、自分以外の宛先・送信元のパケットも処理できるようにする必要があります。

  5. NAT インスタンスのセキュリティグループに、プライベートサブネットからの通信を許可する

    NAT インスタンスのセキュリティグループのインバウンドルールに、ソースをプライベートサブネットの CIDR 範囲(例:10.0.2.0/24)とした、すべてのトラフィックを許可するルールを追加します。

    範囲を絞る

    許可するソースは「プライベートサブネットの CIDR」に絞ります。インターネット全体(0.0.0.0/0)からの通信を直接受け付ける設定にはしないようにしましょう。

  6. ローカルの PowerShell から NAT インスタンスに SSH ログインし、IP フォワーディングを有効化する

    NAT インスタンスのパブリック IP に SSH 接続し、カーネルの IP フォワーディング設定を有効化します。再起動後も設定が消えないように、/etc/sysctl.d/ 配下に設定ファイルを追加して永続化します。

    PowerShell → NAT インスタンス
    # ローカルの PowerShell から NAT インスタンスへ SSH
    ssh -i my-key.pem ec2-user@<NAT インスタンスのパブリック IP>
    
    # その場限りで IP フォワーディングを有効化(動作確認用)
    sudo sysctl -w net.ipv4.ip_forward=1
    
    # 再起動後も有効になるよう設定ファイルとして永続化
    echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-nat-instance.conf
    sudo sysctl --system

    続けて、firewalld でマスカレード(送信元アドレス変換)を有効化します。

    NAT インスタンスの中
    # firewalld のパブリックゾーンでマスカレードを有効化(永続設定)
    sudo firewall-cmd --zone=public --add-masquerade --permanent
    
    # 設定を反映
    sudo firewall-cmd --reload
    マスカレードとは

    プライベートサブネットのサーバーが送ったパケットの送信元アドレスを、NAT インスタンス自身のアドレスに書き換えて転送する処理です。これにより、インターネット側からは NAT インスタンスが送信元であるかのように見え、応答もいったん NAT インスタンスに戻ってきます。

  7. プライベートサブネットにテスト用 EC2 を 1 台起動する

    EC2 コンソールでインスタンスを起動します。private-subnetパブリック IP なしで起動し、セキュリティグループはソースを NAT インスタンスのセキュリティグループとした SSH(22)許可ルールを持つものを使います。名前は自由に決めます(例:private-test)。

    プライベート IP アドレスをメモしておく

    テスト用 EC2 にはパブリック IP がないため、直接 SSH することはできません。次のステップで使うプライベート IPv4 アドレスを、インスタンスの詳細画面で確認してメモしておきましょう。

  8. プライベートサブネットのルートテーブルで、NAT インスタンスへの経路を書く

    プライベートサブネット用のルートテーブルの「ルート」タブから、次のルートを追加します。

    送信先(Destination)0.0.0.0/0
    ターゲット(Target)「インスタンス」を選び、手順 3 で作った NAT インスタンスを指定
    NAT ゲートウェイ向けのターゲットとは異なる

    マネージドサービスを使う場合はターゲットの種類が専用のものになりますが、今回は「インスタンス」を選び、起動した EC2 そのものをターゲットに指定する点が特徴です。

  9. NAT インスタンス経由で 2 段階 SSH し、外向き通信を確認する

    ローカルの PowerShell から、エージェントフォワードを使って NAT インスタンス経由でテスト用 EC2 にログインします。エージェントフォワードを使うには、事前に Windows 標準の OpenSSH に付属する ssh-agent サービスを有効化しておく必要があります。

    PowerShell(管理者)
    # ssh-agent サービスを有効化して起動する(初回のみ)
    Set-Service ssh-agent -StartupType Automatic
    Start-Service ssh-agent
    
    # 鍵をエージェントに登録する
    ssh-add my-key.pem
    PowerShell → NAT インスタンス → テスト用サーバー
    # ローカルから NAT インスタンスへ(エージェントフォワードを有効にする -A オプション)
    ssh -A -i my-key.pem ec2-user@<NAT インスタンスのパブリック IP>
    
    # NAT インスタンスの中から、テスト用サーバーのプライベート IP へ
    ssh ec2-user@<テスト用サーバーのプライベート IP>
    
    # テスト用サーバーの中で、外向き通信を確認する
    sudo dnf update -y

    パッケージの取得がエラーなく完了すれば、プライベートサブネットのサーバーが NAT インスタンス経由で外向きの通信に成功しています。

    ここで起きていること

    テスト用サーバーが送ったパケットは、いったん NAT インスタンスに転送され、送信元アドレスが NAT インスタンスのものに書き換えられてからインターネットゲートウェイへ送られます。応答も同じ経路を逆にたどって戻ってきます。

07 — Pitfalls

つまずきポイント

初学者がよく引っかかる箇所を先回りでまとめました。答えそのものは載せていませんが、「どこを見直せばよいか」の手がかりとして使ってください。

Pitfall 01 — プライベートのサーバーから外に出られない(その 1)

「設定したはずなのに、パケットが転送されない」

最も典型的な原因は、NAT インスタンスの「ソース/宛先の変更チェック」が無効化されていないことです。このチェックはデフォルトで有効になっており、有効なままだと NAT インスタンスは自分以外の宛先・送信元のパケットをすべて破棄してしまいます。AWS 特有の設定なので見落としやすいポイントです。インスタンスの詳細画面で、この項目の状態を確認してみましょう。

Pitfall 02 — プライベートのサーバーから外に出られない(その 2)

「インスタンスを再起動したら、また通信できなくなった」

IP フォワーディングの設定を sysctl -w だけで反映させた場合、再起動すると設定が消えてしまいます。/etc/sysctl.d/ 配下への永続化ファイルが正しく書かれているか、確認してみましょう。また、firewalld のマスカレード設定も --permanent オプション付きで実行し、--reload で反映したかを再確認してみてください。

08 — Checklist

完了チェック

要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。EC2 コンソールと VPC コンソールを開いて、次を順に確かめましょう。

  • NAT インスタンスの詳細画面で、「ソース/宛先の変更チェック」が「無効」になっている。
  • プライベートサブネット用ルートテーブルの「ルート」タブで、送信先 0.0.0.0/0ターゲットが NAT インスタンス(インスタンス ID)になっている。
  • テスト用 EC2 の中で実行したパッケージ取得コマンドが、エラーなく完了する。
  • NAT インスタンスのセキュリティグループの「インバウンドルール」に、プライベートサブネットの CIDR からの許可ルールが表示されている。
  • NAT インスタンスの中で cat /proc/sys/net/ipv4/ip_forward を実行すると、値が 1 になっている。
09 — Think

考えてみよう

手を動かすことに加えて、次の問いに自分の言葉で答えられるようにしておくと、理解がより深まります。

  1. 今回作った NAT インスタンスは、EC2 インスタンスを 1 台だけ使う構成でした。可用性の観点で、この構成にはどんな弱点がありそうでしょうか。
    ヒント
    マネージドサービスとして提供される方式では、AWS が複数のアベイラビリティーゾーンにまたがる冗長性やフェイルオーバーを管理してくれます。1 台の EC2 インスタンスに役割を集約した場合、そのインスタンスに何か起きたときに何が止まるかを考えてみましょう。
  2. NAT インスタンスのインスタンスタイプ(例:t3.micro から t3.large などへ)を変更すると、何が変わりそうでしょうか。
    ヒント
    ネットワークアドレス変換の処理は、インスタンスの CPU やネットワーク帯域を使って行われます。インスタンスタイプごとに割り当てられるネットワーク性能の上限が異なる点から考えてみましょう。
  3. NAT インスタンスを実務で使う場合、パッチ適用や監視を自分で行う必要があります。これは運用上どんな負担になりそうでしょうか。
    ヒント
    OS のセキュリティ更新を適用するタイミングや、インスタンスが正常に動いているかを監視する仕組みを、自分たちで用意し続ける必要があります。マネージドサービスであれば不要だった作業が、誰の役割として発生するかを考えてみましょう。
10 — Clean up

後片づけ

作成したリソースを次の順で片づけましょう。

  1. テスト用 EC2 を削除する:EC2 コンソールでテスト用インスタンス(例:private-test)を選び、「インスタンスの状態」→「インスタンスを終了」。
  2. NAT インスタンスを削除する:NAT インスタンス(例:nat-instance)を選び、同様に終了する。
  3. ルートテーブルの設定を元に戻すか、ルートテーブル自体を削除する:このハンズオン専用に作成したルートテーブルであれば削除し、既存のルートテーブルに追加したルートであれば、追加した 0.0.0.0/0 のルートを削除する。
  4. セキュリティグループを削除する:NAT インスタンス用・テスト用に作成したセキュリティグループを、他のリソースに使われていないことを確認してから削除する。
Caution — 既存の VPC やデフォルトリソースを間違えて消さない

削除するのは、このハンズオンで自分が作ったものだけ

既存の VPC を利用した場合、サブネットやルートテーブル、デフォルト VPC そのものは削除しないようにしてください。一覧には他で使っているリソースも並んでいるかもしれません。このハンズオンのために作成した名前のものだけを選んで削除してください。

コストに関する注意: NAT インスタンスは通常の EC2 インスタンスとして課金されます。インスタンスタイプに応じた時間課金のみが発生し、データ処理量に応じた追加課金はありません。低トラフィックの検証用途では、マネージドサービスを使う方式より安くなる場合もありますが、可用性・スループット・運用負担の面ではマネージドサービスに劣ります。テスト用 EC2 にも同様にインスタンスタイプに応じた時間課金が発生します。VPC・サブネット・ルートテーブル・セキュリティグループ自体には料金はかかりません。使い終えたら、上の「後片づけ」を参考に EC2 インスタンスを必ず終了しましょう。最新の料金は AWS の公式料金ページで確認してください。