← ハンズオン一覧に戻る

AWS Hands-on / Networking

セキュリティグループの外側に、もう1つの壁を作る

VPC には、サーバー単位の「セキュリティグループ」以外にも、サブネット単位で通信を制御する「ネットワークACL」というもう1つの壁があります。セキュリティグループでは許可されているはずの通信が、ネットワークACLの設定だけでブロックされる様子を実際に作って体験します。

● Lv.2 基本的なリソースを作れる人 ⏱ 所要 40〜60 分 コンソールのみで完結
01 — Prerequisites

はじめる前に

  • 必須AWS アカウントを持っていること
  • 必須マネジメントコンソールにサインインできること
  • 必須VPC・サブネット・セキュリティグループを使って EC2 に SSH 接続した経験
  • あると良いパブリック/プライベートサブネットの違いについての理解

※ このハンズオンは すべてコンソールだけで完結します。ローカル端末からの SSH 接続確認のみ行います。

02 — References

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

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

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

03 — Background

背景・シナリオ

VPC の通信制御は、サーバー単位の「セキュリティグループ」だけで決まると思われがちです。しかし VPC には、サブネット単位で通信を制御する「ネットワークACL」というもう1つの壁があります。最初から使っている「デフォルトのネットワークACL」はすべての通信を許可しているため、多くの人はその存在を意識せずに過ごしています。

ところが、自分でカスタムのネットワークACLを作ってサブネットに関連付けると、様子が変わります。新しく作ったカスタムネットワークACLは、ルールを何も追加していない時点では、すべての通信を暗黙的に拒否するという初期状態を持っています。そのため、セキュリティグループでは許可されているはずのSSH通信が、ネットワークACLの側で止まってしまう、ということが起こります。今回はこの「2段階の壁」を実際に作り、片方が許可していても、もう片方が拒否していれば通信できない、という様子を体験します。

セキュリティグループとネットワークACL、両方設定する必要があるの?

多くの場合はセキュリティグループだけで十分です。ネットワークACLは、サブネット単位でまとめて通信を制限したい場合や、特定のIPアドレスを明示的に拒否したい場合などに使います。両方を設定すると、両方の条件を満たした通信だけが許可される、二重の壁になります。

セキュリティグループは「ステートフル」、ネットワークACLは「ステートレス」と言われるのはどういうこと?

セキュリティグループは、リクエストを許可すると、その応答の通信は自動的に許可されます(ステートフル)。一方ネットワークACLは、リクエストを許可しても、応答の通信は別のルールとして許可しないと通信が成立しません(ステートレス)。今回、インバウンドの許可ルールだけでは接続が戻らない、という体験もします。

Goal

サブネットに関連付けるネットワークACLを「デフォルト(すべて許可)」から「自作したカスタムACL(最初は何も許可していない)」に切り替えると、セキュリティグループでは許可されているSSH通信が拒否されることを確認し、インバウンド・アウトバウンドそれぞれに正しいルールを追加して、再びSSH接続できる状態に戻す。

04 — Architecture

つくる構成

同じセキュリティグループ・同じEC2のまま、サブネットに関連付けるネットワークACLだけを切り替えて、SSH接続できるかどうかを比較します。

ケース1 — デフォルトのネットワークACL

すべての通信を許可

💻 自分のPC 🔓 セキュリティグループ(許可) 🔓 デフォルトNACL(許可) 🖥️ EC2
SSH接続に成功する
ケース2 — カスタムNACL(ルール未追加)

暗黙的にすべてを拒否

💻 自分のPC 🔓 セキュリティグループ(許可) 🔒 カスタムNACL(拒否) ✕ 🖥️ EC2
SSH接続が失敗する(SGは許可しているのに)

※ セキュリティグループの設定は変更していません。サブネットに関連づくネットワークACLだけを切り替えています。

05 — Requirements

要件

以下の要件を満たし、「つながる」→「つながらない」→「ルールを直してつながる」という変化を確認してください。

No要件
1リージョンは「東京(ap-northeast-1)」を使用する。
2VPC内のサブネットに、SSH(22番、マイIPから)を許可したセキュリティグループを持つ EC2 を1台用意する(例:t3.micro、Amazon Linux 2023)。まず SSH 接続できることを確認する。
3カスタムのネットワークACLを1つ作成し、EC2のあるサブネットに関連付ける。関連付け直後、ルールを何も追加していない状態でSSH接続が失敗することを確認する。
4インバウンドルールにSSH(22番、自分のIPから)の許可を1つ追加する。この時点でもまだ接続できないことを確認する。
5アウトバウンドルールに、エフェメラルポート(例:1024〜65535)の許可を追加し、SSH接続が再び成功することを確認する。
06 — Steps

構築の進め方

「土台を作る」→「ブロックを体験する」→「正しいルールを追加して戻す」という順番で進めます。

  1. フェーズ1 — 土台を作る
  2. マネジメントコンソールにサインインし、リージョンを合わせる

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

  3. SSH接続できるEC2を1台用意する

    EC2コンソールで、名前を自由に決め(例:nacl-demo)、AMIにAmazon Linux 2023、セキュリティグループでSSH(22番)をマイIPから許可して起動します。キーペアも作成しておきます。

  4. SSH接続できることを確認する

    ローカルのターミナル(PowerShellなど)から、作成したキーペアを使ってSSH接続できることを確認します。これが「ケース1」の状態です。

    PowerShell
    ssh -i nacl-demo-key.pem ec2-user@<パブリックIP>
  5. フェーズ2 — ブロックを体験する
  6. カスタムのネットワークACLを作成する

    VPCコンソールの「ネットワークACL」から、「ネットワークACLを作成」を選び、EC2と同じVPCを指定して作成します(名前は自由、例:nacl-demo-custom)。

    作っただけでは「何も許可していない」

    カスタムのネットワークACLは、作成した時点ではインバウンド・アウトバウンドともにルールが1つもなく、暗黙的にすべての通信を拒否する状態になっています。これは初期状態としてそうなる仕様で、設定ミスではありません。

  7. EC2のあるサブネットに関連付ける

    作成したネットワークACLの「サブネットの関連付け」タブから「編集」を選び、EC2が属しているサブネットを選んで関連付けます。

  8. SSH接続が失敗することを確認する

    もう一度同じSSHコマンドを実行します。先ほどまで成功していた接続が、今度は応答がないまま固まる、またはタイムアウトすることを確認します。これが「ケース2」の状態です。

    セキュリティグループは何も変えていない

    セキュリティグループの設定は最初のままです。それでも接続できなくなるのは、サブネットに関連付くネットワークACLの側が、すべての通信を暗黙的に拒否しているためです。

  9. フェーズ3 — ルールを直して戻す
  10. インバウンドにSSHの許可ルールを追加する

    作成したネットワークACLの「インバウンドルール」タブから、SSH(22番)を自分のIPアドレスから許可するルールを1つ追加します(ルール番号は例:100)。

    ルール番号タイプポート送信元許可/拒否
    100SSH22自分のIP/32ALLOW
    *すべてすべて0.0.0.0/0DENY(変更不可)
  11. この時点でもまだ接続できないことを確認する

    もう一度SSHコマンドを実行しますが、まだ失敗するはずです。インバウンドだけ許可しても、応答(戻り)の通信がまだ許可されていないためです。

  12. アウトバウンドにエフェメラルポートの許可ルールを追加する

    「アウトバウンドルール」タブから、TCPのポート範囲1024〜65535(エフェメラルポート、例)を、送信先 0.0.0.0/0 で許可するルールを追加します(ルール番号は例:100)。

    ルール番号タイプポート送信先許可/拒否
    100カスタムTCP1024-655350.0.0.0/0ALLOW
    *すべてすべて0.0.0.0/0DENY(変更不可)
    これがゴール

    もう一度SSHコマンドを実行し、接続が成功すれば、このハンズオンの目的は達成です。インバウンドの許可だけでは戻らず、アウトバウンドの許可も追加してはじめて戻る、という体験がポイントです。

07 — Pitfalls

つまずきポイント

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

Pitfall 01 — 両方のルールを追加してもまだ繋がらない

「インバウンドもアウトバウンドも追加したのに失敗する」

追加したルールのポート番号・プロトコル(TCP)・送信元/送信先のCIDRを見直しましょう。また、セキュリティグループ側のSSH許可ルールが、自分のIPアドレスの変化(再起動などでIPが変わるケース)によって合わなくなっていないかも確認しましょう。

Pitfall 02 — ルール番号の意味がわからない

「番号は何のために設定するのか」

ネットワークACLのルールは、番号が小さいものから順に評価され、最初に一致したルールが適用されます。複数のルールを追加する場合は、後から間に挿入できるよう、10や100刻みで番号を空けておくと管理しやすくなります。

08 — Checklist

完了チェック

要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。次を順に確かめましょう。

  • デフォルトのネットワークACLの時点で、SSH接続が成功していたことを確認済みである。
  • カスタムネットワークACLを関連付けた直後(ルール追加前)は、SSH接続が失敗する。
  • インバウンドのSSH許可ルールだけを追加した時点でも、SSH接続はまだ失敗する。
  • アウトバウンドのエフェメラルポート許可ルールを追加した後、SSH接続が成功する。
  • VPCコンソールのサブネット詳細で、関連付けられているネットワークACLが、自分で作成したものになっている。
09 — Think

考えてみよう

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

  1. インバウンドのSSH許可ルールだけでは接続が戻らず、アウトバウンドのルールも必要だったのはなぜでしょうか。
    ヒント
    ネットワークACLは「ステートレス」、つまり一度許可したリクエストの応答を自動では許可しません。SSHのリクエストとその応答(戻りの通信)が、それぞれ別のルールとして扱われている、という点がヒントです。
  2. セキュリティグループとネットワークACL、本番運用ではどのように使い分けるとよさそうでしょうか。
    ヒント
    セキュリティグループは「サーバーごとの細かい制御」に向いています。ネットワークACLは「サブネット単位でまとめて制限したい場合」や「特定のIPアドレスを明示的に拒否したい場合」に向いています。それぞれの得意な場面を考えてみましょう。
  3. ネットワークACLのルール番号を「10刻み」や「100刻み」で作ることが推奨されているのはなぜでしょうか。
    ヒント
    ルールは番号の小さい順に評価されます。後から新しいルールを「既存のルールの間」に挿入したくなった場合、番号が詰まっていると挿入できる余地がありません。運用中に変更が発生することを考えてみましょう。
10 — Clean up

後片づけ

作成したリソースを順番に削除します。

  1. サブネットの関連付けを戻す:サブネットの「ネットワークACL」をデフォルトのネットワークACLに戻すか、削除前にいったん別のネットワークACLへ関連付け直します。
  2. カスタムネットワークACLを削除する:サブネットの関連付けを外した後、作成したネットワークACLを削除します。
  3. EC2インスタンスを終了する:EC2コンソールで nacl-demo を選び、終了します。
Caution — デフォルトのネットワークACLは削除しない

削除するのは、自分で作成したカスタムネットワークACLだけ

ネットワークACLの一覧には、VPC作成時に自動的に用意される「デフォルトのネットワークACL」も表示されます。これは削除できません(削除しようとしてもエラーになります)が、誤って他のサブネットの関連付けを変更しないよう、対象を名前でよく確認しましょう。

コストに関する注意: ネットワークACLの利用そのものに料金はかかりません。VPC・サブネット・ルートテーブル・セキュリティグループ・ネットワークACL自体も同様に無料です。一方、EC2インスタンスは起動中の時間に応じて課金されます(t3.microなどは無料利用枠の対象になる場合があります)。アタッチされるEBSボリュームにも保存容量に応じた料金がかかります。検証が終わったら、上の「後片づけ」に沿って忘れずに削除しましょう。最新の料金は AWS の公式料金ページで確認してください。