概要
VPC 上にリソースを配置したら、次に考えるべきはアクセス制御です。誰がどのリソースに、どのポートで通信できるのかを正しく制限しないと、本来公開すべきでないサーバーがインターネットからアクセスできてしまうことがあります。
Amazon VPC には、トラフィックを制御するための仕組みが 2 つ用意されています。EC2 インスタンスなどのリソース単位で動作する「セキュリティグループ」と、サブネット単位で動作する「ネットワーク ACL(Network ACL、NACL)」です。この 2 つは似ているようで、適用される単位や動作の仕方が大きく異なります。
本記事では、セキュリティグループとネットワーク ACL の違いを理解し、実際にカスタムセキュリティグループとカスタムネットワーク ACL を作成して、それぞれの設定箇所と挙動の違いを体験します。

この記事のメリット
- セキュリティグループとネットワーク ACL の役割と適用単位の違いを理解できる
- ステートフルとステートレスの違い、それがルール設計に与える影響を把握できる
- デフォルトの挙動(デフォルトセキュリティグループ・デフォルト NACL)を理解できる
- カスタムセキュリティグループとカスタムネットワーク ACL を作成・設定する手順を習得できる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

クラウドおさる
クラウドおさるはじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
セキュリティグループとは



とひさん、VPC でアクセス制御をするには「セキュリティグループ」を使うって聞いたんですけど、これってどういうものなんですか?
セキュリティグループは、EC2 インスタンスなどのリソースに対する仮想的なファイアウォールだよ。正確には、リソースに付いている ENI(Elastic Network Interface、ネットワークインターフェイス)単位で動作するんだ。インバウンド(入ってくる通信)とアウトバウンド(出ていく通信)のそれぞれにルールを設定して、どの通信を許可するかを決めるんだよ。



ルールっていうのは、具体的にどんな項目を設定するんですか?
セキュリティグループのルールは、プロトコル・ポート範囲・送信元(または送信先)の組み合わせで構成されるよ。たとえば「TCP の 22 番ポートを、自分の IP アドレスからだけ許可する」みたいに設定するんだ。送信元には IP アドレスの範囲(CIDR)だけじゃなく、別のセキュリティグループ ID を指定することもできるんだよ。



セキュリティグループ ID を指定できるんですね!「このセキュリティグループを持っているインスタンスからの通信を許可」みたいに書けるってことですか?
その通り!いいところに気づいたね。IP アドレスを直接書くより柔軟になるから、よく使うパターンだよ。それと、もう 1 つ大事な特徴があるんだ。セキュリティグループには 許可ルール(Allow)しか書けない ということ。「これを拒否する」というルールは作れないんだ。明示的に許可していない通信は、すべて暗黙的に拒否される、と考えるとわかりやすいかな。



許可するものだけを書いていく、というスタイルなんですね。
そう。そしてもう 1 つ覚えておきたいのが、セキュリティグループは ステートフル だということ。
ステートフルという特徴



ステートフル…?なんだか難しそうな言葉ですね。
大丈夫、難しくないよ。ステートフルっていうのは「通信の状態を覚えている」という意味なんだ。たとえば、インスタンスからインターネットにリクエストを送ったとするよね。そのリクエストに対する応答(レスポンス)は、インバウンドルールに許可がなくても自動的にインスタンスに戻ってこられるんだ。



あ、行きの通信を許可していれば、帰りの通信は自動的に通してくれるってことですか!
まさにそういうこと。逆も同じで、インバウンドで許可した通信への応答は、アウトバウンドルールに関係なくインスタンスから出ていけるんだ。だから、セキュリティグループでは「行き」のルールだけ考えればよくて、「帰り」の通信を意識する必要がないんだよ。これがステートフルの便利なところだね。



設定がシンプルになりますね!
ネットワーク ACL とは



ところで、もう 1 つ「ネットワーク ACL」っていうのもあるって聞きました。これはセキュリティグループとどう違うんですか?
ネットワーク ACL は、サブネット単位 で動作するファイアウォールだよ。VPC 内の各サブネットには必ず 1 つのネットワーク ACL が関連付けられていて、そのサブネットを出入りするトラフィックをフィルタリングするんだ。セキュリティグループがリソース単位なのに対して、ネットワーク ACL はもっと広い「サブネットの境界」で効くイメージだね。



なるほど、効く場所が違うんですね。ルールの書き方も違うんですか?
いくつか違いがあるよ。まず、ネットワーク ACL では 許可ルールと拒否ルールの両方 が書けるんだ。「特定の IP アドレスからの通信だけ拒否する」みたいなブラックリスト的な設定ができるのは、セキュリティグループにはない特徴だね。



拒否も書けるんですね。じゃあルールの評価はどうやって決まるんですか?
ネットワーク ACL の各ルールには ルール番号 が付いていて、番号の小さいものから順に評価されるんだ。トラフィックがあるルールに一致したら、その時点でそのルールが適用されて、それ以降のルールは評価されないんだよ。だから番号の付け方が重要なんだ。



上から順に見ていって、最初に当たったルールで決まるんですね。セキュリティグループとはここも違うんですか?
そう、そこが大きな違いだね。セキュリティグループは すべてのルールを評価 して、どれか 1 つでも許可ルールに一致すれば通信が許可される。一方ネットワーク ACL は 番号順に評価して最初に一致したルールで打ち切る。同じ「ルール」でも動き方がまったく違うんだよ。
ステートレスという特徴



ネットワーク ACL もステートフルなんですか?
いや、ここが重要なんだけど、ネットワーク ACL は ステートレス なんだ。つまり、通信の状態を覚えていない。インバウンドで許可した通信でも、その応答(帰りの通信)は自動的には許可されないんだよ。



えっ、じゃあ帰りの通信のルールも自分で書かないといけないんですか…?
そういうこと。インバウンドルールとアウトバウンドルールの両方を、行きと帰りでセットで考える必要があるんだ。ここで関係してくるのが「エフェメラルポート」だよ。



エフェメラルポート…また新しい言葉ですね。
エフェメラルポート(一時ポート)は、クライアントが通信を始めるときに一時的に使う送信元ポートのことなんだ。たとえば Web サーバーの 80 番ポートにアクセスするとき、クライアント側は OS が割り当てた高い番号のポートを使う。サーバーからの応答は、その高い番号のポート宛てに返ってくるんだ。
使われるポート範囲は OS や仕組みによって違うんだけど、まとめるとこんな感じだよ。
| クライアント | エフェメラルポート範囲 |
|---|---|
| Linux カーネル(Amazon Linux 含む) | 32768〜61000 |
| Windows Server 2008 以降 | 49152〜65535 |
| NAT ゲートウェイ | 1024〜65535 |
| Elastic Load Balancing / AWS Lambda | 1024〜65535 |
公開サーバーのようにいろいろなクライアントが通信してくる場合は、幅広く 1024〜65535 を開けておくのが一般的だよ。ネットワーク ACL を使うときは、この戻り通信用のポートをアウトバウンド(またはインバウンド)に許可し忘れると、通信がうまくいかなくなるから注意が必要だね。


デフォルトの挙動



セキュリティグループやネットワーク ACL って、最初から何か設定されているんですか?
いい質問だね。それぞれデフォルトの挙動があるんだ。まずセキュリティグループから。新しくセキュリティグループを作ると、インバウンドルールは空っぽ で、何も通信が入ってこられない状態になるんだ。一方 アウトバウンドルールには「すべての通信を許可」が 1 つ入っている。だから作ったばかりのセキュリティグループは「出ていくのは自由、入ってくるのは全部拒否」という状態なんだよ。



なるほど、必要なインバウンドルールを自分で足していくんですね。ネットワーク ACL はどうですか?
ネットワーク ACL は「デフォルトネットワーク ACL」と「カスタムネットワーク ACL」で挙動が違うんだ。VPC を作ると自動的に作られる デフォルトネットワーク ACL は、インバウンド・アウトバウンドともにすべての通信を許可 している。だから何も設定しなくても通信は通るんだよ。
一方、自分で新しく作る カスタムネットワーク ACL は、最初はすべての通信を拒否 している。インバウンドもアウトバウンドも、必要なルールを自分で追加するまで通信は一切通らないんだ。



カスタムを作ってサブネットに付けると、いきなり全部止まっちゃうってことですか…?
そうなんだ。だからカスタムネットワーク ACL を使うときは、必要な許可ルールをちゃんと追加してから本番に適用しないと、通信が止まってしまうから気をつけてね。ここまでの違いを表にまとめるとこうなるよ。
| 観点 | セキュリティグループ | ネットワーク ACL |
|---|---|---|
| 適用単位 | ENI(インスタンス)単位 | サブネット単位 |
| ルールの種類 | 許可ルールのみ | 許可ルール + 拒否ルール |
| ルールの評価 | すべてのルールを評価 | ルール番号の昇順で評価し、最初に一致したルールを適用 |
| 状態の保持 | ステートフル(戻り通信は自動許可) | ステートレス(戻り通信のルールも必要) |
| デフォルトの挙動 | インバウンドは全拒否、アウトバウンドは全許可 | デフォルト NACL は全許可、カスタム NACL は全拒否 |



2 つの違いがすっきり整理できました!どちらか一方だけ使えばいいんですか?
実は両方が同時に効くんだ。インターネットから来た通信は、まずサブネットの境界でネットワーク ACL のチェックを受けて、そのあとインスタンスの手前でセキュリティグループのチェックを受ける。2 段階のフィルターになっているイメージだね。普段の細かいアクセス制御はセキュリティグループで行って、ネットワーク ACL はサブネット全体に効かせたい大まかなルールや、特定 IP のブロックといった用途で使うのが一般的だよ。



役割分担があるんですね。実際に作って試してみたいです!
実践
セキュリティグループとネットワーク ACL を実際に作成し、それぞれの設定箇所と挙動の違いを確認します。
前提条件
- リージョン:
ap-northeast-1(東京) - IAM ユーザーまたはロールに VPC・EC2 関連リソースの操作権限があること
- 以下のリソースが作成済みであること
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| VPC | sgnacl-vpc | 仮想ネットワーク(CIDR: 10.0.0.0/16) |
| パブリックサブネット | sgnacl-public-subnet | EC2 を配置するサブネット(10.0.1.0/24、AZ: ap-northeast-1a) |
| インターネットゲートウェイ | sgnacl-igw | VPC とインターネットの接続 |
| ルートテーブル | sgnacl-public-rt | 0.0.0.0/0 → IGW のルートを持つ |
| EC2 インスタンス | sgnacl-web-server | httpd が起動済みの Web サーバー(Amazon Linux 2023、t3.micro) |
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| セキュリティグループ | sgnacl-web-sg | Web サーバー用のカスタムセキュリティグループ |
| ネットワーク ACL | sgnacl-custom-nacl | パブリックサブネット用のカスタムネットワーク ACL |
ステップ1: カスタムセキュリティグループを作成する
- AWS マネジメントコンソールにログインし、リージョンが
ap-northeast-1(東京)であることを確認します - 上部の検索バーに
VPCと入力し、表示された「VPC」を選択します - 左側ナビゲーションの「セキュリティ」→「セキュリティグループ」を選択し、「セキュリティグループを作成」をクリックします
- 以下の内容を入力します
- セキュリティグループ名:
sgnacl-web-sg - 説明:
Security group for web server - VPC:
sgnacl-vpcを選択


ステップ2: インバウンドルールを設定する
- 同じ画面の「インバウンドルール」セクションで「ルールを追加」をクリックし、以下を入力します
- タイプ:
HTTP(プロトコルTCP、ポート範囲80が自動入力されます) - ソース:
任意の場所 - IPv4(0.0.0.0/0) - 説明:
HTTP access from anywhere - もう一度「ルールを追加」をクリックし、以下を入力します
- タイプ:
SSH(プロトコルTCP、ポート範囲22が自動入力されます) - ソース:
マイ IP(自分のグローバル IP アドレスが自動入力されます) - 説明:
SSH access from my IP


- 「アウトバウンドルール」セクションはデフォルトの「すべてのトラフィックを許可」のままにします
- ページ下部の「セキュリティグループを作成」をクリックします
- セキュリティグループが作成され、セキュリティグループ ID が表示されることを確認します


ステップ3: セキュリティグループを EC2 インスタンスに関連付ける
- 上部の検索バーに
EC2と入力し、表示された「EC2」を選択します - 左側ナビゲーションの「インスタンス」を選択し、
sgnacl-web-serverにチェックを入れます - 「アクション」→「セキュリティ」→「セキュリティグループを変更」を選択します
- 「関連付けられたセキュリティグループ」で
sgnacl-web-sgを検索して「セキュリティグループを追加」をクリックします - 元から関連付けられていたデフォルトのセキュリティグループは「削除」して、
sgnacl-web-sgのみが関連付けられた状態にします - 「保存」をクリックします
- インスタンスの詳細画面の「セキュリティ」タブで、
sgnacl-web-sgが関連付けられていることを確認します
ステップ4: 動作を確認する
sgnacl-web-serverのパブリック IPv4 アドレスをコピーします- ブラウザで
http://<パブリック IPv4 アドレス>にアクセスします - httpd が返す Web ページが表示されることを確認します
この時点では、セキュリティグループのインバウンドルールで HTTP(80 番)を許可しているため、インターネットからアクセスできます。
ステップ5: カスタムネットワーク ACL を作成する
- VPC コンソールに戻り、左側ナビゲーションの「セキュリティ」→「ネットワーク ACL」を選択します
- 「ネットワーク ACL を作成」をクリックし、以下の内容を入力します
- 名前:
sgnacl-custom-nacl - VPC:
sgnacl-vpcを選択 - 「ネットワーク ACL を作成」をクリックします
- 作成した
sgnacl-custom-naclを選択し、「インバウンドルール」タブを確認します - ルール番号
*の「すべてのトラフィックを拒否」のみが存在し、許可ルールが 1 つもないことを確認します


カスタムネットワーク ACL は、作成直後はすべてのトラフィックを拒否する状態です。
ステップ6: インバウンドルールを設定する
sgnacl-custom-naclの「インバウンドルール」タブで「インバウンドルールを編集」をクリックします- 「新しいルールを追加」をクリックし、HTTP 用のルールを入力します
- ルール番号:
100 - タイプ:
HTTP (80) - ソース:
0.0.0.0/0 - 許可/拒否:
許可 - もう一度「新しいルールを追加」をクリックし、SSH 用のルールを入力します
- ルール番号:
110 - タイプ:
SSH (22) - ソース:
0.0.0.0/0 - 許可/拒否:
許可 - さらに「新しいルールを追加」をクリックし、戻り通信用のエフェメラルポートのルールを入力します
- ルール番号:
120 - タイプ:
カスタム TCP - ポート範囲:
1024-65535 - ソース:
0.0.0.0/0 - 許可/拒否:
許可


- 「変更を保存」をクリックします
ネットワーク ACL はステートレスのため、アウトバウンドで送り出した通信の戻り(インバウンド方向)も、エフェメラルポートとして明示的に許可する必要があります。
ステップ7: アウトバウンドルールを設定する
sgnacl-custom-naclの「アウトバウンドルール」タブで「アウトバウンドルールを編集」をクリックします- 「新しいルールを追加」をクリックし、HTTP 応答などの戻り通信用ルールを入力します
- ルール番号:
100 - タイプ:
カスタム TCP - ポート範囲:
1024-65535 - 送信先:
0.0.0.0/0 - 許可/拒否:
許可 - 「変更を保存」をクリックします


クライアントからの HTTP リクエストに対する Web サーバーの応答は、クライアントのエフェメラルポート宛てに送られます。そのため、アウトバウンドで 1024-65535 を許可しておく必要があります。
ステップ8: ネットワーク ACL をサブネットに関連付けて挙動を確認する
sgnacl-custom-naclを選択し、「サブネットの関連付け」タブを選択します- 「サブネットの関連付けを編集」をクリックします
sgnacl-public-subnetにチェックを入れます- 「変更を保存」をクリックします
- 再度ブラウザで
http://<パブリック IPv4 アドレス>にアクセスし、Web ページが引き続き表示されることを確認します
ここまでで、サブネット境界(ネットワーク ACL)とインスタンス(セキュリティグループ)の 2 層でトラフィックが許可され、通信が成立していることが確認できます。セキュリティグループはインスタンスの「セキュリティ」タブ、ネットワーク ACL はサブネットの「ネットワーク ACL」タブから、それぞれ設定箇所が分かれていることも合わせて確認できます。
まとめ
- セキュリティグループは ENI(インスタンス)単位、ネットワーク ACL はサブネット単位で動作するファイアウォールである
- セキュリティグループは許可ルールのみで、すべてのルールが評価される。ネットワーク ACL は許可・拒否ルールを持ち、ルール番号の昇順で評価して最初に一致したルールが適用される
- セキュリティグループはステートフルで戻り通信が自動的に許可されるが、ネットワーク ACL はステートレスのため戻り通信のルール(エフェメラルポート)も明示的に設定する必要がある
- デフォルトセキュリティグループはインバウンド全拒否・アウトバウンド全許可、デフォルトネットワーク ACL は全許可、カスタムネットワーク ACL は全拒否で始まる
- 2 つは同時に効くため、細かなアクセス制御はセキュリティグループ、サブネット全体への大まかな制御や特定 IP のブロックはネットワーク ACL という使い分けが基本となる
参照先
- セキュリティグループを使用して AWS リソースへのトラフィックを制御する
- セキュリティグループルール
- ネットワーク ACL を使用してサブネットへのトラフィックを制御する
- ネットワーク ACL のルール
- デフォルトのネットワーク ACL
- カスタムネットワーク ACL とエフェメラルポート












