※本記事にはアフィリエイト広告が含まれます。
AWSのセキュリティグループ(SG)とネットワークACL(NACL)の違いは、AWS認定の学習で必ず出てくる。「SGはインスタンス単位でステートフル、NACLはサブネット単位でステートレス」と覚えている人は多いはずだ。
ただ、暗記だけだと「ステートレスだと、具体的にどのポートを追加で許可すればいいのか」という疑問が残る。NACLを触ってみたら戻りの通信が通らない、という状況はたいていここでつまずいている。
この記事では、Amazon VPCの公式ドキュメントをもとに、両者の違いを「戻りの通信」と「エフェメラルポートの範囲」から整理する。内容は確認日(2026-10-15)時点の公式ドキュメントの記述に基づく。
結論:基本はセキュリティグループ、NACLはサブネット単位の補助。違いの本質は「戻りの通信を自動で通すか」
公式ドキュメントは、VPCのネットワークアクセスの制御にはセキュリティグループを主な仕組み(primary mechanism)として使い、必要な場合にネットワークACLでステートレスで粗い(stateless, coarse-grain)制御を加える、という考え方を示している。
同じページでは、SGのほうが用途が広い理由として、ステートフルなパケットフィルタリングができることと、他のセキュリティグループを参照するルールを作れることを挙げている。NACLは「特定の通信を拒否する」補助的な制御や、サブネットのガードレールとして有効で、正しいSGを付けずにインスタンスが起動された場合の多層防御にもなる、とされている。
つまり、まずSGで必要な通信だけを許可し、サブネット全体で止めたい通信があるときにNACLを足す、という順番で考えるとよい。両者の違いの中で実務の設定に一番効いてくるのは、「戻りの通信」を自動で通すかどうかだ。
比較表:動作レベル・適用範囲・ルールの種類・評価方法・戻りの通信
公式ドキュメントの「Compare security groups and network ACLs」の表を日本語で整理すると次のとおり。
| 項目 | セキュリティグループ | ネットワークACL |
|---|---|---|
| 動作レベル | インスタンスレベル | サブネットレベル |
| 適用範囲 | そのSGに関連付けたすべてのインスタンス | 関連付けたサブネット内のすべてのインスタンス |
| ルールの種類 | 許可ルールのみ | 許可ルールと拒否ルール |
| 評価方法 | すべてのルールを評価してから許可するか決める | 番号の小さい順に評価し、一致するルールが見つかった時点で決まる |
| 戻りの通信 | 自動で許可(ステートフル) | 明示的に許可が必要(ステートレス) |
表だけでは見えにくい細かい仕様も押さえておく。
- NACLには、ルール番号がアスタリスク(*)の既定のインバウンドルールとアウトバウンドルールがある。他のどのルールにも一致しないパケットはこのルールで拒否される。*のルールは削除できない
- SGは、作成した直後はインバウンドルールがない(インバウンドは何も通らない)。一方、アウトバウンドにはすべての通信を許可するルールが最初から入っている
- 1つのリソースに複数のSGを関連付けると、それぞれのルールが集約されて1つのルールセットとして評価される
SGのステートフルについて、日本語版のドキュメントは「インスタンスからリクエストを送信した場合、そのリクエストのレスポンストラフィックは、インバウンドセキュリティグループのルールに関係なく、インスタンスに到達が許可されます」「許可されたインバウンドトラフィックへのレスポンスは、アウトバウンドルールに関係なく、インスタンスを離れることができます」と説明している。
NACLにはこの仕組みがない。だからNACLでは、行きの通信を許可するルールを書くたびに、その応答を通すルールを反対方向にも書く必要がある。公式ドキュメントも「追加するすべてのルールについて、応答トラフィックを許可するインバウンドまたはアウトバウンドのルールが必要」としている。
ステートレスだと何が起きるか:エフェメラルポートと方向別のルール
応答の通信は、リクエストを送ったクライアント側の「エフェメラルポート(一時的なポート)」宛てに返ってくる。たとえばブラウザがWebサーバーの443番に接続するとき、送信元のポートは443ではなく、クライアントのOSが選んだ番号になる。Webサーバーからの応答はその番号宛てに返る。
公式ドキュメントでは、エフェメラルポートの範囲はリクエストを始めたクライアントが選び、クライアントのOSによって異なるとされている。挙げられている範囲は次のとおり。
| クライアント | エフェメラルポートの範囲 |
|---|---|
| 多くのLinuxカーネル(Amazon Linuxのカーネルを含む) | 32768-61000 |
| Elastic Load Balancingから出るリクエスト | 1024-65535 |
| Windows Server 2003までのWindows | 1025-5000 |
| Windows Server 2008以降 | 49152-65535 |
| NATゲートウェイ | 1024-65535 |
| AWS Lambda関数 | 1024-65535 |
ここで大事なのは、「誰がリクエストを始めたか」で、エフェメラルポートのルールを書く方向が変わることだ。
| 通信の向き | 行きの通信に必要なルール | 戻りの通信に必要なルール |
|---|---|---|
| 外部のクライアント → サブネット内のWebサーバー | インバウンド:80や443など、サーバーの待ち受けポート | アウトバウンド:クライアントのエフェメラルポートの範囲 |
| サブネット内のインスタンス → 外部(API呼び出し・パッケージ取得など) | アウトバウンド:接続先のポート(443など) | インバウンド:インスタンス自身のOSのエフェメラルポートの範囲 |
公式ドキュメントの例では、インターネット上のWindows 10クライアントからVPC内のWebサーバーにリクエストが来る場合、ネットワークACLに49152-65535宛ての通信を許可するアウトバウンドルールが必要だとしている。また、VPC内のインスタンスがリクエストを始める側なら、そのインスタンスのOSのエフェメラルポート宛ての通信を許可するインバウンドルールが必要になる。
同じページのルール例では、エフェメラルポートの範囲として32768-65535を使っている。ただ、上の表のとおりクライアントによって範囲は違う。そのため公式ドキュメントでは、公開しているインスタンスにさまざまなクライアントが接続してくることを考えて、実際には1024-65535を開けてもよい、とされている。
1024-65535のように広く開ける場合は、その範囲の中の悪意のあるポートを拒否するルールを足すことができる。このとき拒否ルールは、広い範囲を開ける許可ルールより前(小さい番号)に置く必要がある。NACLは番号の小さい順に評価して最初に一致したルールで決まるので、許可ルールが先にあると、後ろの拒否ルールまで評価が進まないからだ。
なお、IPv4とIPv6の通信は別々に評価され、IPv4のルールはIPv6の通信には適用されない。VPCにIPv6のCIDRを関連付けている場合は、IPv6用のルールも同じように用意する必要がある。
セキュリティグループの参照:ALB→Web→DBの3層構成
SGが「用途が広い」とされるもう1つの理由が、ルールの送信元・送信先に他のSGのIDを指定できることだ。SGを指定すると、そのSGに関連付けたインスタンスのネットワークインターフェイスのプライベートIPアドレスとの通信が、指定したプロトコルとポートで許可される。
公式ドキュメントでは、Application Load Balancer・Webサーバー・DBサーバーにそれぞれ別のSGを用意する例が紹介されている。
- ロードバランサーのSG:インターネットからのHTTP・HTTPSを許可(送信元は0.0.0.0/0)
- WebサーバーのSG:ロードバランサーからのHTTP・HTTPSだけを許可(送信元はロードバランサーのSG)
- DBサーバーのSG:Webサーバーからのデータベースへのリクエストを許可(送信元はWebサーバーのSG)
IPアドレスではなくSGで指定しておけば、Webサーバーが増減してIPアドレスが変わっても、DB側のルールを書き換えずに済む。ただし、参照には次の条件と制約がある。
| 項目 | 内容 |
|---|---|
| インバウンドルールで参照できる条件 | SG同士が同じVPCに関連付いている/VPC間にピアリング接続がある/VPC間にTransit Gateway(複数のVPCやオンプレミスのネットワークをつなぐ中継用のハブ)がある、のいずれか |
| アウトバウンドルールで参照できる条件 | SG同士が同じVPCに関連付いている/VPC間にピアリング接続がある、のいずれか(Transit Gatewayは含まれない) |
| 参照先のルール | 参照先のSGのルールは、参照する側のSGに追加されない |
| ミドルボックス経由の制約 | 異なるサブネットのインスタンス間の通信を、ミドルボックスのアプライアンス(通信を検査するセキュリティアプライアンスなど、ルーティングの途中に挟む機器)経由でルーティングする場合、相手のSGを送信元に指定しても通信は通らない。相手のプライベートIPかサブネットのCIDRを指定する必要がある |
「参照先のルールは追加されない」は誤解しやすい点だ。WebサーバーのSGがロードバランサーのSGを参照しても、ロードバランサーのSGに書いた「0.0.0.0/0から443を許可」がWebサーバーに引き継がれるわけではない。あくまで「そのSGが付いたインスタンスからの通信」を許可するだけである。
通信できないときの確認順
公式ドキュメントの図では、インターネットゲートウェイからの通信はルートテーブルによってサブネットへルーティングされ、サブネットのNACLがサブネットに入る通信を、インスタンスのSGがインスタンスに入る通信を制御する、という層の順番で説明されている。
この層の順番に沿って、外側から確認していくと切り分けやすい。
- ルートテーブル:送信先へのルートがあるか(インターネットゲートウェイ・NATゲートウェイなど)
- NACL:インバウンドとアウトバウンドの両方に、行きのポートと戻りのエフェメラルポートの範囲が許可されているか。許可より前の番号に拒否ルールがないか
- SG:インバウンドに必要なポートと送信元があるか。アウトバウンドの既定ルールを消していないか
ロードバランサーを使っている場合は、もう1つ注意がある。公式ドキュメントでは、バックエンドのインスタンスがあるサブネットのNACLに、送信元が0.0.0.0/0またはそのサブネットのCIDRのすべての通信を拒否するルールを追加すると、ロードバランサーがインスタンスのヘルスチェックをできなくなる、とされている。前述の表のとおり、Elastic Load Balancingから出るリクエストのエフェメラルポートは1024-65535なので、バックエンド側のNACLのアウトバウンドでもこの範囲を考える必要がある。ロードバランサーの種類ごとの推奨ルールは、ELBの各ドキュメントで案内されている。
設定を目で追っても原因が分からないときは、Reachability Analyzerが使える。公式ドキュメントでは、VPC内の2つのリソース間の到達性を分析する静的な設定分析ツールで、到達できる場合は経路をホップごとに示し、到達できない場合は遮断しているコンポーネントを特定する、と説明されている。NACLのルールの不足や設定ミスも特定できる例として挙げられている。
まとめ
最後に、使い分けを早見表にまとめる(公式ドキュメントの推奨をもとにした整理)。
| やりたいこと | 使うもの |
|---|---|
| インスタンスごとに必要な通信だけを許可する | セキュリティグループ |
| ALB→Web→DBのように層ごとに送信元を絞る | セキュリティグループ(SG参照) |
| 特定のIPアドレスやポートを明示的に拒否する | ネットワークACL(SGは拒否ルールを書けない) |
| サブネット全体のガードレール・多層防御 | ネットワークACL |
「ステートフル/ステートレス」は、言い換えると「戻りの通信を自分で書く必要があるかどうか」だ。NACLを使うときは、エフェメラルポートの範囲がクライアントによって違うこと、そして誰がリクエストを始めるかで書く方向が変わることを意識しておくと、通信できない原因を絞り込みやすくなる。
SGとNACLの違いは、AWS認定のアソシエイト試験でもよく問われる範囲だ。私はアソシエイトの3資格を同日に受験して合格しており、資格ごとの勉強の順番や進め方はAWS認定アソシエイト3冠の完全攻略ガイドに、同日受験したときの話はAWS三冠を同日受験して全合格した勉強法と当日の話にまとめている。
VPCのサブネット・ルーティング・セキュリティグループを図解つきで体系的に学びたい人は、AWSのネットワークを扱った技術書を1冊手元に置いておくと、公式ドキュメントを読むときの土台になる。

