← ハンズオン一覧に戻る

AWS Hands-on / Networking

プライベートのサーバーが、外だけに出られる道を作る

外から直接アクセスできない「プライベートサブネット」のサーバーに、外向きの通信だけを許す「NAT ゲートウェイ」を組み合わせます。インターネットゲートウェイとの違いを、踏み台サーバー経由で実際に確かめます。

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

はじめる前に

  • 必須AWS アカウントを持ち、マネジメントコンソールにサインインできること
  • 必須VPC・サブネット・ルートテーブル・インターネットゲートウェイの基本(パブリックサブネットとプライベートサブネットの違いをなんとなく分かる)こと
  • 必須EC2 を起動し、キーペアで SSH ログインした経験があること
  • 必須セキュリティグループで通信を許可した経験があること
  • あると良い「踏み台サーバー(bastion)」という言葉を聞いたことがある

※ コンソール操作に加えて、お使いのパソコンのターミナルから SSH を 2 段階(踏み台サーバー → プライベートサーバー)で使用します。

02 — References

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

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

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

03 — Background

背景・シナリオ

プライベートサブネットに置いたサーバーは、外から直接アクセスされないという安心感があります。しかし実務では「OS のセキュリティ更新を取りに行きたい」「外部の API を呼び出したい」など、自分から外へ出たい場面がよくあります。インターネットゲートウェイをそのままプライベートサブネットにつなぐと、外から内へも自由に入れてしまい、プライベートサブネットを使う意味が薄れてしまいます。

そこで使うのが NAT ゲートウェイです。「外から内側へは新しい接続を開始できず、内側から外へ出る通信とその応答だけを中継する」という一方通行の出入口です。今回はパブリックサブネットに NAT ゲートウェイを置き、プライベートサブネットのサーバーがそれ経由で外向きの通信だけを行えることを確かめます。

インターネットゲートウェイと何が違うの?

インターネットゲートウェイは、設定次第で外から内側へのアクセスも、内側から外への通信も両方を通せる双方向の出入口です。NAT ゲートウェイは内側が始めた通信の応答だけを戻し、外側から新しく接続を開始することはできません。この非対称性が、プライベートサブネットを「外から守られたまま」にする鍵です。

プライベートのサーバーに直接 Elastic IP を付ければいいのでは?

Elastic IP を付けてインターネットゲートウェイ行きのルートを持たせると、そのサーバーは外から直接到達できる状態になってしまい、「外から保護されている」というプライベートサブネットの前提が崩れます。NAT ゲートウェイを使うと、サーバー自身は公開アドレスを持たないまま、外向き通信だけを実現できます。

Goal

パブリックサブネットに NAT ゲートウェイを作成し、プライベートサブネットのルートテーブルをそこへ向ける。踏み台サーバー経由でプライベートサブネットの EC2 に SSH 接続し、外向きの通信(パッケージの取得など)が成功することを確認する。

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 ゲートウェイ(EIP 付き)
踏み台サーバー(bastion)
ルート: 0.0.0.0/0 → インターネットゲートウェイ
private-subnet
ap-northeast-1a
10.0.2.0/24
確認用サーバー(パブリック IP なし)
ルート: 0.0.0.0/0 → NAT ゲートウェイ
プライベートサブネットの「外向き」の通信だけが NAT ゲートウェイ → インターネットゲートウェイの順に流れます。外側から新しい接続を始めてプライベートサブネットに入ることはできません。
※ 数値は一例です。CIDR は VPC の範囲内で重ならなければ自由に決められます。
05 — Requirements

要件

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

No要件
1リージョンは「東京(ap-northeast-1)」を使用する。
2VPC を 1 つ用意し、その中にパブリックサブネットとプライベートサブネットを 1 つずつ作る。CIDR は重ならなければ自由(例:10.0.1.0/2410.0.2.0/24)、アベイラビリティーゾーンは同一(例:ap-northeast-1a)とする。
3インターネットゲートウェイを VPC にアタッチし、パブリックサブネットのルートテーブルに 0.0.0.0/0 → インターネットゲートウェイのルートを追加・関連付ける。パブリックサブネットは「パブリック IPv4 自動割り当て」を有効にする。
4パブリックサブネットに NAT ゲートウェイを作成する(接続タイプ「パブリック」、新規 Elastic IP を割り当て)。プライベートサブネット用のルートテーブルに 0.0.0.0/0 → NAT ゲートウェイのルートを追加し、プライベートサブネットに関連付ける。
5セキュリティグループを 2 つ用意する(踏み台用:自分の IP からのみ SSH 許可/プライベート用:踏み台用セキュリティグループからのみ SSH 許可)。踏み台用 EC2(パブリックサブネット、パブリック IP あり)とテスト用 EC2(プライベートサブネット、パブリック IP なし)を 1 台ずつ起動する。
6踏み台サーバー経由でテスト用 EC2 に SSH 接続し、外向きの通信(パッケージ取得コマンドなど)が成功することを確認する。
06 — Steps

構築の進め方

「パブリック側を整える → NAT ゲートウェイを置く → プライベート側の経路をそこへ向ける → サーバーで確認する」の順に積み上げます。各ステップで「なぜそうするのか」を意識すると理解が定着しやすくなります。

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

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

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

    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)。

    この時点ではまだ何も区別がない

    作っただけのサブネットは、どちらもまだパブリック/プライベートの区別がありません。これから経路の設定で差をつけていきます。

  3. インターネットゲートウェイをアタッチし、パブリックサブネットを外につなげる

    インターネットゲートウェイを 1 つ作成して VPC にアタッチします。パブリック用ルートテーブルを作り、0.0.0.0/0 → インターネットゲートウェイのルートを追加して public-subnet に関連付けます。public-subnet の設定で「パブリック IPv4 アドレスの自動割り当て」も有効にしておきます。

    先にパブリック側を完成させる理由

    NAT ゲートウェイ自体が、外とやり取りするためにパブリックサブネットの中で動きます。NAT ゲートウェイを置く前に、まずパブリックサブネットが正しく外につながる状態を作っておきます。

  4. NAT ゲートウェイを作成する

    VPC コンソール左メニュー「NAT ゲートウェイ」→「NAT ゲートウェイを作成」を開きます。名前(例:my-nat-gw)を付け、サブネットに public-subnet を指定し、次のように設定します。

    接続タイプパブリック
    Elastic IP 割り当て ID「新しい Elastic IP を割り当てる」を選択
    NAT ゲートウェイを作成 — 接続タイプの選択(イメージ)

    接続タイプ

    パブリック
    Elastic IP を持ち、インターネットへ出られる
    プライベート
    VPC 内や接続先のネットワーク向けの中継専用

    インターネットへ出たいので「パブリック」を選びます

    作成直後は少し待つ

    NAT ゲートウェイは作成してすぐには使えず、状態が 「Pending」→「Available」に変わるまで数分かかります。次のステップに進む前に、状態が「Available」になっているか確認しましょう。

  5. プライベート用ルートテーブルを作り、NAT ゲートウェイへの経路を書く

    プライベートサブネット用のルートテーブルを 1 つ作成します(名前は例:private-rt)。「ルート」タブから次のルートを追加します。

    送信先(Destination)0.0.0.0/0
    ターゲット(Target)「NAT Gateway」を選び、手順 4 で作った my-nat-gw を指定

    作成したルートテーブルの「サブネットの関連付け」タブから private-subnet を関連付けます。

    インターネットゲートウェイには向けない

    プライベートサブネットのルートは必ず NAT ゲートウェイへ向けます。誤ってインターネットゲートウェイへ向けてしまうと、サーバーがパブリック IP を持っていない限り通信できず、設計の意図も崩れてしまいます。

  6. セキュリティグループを 2 つ用意する

    EC2 コンソールの「セキュリティグループ」で次の 2 つを作成します。

    踏み台用(例:bastion-sgインバウンドで SSH(22)を「マイ IP」から許可
    プライベート用(例:private-sgインバウンドで SSH(22)を、ソース=踏み台用セキュリティグループ(bastion-sgから許可
    プライベートには「踏み台からのみ」

    プライベートサブネットのサーバーには、利用者が直接 SSH できないようにします。踏み台用セキュリティグループからの通信だけを許可しておくことで、接続経路を踏み台に一本化できます。

  7. 踏み台用 EC2 とテスト用 EC2 を起動する

    同じキーペアを使って EC2 を 2 台起動します(Amazon Linux 2023・無料利用枠対象タイプ)。

    踏み台用(例:bastionpublic-subnet・パブリック IP 自動割り当て有効・セキュリティグループ bastion-sg
    テスト用(例:private-testprivate-subnet・パブリック IP なし・セキュリティグループ private-sg
    プライベート IP アドレスをメモしておく

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

  8. 踏み台経由でテスト用 EC2 に接続し、外向き通信を確認する

    まずローカルのターミナルから踏み台のパブリック IP に SSH します。続けて踏み台の中から、テスト用 EC2 のプライベート IP に SSH します(同じキーペアを踏み台にも置いておくか、SSH エージェントフォワードを使います)。

    ローカル → 踏み台 → テスト用サーバー
    # ローカルから踏み台へ(エージェントフォワードを有効にする -A オプション)
    ssh -A -i my-key.pem ec2-user@<踏み台のパブリック IP>
    
    # 踏み台の中から、テスト用サーバーのプライベート IP へ
    ssh ec2-user@<テスト用サーバーのプライベート IP>
    
    # テスト用サーバーの中で、外向き通信を確認する
    sudo dnf update -y

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

    ここで起きていること

    テスト用サーバーは公開アドレスを持たないまま、内側から外への通信だけを NAT ゲートウェイが中継しています。外側からこのサーバーへ新しく接続を始めることはできません。

    Windows でエージェントフォワードを使う場合

    Windows 10/11 に標準搭載の OpenSSH では、ssh-agent サービスを先に有効化しておく必要があります。PowerShell を管理者として開き、次のコマンドを実行してから鍵を登録してください。

    PowerShell(管理者)
    # ssh-agent サービスを有効化して起動する(初回のみ)
    Set-Service ssh-agent -StartupType Automatic
    Start-Service ssh-agent
    
    # 鍵をエージェントに登録する
    ssh-add my-key.pem

    登録できていれば、あとは同じ ssh -A コマンドでエージェントフォワードが使えます。

07 — Pitfalls

つまずきポイント

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

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

「dnf update がタイムアウトする、または止まったまま進まない」

確認したい点がいくつかあります。①NAT ゲートウェイの状態が「Available」になっているか②プライベート用ルートテーブルに 0.0.0.0/0 → NAT ゲートウェイのルートがあり、プライベートサブネットに関連付けられているか③NAT ゲートウェイ自体がパブリックサブネットに置かれ、そのサブネットがインターネットゲートウェイへの経路を持っているか——のいずれかが欠けていることが多いです。

Pitfall 02 — 踏み台経由でテスト用サーバーに SSH できない

「踏み台には入れるのに、その先のサーバーに入れない」

よくある原因は鍵を踏み台側にも渡してしまっているか、SSH エージェントフォワード(-A オプション)を忘れていることです。鍵そのものを踏み台に置くのは避け、エージェントフォワードを使いましょう。また、接続先はプライベート IP アドレスであること(パブリック IP は付いていません)、プライベート用セキュリティグループのソースが踏み台用セキュリティグループになっているかも確認してみてください。

08 — Checklist

完了チェック

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

  • 「NAT ゲートウェイ」一覧で、作成したものの状態が「Available」になっている。
  • その NAT ゲートウェイにElastic IP アドレスが割り当てられている
  • private-rt の「ルート」タブに、送信先 0.0.0.0/0 ・ターゲットが NAT ゲートウェイの行がある。
  • private-rt の「サブネットの関連付け」タブに private-subnet が表示されている。
  • 踏み台サーバーにローカルから SSH でログインできる。
  • 踏み台サーバーから、テスト用サーバーのプライベート IP へ SSH でログインできる。
  • テスト用サーバーの中で実行したパッケージ取得コマンドが、エラーなく完了する。
09 — Think

考えてみよう

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

  1. NAT ゲートウェイとインターネットゲートウェイは、どちらもインターネットへの経路に関わります。「外から内側へ新しい接続を開始できるか」という観点で、両者の違いを説明してみましょう。
    ヒント
    インターネットゲートウェイは設定次第で双方向に使えますが、NAT ゲートウェイは内側が始めた通信の応答だけを返します。「誰が通信を始めたか」という視点で振り返ってみましょう。
  2. 今回は NAT ゲートウェイを 1 つ、1 つのアベイラビリティーゾーンに作りました。これを 2 つのアベイラビリティーゾーンにそれぞれ作る構成にすると、可用性とコストはどう変わるでしょうか。
    ヒント
    単一の NAT ゲートウェイだと、そのアベイラビリティーゾーンに障害が起きると外向き通信全体が止まります。ゾーンごとに用意すると影響範囲を抑えられますが、NAT ゲートウェイと Elastic IP がゾーンの数だけ必要になり、時間課金も増えます。
  3. プライベートサブネットのサーバーに Elastic IP を直接付けて、ルートをインターネットゲートウェイに向ける、という方法でも外への通信はできそうです。なぜ今回はその方法を取らず、NAT ゲートウェイを使ったのでしょうか。
    ヒント
    Elastic IP とインターネットゲートウェイ行きのルートを持たせると、そのサーバーは外から直接到達できる状態になります。「外から保護されたまま、外には出られる」という非対称な状態を作れるかどうかで考えてみましょう。
10 — Clean up

後片づけ

片づけの順番が大切です。NAT ゲートウェイを先に削除しないと、時間課金が止まりません。次の順で進めましょう。

  1. テスト用・踏み台用の EC2 を終了する:2 台とも選んで「インスタンスの状態」→「インスタンスを終了」。
  2. NAT ゲートウェイを削除する:my-nat-gw を選び「アクション」→「NAT ゲートウェイの削除」。削除完了まで数分かかります。
  3. Elastic IP アドレスの関連付けを解放する:NAT ゲートウェイの削除後、使われなくなった Elastic IP を「アクション」→「Elastic IP アドレスの解放」。
  4. ルートテーブルの関連付けを外し、削除する:private-rt の関連付けを解除してから削除(パブリック側で作成したルートテーブルも、このハンズオン専用に作った場合は同様に削除)。
  5. インターネットゲートウェイをデタッチして削除する:VPC からデタッチしたあとに削除。
  6. サブネットと VPC を削除する(このハンズオン用に作った場合):public-subnet / private-subnet を削除し、最後に VPC を削除。
Caution — Elastic IP の解放忘れに注意

NAT ゲートウェイを消しても、Elastic IP はそのままでは消えない

Elastic IP アドレスは、NAT ゲートウェイなどにアタッチされている間は無料ですが、使っていないのに保持したままだと課金される場合があります。NAT ゲートウェイを削除したあとは、忘れずに Elastic IP を確認し、不要であれば解放してください。デフォルト VPC やそのサブネットは削除しないようにしましょう。

コストに関する注意: このハンズオンで最も料金が大きいのは NAT ゲートウェイです。起動している時間に対する料金と、処理したデータ量に対する料金の両方が発生します。Elastic IP アドレスは NAT ゲートウェイなどにアタッチされている間は無料ですが、未使用のまま保持すると課金されることがあります。EC2 インスタンスは 2 台分(無料利用枠対象タイプなら最小限に抑えられます)の料金がかかります。VPC・サブネット・ルートテーブル・インターネットゲートウェイ・セキュリティグループ自体には料金はかかりません。使い終えたら、上の「後片づけ」を参考にNAT ゲートウェイと Elastic IP を必ず整理しましょう。最新の料金は AWS の公式料金ページで確認してください。